mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 19:51:09 +01:00
Add underscores to private data members (#898)
This is the last PR I plan to have focused on #720
This commit is contained in:
+7
-7
@@ -34,7 +34,7 @@ class ExitingStream {
|
||||
// Indicates that the program is exiting due to a bug in the program, rather
|
||||
// than, e.g., invalid input.
|
||||
ExitingStream& TreatAsBug() {
|
||||
treat_as_bug = true;
|
||||
treat_as_bug_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -45,16 +45,16 @@ class ExitingStream {
|
||||
// Forward output to llvm::errs.
|
||||
template <typename T>
|
||||
ExitingStream& operator<<(const T& message) {
|
||||
if (separator) {
|
||||
if (separator_) {
|
||||
llvm::errs() << ": ";
|
||||
separator = false;
|
||||
separator_ = false;
|
||||
}
|
||||
llvm::errs() << message;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ExitingStream& operator<<(AddSeparator /*unused*/) {
|
||||
separator = true;
|
||||
separator_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ class ExitingStream {
|
||||
[[noreturn]] friend auto operator|(Helper /*unused*/, ExitingStream& rhs) {
|
||||
// Finish with a newline.
|
||||
llvm::errs() << "\n";
|
||||
if (rhs.treat_as_bug) {
|
||||
if (rhs.treat_as_bug_) {
|
||||
std::abort();
|
||||
} else {
|
||||
std::exit(-1);
|
||||
@@ -73,10 +73,10 @@ class ExitingStream {
|
||||
|
||||
private:
|
||||
// Whether a separator should be printed if << is used again.
|
||||
bool separator = false;
|
||||
bool separator_ = false;
|
||||
|
||||
// Whether the program is exiting due to a bug.
|
||||
bool treat_as_bug = false;
|
||||
bool treat_as_bug_ = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
+14
-14
@@ -45,43 +45,43 @@ class IndirectValue {
|
||||
// std::is_constructible give correct answers.
|
||||
|
||||
// Initializes the underlying T object as if by `T()`.
|
||||
IndirectValue() : value(std::make_unique<T>()) {}
|
||||
IndirectValue() : value_(std::make_unique<T>()) {}
|
||||
|
||||
// Initializes the underlying T object as if by `T(std::move(value))`.
|
||||
IndirectValue(T value) : value(std::make_unique<T>(std::move(value))) {}
|
||||
IndirectValue(T value) : value_(std::make_unique<T>(std::move(value))) {}
|
||||
|
||||
// TODO(geoffromer): consider defining implicit conversions from
|
||||
// U and IndirectValue<U>, when U is implicitly convertible to T.
|
||||
|
||||
IndirectValue(const IndirectValue& other)
|
||||
: value(std::make_unique<T>(*other)) {}
|
||||
: value_(std::make_unique<T>(*other)) {}
|
||||
|
||||
IndirectValue(IndirectValue&& other)
|
||||
: value(std::make_unique<T>(std::move(*other))) {}
|
||||
: value_(std::make_unique<T>(std::move(*other))) {}
|
||||
|
||||
auto operator=(const IndirectValue& other) -> IndirectValue& {
|
||||
*value = *other.value;
|
||||
*value_ = *other.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator=(IndirectValue&& other) -> IndirectValue& {
|
||||
*value = std::move(*other.value);
|
||||
*value_ = std::move(*other.value_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator*() -> T& { return *value; }
|
||||
auto operator*() const -> const T& { return *value; }
|
||||
auto operator*() -> T& { return *value_; }
|
||||
auto operator*() const -> const T& { return *value_; }
|
||||
|
||||
auto operator->() -> T* { return value.get(); }
|
||||
auto operator->() const -> const T* { return value.get(); }
|
||||
auto operator->() -> T* { return value_.get(); }
|
||||
auto operator->() const -> const T* { return value_.get(); }
|
||||
|
||||
// Returns the address of the stored value.
|
||||
//
|
||||
// TODO(geoffromer): Consider eliminating this method, which is not
|
||||
// present in comparable types like indirect_value<T> or optional<T>,
|
||||
// once our APIs are less pointer-centric.
|
||||
auto GetPointer() -> T* { return value.get(); }
|
||||
auto GetPointer() const -> const T* { return value.get(); }
|
||||
auto GetPointer() -> T* { return value_.get(); }
|
||||
auto GetPointer() const -> const T* { return value_.get(); }
|
||||
|
||||
private:
|
||||
static_assert(std::is_object_v<T>, "T must be an object type");
|
||||
@@ -91,9 +91,9 @@ class IndirectValue {
|
||||
-> IndirectValue<std::decay_t<decltype(callable())>>;
|
||||
|
||||
template <typename... Args>
|
||||
IndirectValue(std::unique_ptr<T> value) : value(std::move(value)) {}
|
||||
IndirectValue(std::unique_ptr<T> value) : value_(std::move(value)) {}
|
||||
|
||||
const std::unique_ptr<T> value;
|
||||
const std::unique_ptr<T> value_;
|
||||
};
|
||||
|
||||
template <typename Callable>
|
||||
|
||||
@@ -17,9 +17,9 @@ class SourceLocation {
|
||||
public:
|
||||
// The filename should be eternal or arena-allocated to eliminate copies.
|
||||
SourceLocation(const char* filename, int line_num)
|
||||
: filename(filename), line_num(line_num) {}
|
||||
: filename_(filename), line_num_(line_num) {}
|
||||
SourceLocation(Nonnull<const std::string*> filename, int line_num)
|
||||
: filename(filename->c_str()), line_num(line_num) {}
|
||||
: filename_(filename->c_str()), line_num_(line_num) {}
|
||||
|
||||
SourceLocation(const SourceLocation&) = default;
|
||||
SourceLocation(SourceLocation&&) = default;
|
||||
@@ -27,17 +27,17 @@ class SourceLocation {
|
||||
auto operator=(SourceLocation&&) -> SourceLocation& = default;
|
||||
|
||||
bool operator==(SourceLocation other) const {
|
||||
return filename == other.filename && line_num == other.line_num;
|
||||
return filename_ == other.filename_ && line_num_ == other.line_num_;
|
||||
}
|
||||
|
||||
void Print(llvm::raw_ostream& out) const {
|
||||
out << filename << ":" << line_num;
|
||||
out << filename_ << ":" << line_num_;
|
||||
}
|
||||
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
|
||||
|
||||
private:
|
||||
std::string_view filename;
|
||||
int line_num;
|
||||
std::string_view filename_;
|
||||
int line_num_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -20,7 +20,7 @@ class Arena {
|
||||
auto smart_ptr =
|
||||
std::make_unique<ArenaEntryTyped<T>>(std::forward<Args>(args)...);
|
||||
Nonnull<T*> ptr = smart_ptr->Instance();
|
||||
arena.push_back(std::move(smart_ptr));
|
||||
arena_.push_back(std::move(smart_ptr));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -38,16 +38,16 @@ class Arena {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit ArenaEntryTyped(Args&&... args)
|
||||
: instance(std::forward<Args>(args)...) {}
|
||||
: instance_(std::forward<Args>(args)...) {}
|
||||
|
||||
auto Instance() -> Nonnull<T*> { return Nonnull<T*>(&instance); }
|
||||
auto Instance() -> Nonnull<T*> { return Nonnull<T*>(&instance_); }
|
||||
|
||||
private:
|
||||
T instance;
|
||||
T instance_;
|
||||
};
|
||||
|
||||
// Manages allocations in an arena for destruction at shutdown.
|
||||
std::vector<std::unique_ptr<ArenaEntry>> arena;
|
||||
std::vector<std::unique_ptr<ArenaEntry>> arena_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -27,7 +27,7 @@ class Address {
|
||||
|
||||
// Returns true if the two addresses refer to the same memory location.
|
||||
friend auto operator==(const Address& lhs, const Address& rhs) -> bool {
|
||||
return lhs.index == rhs.index;
|
||||
return lhs.index_ == rhs.index_;
|
||||
}
|
||||
|
||||
friend auto operator!=(const Address& lhs, const Address& rhs) -> bool {
|
||||
@@ -40,7 +40,7 @@ class Address {
|
||||
// the whole memory allocation, and an optional FieldPath specifying a
|
||||
// particular field within that allocation.
|
||||
void Print(llvm::raw_ostream& out) const {
|
||||
out << "Address(" << index << ")" << field_path;
|
||||
out << "Address(" << index_ << ")" << field_path_;
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
|
||||
@@ -49,7 +49,7 @@ class Address {
|
||||
// `field_name`, this method returns the address of that field.
|
||||
auto SubobjectAddress(std::string field_name) const -> Address {
|
||||
Address result = *this;
|
||||
result.field_path.Append(std::move(field_name));
|
||||
result.field_path_.Append(std::move(field_name));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ class Address {
|
||||
// details of the Heap.
|
||||
friend class Heap;
|
||||
|
||||
explicit Address(uint64_t index) : index(index) {}
|
||||
explicit Address(uint64_t index) : index_(index) {}
|
||||
|
||||
uint64_t index;
|
||||
FieldPath field_path;
|
||||
uint64_t index_;
|
||||
FieldPath field_path_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -44,10 +44,10 @@ class Dictionary {
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
explicit Iterator(std::optional<Nonnull<Node*>> x) : p(x) {}
|
||||
Iterator(const Iterator& iter) : p(iter.p) {}
|
||||
explicit Iterator(std::optional<Nonnull<Node*>> x) : p_(x) {}
|
||||
Iterator(const Iterator& iter) : p_(iter.p_) {}
|
||||
auto operator++() -> Iterator& {
|
||||
p = (*p)->next;
|
||||
p_ = (*p_)->next;
|
||||
return *this;
|
||||
}
|
||||
auto operator++(int) -> Iterator {
|
||||
@@ -55,17 +55,17 @@ class Dictionary {
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
auto operator==(const Iterator& rhs) const -> bool { return p == rhs.p; }
|
||||
auto operator!=(const Iterator& rhs) const -> bool { return p != rhs.p; }
|
||||
auto operator*() -> const value_type& { return (*p)->curr; }
|
||||
auto operator->() -> const value_type* { return &(*p)->curr; }
|
||||
auto operator==(const Iterator& rhs) const -> bool { return p_ == rhs.p_; }
|
||||
auto operator!=(const Iterator& rhs) const -> bool { return p_ != rhs.p_; }
|
||||
auto operator*() -> const value_type& { return (*p_)->curr; }
|
||||
auto operator->() -> const value_type* { return &(*p_)->curr; }
|
||||
|
||||
private:
|
||||
std::optional<Nonnull<Node*>> p;
|
||||
std::optional<Nonnull<Node*>> p_;
|
||||
};
|
||||
|
||||
// Create an empty dictionary.
|
||||
explicit Dictionary(Nonnull<Arena*> arena) : arena(arena) {}
|
||||
explicit Dictionary(Nonnull<Arena*> arena) : arena_(arena) {}
|
||||
|
||||
// Return the value associated with the given key.
|
||||
// Time complexity: O(n) where n is the number of times
|
||||
@@ -82,21 +82,21 @@ class Dictionary {
|
||||
// Associate the value v with key k in the dictionary.
|
||||
// Time complexity: O(1).
|
||||
auto Set(const K& k, const V& v) -> void {
|
||||
head = arena->New<Node>(std::make_pair(k, v), head);
|
||||
head_ = arena_->New<Node>(std::make_pair(k, v), head_);
|
||||
}
|
||||
|
||||
auto IsEmpty() -> bool { return !head; }
|
||||
auto IsEmpty() -> bool { return !head_; }
|
||||
|
||||
// The position of the first element of the dictionary
|
||||
// or `end()` if the dictionary is empty.
|
||||
auto begin() const -> Iterator { return Iterator(head); }
|
||||
auto begin() const -> Iterator { return Iterator(head_); }
|
||||
|
||||
// The position one past that of the last element.
|
||||
auto end() const -> Iterator { return Iterator(std::nullopt); }
|
||||
|
||||
private:
|
||||
std::optional<Nonnull<Node*>> head;
|
||||
Nonnull<Arena*> arena;
|
||||
std::optional<Nonnull<Node*>> head_;
|
||||
Nonnull<Arena*> arena_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -30,7 +30,7 @@ class FieldPath {
|
||||
FieldPath() = default;
|
||||
|
||||
// Constructs a FieldPath consisting of a single step.
|
||||
explicit FieldPath(std::string name) : components({std::move(name)}) {}
|
||||
explicit FieldPath(std::string name) : components_({std::move(name)}) {}
|
||||
|
||||
FieldPath(const FieldPath&) = default;
|
||||
FieldPath(FieldPath&&) = default;
|
||||
@@ -38,15 +38,15 @@ class FieldPath {
|
||||
auto operator=(FieldPath&&) -> FieldPath& = default;
|
||||
|
||||
// Returns whether *this is empty.
|
||||
auto IsEmpty() const -> bool { return components.empty(); }
|
||||
auto IsEmpty() const -> bool { return components_.empty(); }
|
||||
|
||||
// Appends `name` to the end of *this.
|
||||
auto Append(std::string name) -> void {
|
||||
components.push_back(std::move(name));
|
||||
components_.push_back(std::move(name));
|
||||
}
|
||||
|
||||
void Print(llvm::raw_ostream& out) const {
|
||||
for (const std::string& component : components) {
|
||||
for (const std::string& component : components_) {
|
||||
out << "." << component;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class FieldPath {
|
||||
// another Value, so its implementation details are tied to the implementation
|
||||
// details of Value.
|
||||
friend class Value;
|
||||
std::vector<std::string> components;
|
||||
std::vector<std::string> components_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -14,37 +14,37 @@ auto Heap::AllocateValue(Nonnull<const Value*> v) -> Address {
|
||||
// ensures that we don't do anything else in between, which is really bad!
|
||||
// Consider whether to include a copy of the input v in this function
|
||||
// or to leave it up to the caller.
|
||||
Address a(values.size());
|
||||
values.push_back(v);
|
||||
alive.push_back(true);
|
||||
Address a(values_.size());
|
||||
values_.push_back(v);
|
||||
alive_.push_back(true);
|
||||
return a;
|
||||
}
|
||||
|
||||
auto Heap::Read(const Address& a, SourceLocation source_loc)
|
||||
-> Nonnull<const Value*> {
|
||||
this->CheckAlive(a, source_loc);
|
||||
return values[a.index]->GetField(arena, a.field_path, source_loc);
|
||||
return values_[a.index_]->GetField(arena_, a.field_path_, source_loc);
|
||||
}
|
||||
|
||||
void Heap::Write(const Address& a, Nonnull<const Value*> v,
|
||||
SourceLocation source_loc) {
|
||||
this->CheckAlive(a, source_loc);
|
||||
values[a.index] =
|
||||
values[a.index]->SetField(arena, a.field_path, v, source_loc);
|
||||
values_[a.index_] =
|
||||
values_[a.index_]->SetField(arena_, a.field_path_, v, source_loc);
|
||||
}
|
||||
|
||||
void Heap::CheckAlive(const Address& address, SourceLocation source_loc) {
|
||||
if (!alive[address.index]) {
|
||||
if (!alive_[address.index_]) {
|
||||
FATAL_RUNTIME_ERROR(source_loc)
|
||||
<< "undefined behavior: access to dead value "
|
||||
<< *values[address.index];
|
||||
<< *values_[address.index_];
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::Deallocate(const Address& address) {
|
||||
CHECK(address.field_path.IsEmpty());
|
||||
if (alive[address.index]) {
|
||||
alive[address.index] = false;
|
||||
CHECK(address.field_path_.IsEmpty());
|
||||
if (alive_[address.index_]) {
|
||||
alive_[address.index_] = false;
|
||||
} else {
|
||||
FATAL_RUNTIME_ERROR_NO_LINE() << "deallocating an already dead value";
|
||||
}
|
||||
@@ -52,17 +52,17 @@ void Heap::Deallocate(const Address& address) {
|
||||
|
||||
void Heap::Print(llvm::raw_ostream& out) const {
|
||||
llvm::ListSeparator sep;
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
for (size_t i = 0; i < values_.size(); ++i) {
|
||||
out << sep;
|
||||
PrintAddress(Address(i), out);
|
||||
}
|
||||
}
|
||||
|
||||
void Heap::PrintAddress(const Address& a, llvm::raw_ostream& out) const {
|
||||
if (!alive[a.index]) {
|
||||
if (!alive_[a.index_]) {
|
||||
out << "!!";
|
||||
}
|
||||
out << *values[a.index];
|
||||
out << *values_[a.index_];
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Carbon {
|
||||
class Heap {
|
||||
public:
|
||||
// Constructs an empty Heap.
|
||||
explicit Heap(Nonnull<Arena*> arena) : arena(arena){};
|
||||
explicit Heap(Nonnull<Arena*> arena) : arena_(arena){};
|
||||
|
||||
Heap(const Heap&) = delete;
|
||||
auto operator=(const Heap&) -> Heap& = delete;
|
||||
@@ -51,9 +51,9 @@ class Heap {
|
||||
// Signal an error if the address is no longer alive.
|
||||
void CheckAlive(const Address& address, SourceLocation source_loc);
|
||||
|
||||
Nonnull<Arena*> arena;
|
||||
std::vector<Nonnull<const Value*>> values;
|
||||
std::vector<bool> alive;
|
||||
Nonnull<Arena*> arena_;
|
||||
std::vector<Nonnull<const Value*>> values_;
|
||||
std::vector<bool> alive_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -36,7 +36,7 @@ void Interpreter::PrintEnv(Env values, llvm::raw_ostream& out) {
|
||||
llvm::ListSeparator sep;
|
||||
for (const auto& [name, address] : values) {
|
||||
out << sep << name << ": ";
|
||||
heap.PrintAddress(address, out);
|
||||
heap_.PrintAddress(address, out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void Interpreter::PrintEnv(Env values, llvm::raw_ostream& out) {
|
||||
//
|
||||
|
||||
auto Interpreter::CurrentEnv() -> Env {
|
||||
Nonnull<Frame*> frame = stack.Top();
|
||||
Nonnull<Frame*> frame = stack_.Top();
|
||||
return frame->scopes.Top()->values;
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ auto Interpreter::GetFromEnv(SourceLocation source_loc, const std::string& name)
|
||||
void Interpreter::PrintState(llvm::raw_ostream& out) {
|
||||
out << "{\nstack: ";
|
||||
llvm::ListSeparator sep(" :: ");
|
||||
for (const auto& frame : stack) {
|
||||
for (const auto& frame : stack_) {
|
||||
out << sep << *frame;
|
||||
}
|
||||
out << "\nheap: " << heap;
|
||||
if (!stack.IsEmpty() && !stack.Top()->scopes.IsEmpty()) {
|
||||
out << "\nheap: " << heap_;
|
||||
if (!stack_.IsEmpty() && !stack_.Top()->scopes.IsEmpty()) {
|
||||
out << "\nvalues: ";
|
||||
PrintEnv(CurrentEnv(), out);
|
||||
}
|
||||
@@ -78,28 +78,28 @@ auto Interpreter::EvalPrim(Operator op,
|
||||
SourceLocation source_loc) -> Nonnull<const Value*> {
|
||||
switch (op) {
|
||||
case Operator::Neg:
|
||||
return arena->New<IntValue>(-cast<IntValue>(*args[0]).value());
|
||||
return arena_->New<IntValue>(-cast<IntValue>(*args[0]).value());
|
||||
case Operator::Add:
|
||||
return arena->New<IntValue>(cast<IntValue>(*args[0]).value() +
|
||||
cast<IntValue>(*args[1]).value());
|
||||
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() +
|
||||
cast<IntValue>(*args[1]).value());
|
||||
case Operator::Sub:
|
||||
return arena->New<IntValue>(cast<IntValue>(*args[0]).value() -
|
||||
cast<IntValue>(*args[1]).value());
|
||||
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() -
|
||||
cast<IntValue>(*args[1]).value());
|
||||
case Operator::Mul:
|
||||
return arena->New<IntValue>(cast<IntValue>(*args[0]).value() *
|
||||
cast<IntValue>(*args[1]).value());
|
||||
return arena_->New<IntValue>(cast<IntValue>(*args[0]).value() *
|
||||
cast<IntValue>(*args[1]).value());
|
||||
case Operator::Not:
|
||||
return arena->New<BoolValue>(!cast<BoolValue>(*args[0]).value());
|
||||
return arena_->New<BoolValue>(!cast<BoolValue>(*args[0]).value());
|
||||
case Operator::And:
|
||||
return arena->New<BoolValue>(cast<BoolValue>(*args[0]).value() &&
|
||||
cast<BoolValue>(*args[1]).value());
|
||||
return arena_->New<BoolValue>(cast<BoolValue>(*args[0]).value() &&
|
||||
cast<BoolValue>(*args[1]).value());
|
||||
case Operator::Or:
|
||||
return arena->New<BoolValue>(cast<BoolValue>(*args[0]).value() ||
|
||||
cast<BoolValue>(*args[1]).value());
|
||||
return arena_->New<BoolValue>(cast<BoolValue>(*args[0]).value() ||
|
||||
cast<BoolValue>(*args[1]).value());
|
||||
case Operator::Eq:
|
||||
return arena->New<BoolValue>(ValueEqual(args[0], args[1], source_loc));
|
||||
return arena_->New<BoolValue>(ValueEqual(args[0], args[1], source_loc));
|
||||
case Operator::Ptr:
|
||||
return arena->New<PointerType>(args[0]);
|
||||
return arena_->New<PointerType>(args[0]);
|
||||
case Operator::Deref:
|
||||
FATAL() << "dereference not implemented yet";
|
||||
}
|
||||
@@ -112,12 +112,13 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
Env new_env = *env;
|
||||
// Bring the deduced parameters into scope.
|
||||
for (const auto& deduced : func_def.deduced_parameters()) {
|
||||
Address a = heap.AllocateValue(arena->New<VariableType>(deduced.name));
|
||||
Address a =
|
||||
heap_.AllocateValue(arena_->New<VariableType>(deduced.name));
|
||||
new_env.Set(deduced.name, a);
|
||||
}
|
||||
auto pt = InterpPattern(new_env, &func_def.param_pattern());
|
||||
auto f = arena->New<FunctionValue>(func_def.name(), pt, func_def.body());
|
||||
Address a = heap.AllocateValue(f);
|
||||
auto f = arena_->New<FunctionValue>(func_def.name(), pt, func_def.body());
|
||||
Address a = heap_.AllocateValue(f);
|
||||
env->Set(func_def.name(), a);
|
||||
break;
|
||||
}
|
||||
@@ -132,15 +133,15 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
const BindingPattern& binding = cast<FieldMember>(*m).binding();
|
||||
const Expression& type_expression =
|
||||
cast<ExpressionPattern>(binding.type()).expression();
|
||||
auto type = InterpExp(Env(arena), &type_expression);
|
||||
auto type = InterpExp(Env(arena_), &type_expression);
|
||||
fields.push_back(make_pair(*binding.name(), type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto st = arena->New<NominalClassType>(
|
||||
auto st = arena_->New<NominalClassType>(
|
||||
class_def.name(), std::move(fields), std::move(methods));
|
||||
auto a = heap.AllocateValue(st);
|
||||
auto a = heap_.AllocateValue(st);
|
||||
env->Set(class_def.name(), a);
|
||||
break;
|
||||
}
|
||||
@@ -149,11 +150,11 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
const auto& choice = cast<ChoiceDeclaration>(d);
|
||||
VarValues alts;
|
||||
for (const auto& alternative : choice.alternatives()) {
|
||||
auto t = InterpExp(Env(arena), &alternative.signature());
|
||||
auto t = InterpExp(Env(arena_), &alternative.signature());
|
||||
alts.push_back(make_pair(alternative.name(), t));
|
||||
}
|
||||
auto ct = arena->New<ChoiceType>(choice.name(), std::move(alts));
|
||||
auto a = heap.AllocateValue(ct);
|
||||
auto ct = arena_->New<ChoiceType>(choice.name(), std::move(alts));
|
||||
auto a = heap_.AllocateValue(ct);
|
||||
env->Set(choice.name(), a);
|
||||
break;
|
||||
}
|
||||
@@ -163,7 +164,7 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
// Adds an entry in `globals` mapping the variable's name to the
|
||||
// result of evaluating the initializer.
|
||||
auto v = InterpExp(*env, &var.initializer());
|
||||
Address a = heap.AllocateValue(v);
|
||||
Address a = heap_.AllocateValue(v);
|
||||
env->Set(*var.binding().name(), a);
|
||||
break;
|
||||
}
|
||||
@@ -172,7 +173,7 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
|
||||
void Interpreter::InitGlobals(llvm::ArrayRef<Nonnull<Declaration*>> fs) {
|
||||
for (const auto d : fs) {
|
||||
InitEnv(*d, &globals);
|
||||
InitEnv(*d, &globals_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +181,7 @@ void Interpreter::DeallocateScope(Nonnull<Scope*> scope) {
|
||||
for (const auto& l : scope->locals) {
|
||||
std::optional<Address> a = scope->values.Get(l);
|
||||
CHECK(a);
|
||||
heap.Deallocate(*a);
|
||||
heap_.Deallocate(*a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +199,7 @@ auto Interpreter::CreateTuple(Nonnull<Action*> act,
|
||||
// -> { { `(v1,...,vn) :: C, E, F} :: S, H}
|
||||
const auto& tup_lit = cast<TupleLiteral>(*exp);
|
||||
CHECK(act->results().size() == tup_lit.fields().size());
|
||||
return arena->New<TupleValue>(act->results());
|
||||
return arena_->New<TupleValue>(act->results());
|
||||
}
|
||||
|
||||
auto Interpreter::CreateStruct(const std::vector<FieldInitializer>& fields,
|
||||
@@ -210,7 +211,7 @@ auto Interpreter::CreateStruct(const std::vector<FieldInitializer>& fields,
|
||||
elements.push_back({.name = fields[i].name(), .value = values[i]});
|
||||
}
|
||||
|
||||
return arena->New<StructValue>(std::move(elements));
|
||||
return arena_->New<StructValue>(std::move(elements));
|
||||
}
|
||||
|
||||
auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
@@ -219,9 +220,9 @@ auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
switch (p->kind()) {
|
||||
case Value::Kind::BindingPlaceholderValue: {
|
||||
const auto& placeholder = cast<BindingPlaceholderValue>(*p);
|
||||
Env values(arena);
|
||||
Env values(arena_);
|
||||
if (placeholder.name().has_value()) {
|
||||
Address a = heap.AllocateValue(v);
|
||||
Address a = heap_.AllocateValue(v);
|
||||
values.Set(*placeholder.name(), a);
|
||||
}
|
||||
return values;
|
||||
@@ -236,7 +237,7 @@ auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
<< "arity mismatch in tuple pattern match:\n pattern: "
|
||||
<< p_tup << "\n value: " << v_tup;
|
||||
}
|
||||
Env values(arena);
|
||||
Env values(arena_);
|
||||
for (size_t i = 0; i < p_tup.elements().size(); ++i) {
|
||||
std::optional<Env> matches = PatternMatch(
|
||||
p_tup.elements()[i], v_tup.elements()[i], source_loc);
|
||||
@@ -256,7 +257,7 @@ auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
const auto& p_struct = cast<StructValue>(*p);
|
||||
const auto& v_struct = cast<StructValue>(*v);
|
||||
CHECK(p_struct.elements().size() == v_struct.elements().size());
|
||||
Env values(arena);
|
||||
Env values(arena_);
|
||||
for (size_t i = 0; i < p_struct.elements().size(); ++i) {
|
||||
CHECK(p_struct.elements()[i].name == v_struct.elements()[i].name);
|
||||
std::optional<Env> matches =
|
||||
@@ -312,10 +313,10 @@ auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
|
||||
case Value::Kind::AutoType:
|
||||
// `auto` matches any type, without binding any new names. We rely
|
||||
// on the typechecker to ensure that `v` is a type.
|
||||
return Env(arena);
|
||||
return Env(arena_);
|
||||
default:
|
||||
if (ValueEqual(p, v, source_loc)) {
|
||||
return Env(arena);
|
||||
return Env(arena_);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -327,7 +328,7 @@ void Interpreter::PatternAssignment(Nonnull<const Value*> pat,
|
||||
SourceLocation source_loc) {
|
||||
switch (pat->kind()) {
|
||||
case Value::Kind::PointerValue:
|
||||
heap.Write(cast<PointerValue>(*pat).value(), val, source_loc);
|
||||
heap_.Write(cast<PointerValue>(*pat).value(), val, source_loc);
|
||||
break;
|
||||
case Value::Kind::TupleValue: {
|
||||
switch (val->kind()) {
|
||||
@@ -374,7 +375,7 @@ void Interpreter::PatternAssignment(Nonnull<const Value*> pat,
|
||||
}
|
||||
|
||||
auto Interpreter::StepLvalue() -> Transition {
|
||||
Nonnull<Action*> act = stack.Top()->todo.Top();
|
||||
Nonnull<Action*> act = stack_.Top()->todo.Top();
|
||||
const Expression& exp = cast<LValAction>(*act).expression();
|
||||
if (trace_) {
|
||||
llvm::outs() << "--- step lvalue " << exp << " (" << exp.source_loc()
|
||||
@@ -386,14 +387,14 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
// -> { {E(x) :: C, E, F} :: S, H}
|
||||
Address pointer =
|
||||
GetFromEnv(exp.source_loc(), cast<IdentifierExpression>(exp).name());
|
||||
Nonnull<const Value*> v = arena->New<PointerValue>(pointer);
|
||||
Nonnull<const Value*> v = arena_->New<PointerValue>(pointer);
|
||||
return Done{v};
|
||||
}
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
if (act->pos() == 0) {
|
||||
// { {e.f :: C, E, F} :: S, H}
|
||||
// -> { e :: [].f :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<LValAction>(
|
||||
return Spawn{arena_->New<LValAction>(
|
||||
&cast<FieldAccessExpression>(exp).aggregate())};
|
||||
} else {
|
||||
// { v :: [].f :: C, E, F} :: S, H}
|
||||
@@ -401,7 +402,7 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
Address aggregate = cast<PointerValue>(*act->results()[0]).value();
|
||||
Address field = aggregate.SubobjectAddress(
|
||||
cast<FieldAccessExpression>(exp).field());
|
||||
return Done{arena->New<PointerValue>(field)};
|
||||
return Done{arena_->New<PointerValue>(field)};
|
||||
}
|
||||
}
|
||||
case Expression::Kind::IndexExpression: {
|
||||
@@ -409,11 +410,11 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
// { {e[i] :: C, E, F} :: S, H}
|
||||
// -> { e :: [][i] :: C, E, F} :: S, H}
|
||||
return Spawn{
|
||||
arena->New<LValAction>(&cast<IndexExpression>(exp).aggregate())};
|
||||
arena_->New<LValAction>(&cast<IndexExpression>(exp).aggregate())};
|
||||
|
||||
} else if (act->pos() == 1) {
|
||||
return Spawn{
|
||||
arena->New<ExpressionAction>(&cast<IndexExpression>(exp).offset())};
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<IndexExpression>(exp).offset())};
|
||||
} else {
|
||||
// { v :: [][i] :: C, E, F} :: S, H}
|
||||
// -> { { &v[i] :: C, E, F} :: S, H }
|
||||
@@ -421,7 +422,7 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
std::string f =
|
||||
std::to_string(cast<IntValue>(*act->results()[1]).value());
|
||||
Address field = aggregate.SubobjectAddress(f);
|
||||
return Done{arena->New<PointerValue>(field)};
|
||||
return Done{arena_->New<PointerValue>(field)};
|
||||
}
|
||||
}
|
||||
case Expression::Kind::TupleLiteral: {
|
||||
@@ -431,7 +432,7 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
return Spawn{arena->New<LValAction>(
|
||||
return Spawn{arena_->New<LValAction>(
|
||||
cast<TupleLiteral>(exp).fields()[act->pos()])};
|
||||
} else {
|
||||
return Done{CreateTuple(act, &exp)};
|
||||
@@ -457,7 +458,7 @@ auto Interpreter::StepLvalue() -> Transition {
|
||||
}
|
||||
|
||||
auto Interpreter::StepExp() -> Transition {
|
||||
Nonnull<Action*> act = stack.Top()->todo.Top();
|
||||
Nonnull<Action*> act = stack_.Top()->todo.Top();
|
||||
const Expression& exp = cast<ExpressionAction>(*act).expression();
|
||||
if (trace_) {
|
||||
llvm::outs() << "--- step exp " << exp << " (" << exp.source_loc()
|
||||
@@ -468,11 +469,11 @@ auto Interpreter::StepExp() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { { e[i] :: C, E, F} :: S, H}
|
||||
// -> { { e :: [][i] :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<IndexExpression>(exp).aggregate())};
|
||||
} else if (act->pos() == 1) {
|
||||
return Spawn{
|
||||
arena->New<ExpressionAction>(&cast<IndexExpression>(exp).offset())};
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<IndexExpression>(exp).offset())};
|
||||
} else {
|
||||
// { { v :: [][i] :: C, E, F} :: S, H}
|
||||
// -> { { v_i :: C, E, F} : S, H}
|
||||
@@ -492,7 +493,7 @@ auto Interpreter::StepExp() -> Transition {
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
cast<TupleLiteral>(exp).fields()[act->pos()])};
|
||||
} else {
|
||||
return Done{CreateTuple(act, &exp)};
|
||||
@@ -501,7 +502,7 @@ auto Interpreter::StepExp() -> Transition {
|
||||
case Expression::Kind::StructLiteral: {
|
||||
const auto& literal = cast<StructLiteral>(exp);
|
||||
if (act->pos() < static_cast<int>(literal.fields().size())) {
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&literal.fields()[act->pos()].expression())};
|
||||
} else {
|
||||
return Done{CreateStruct(literal.fields(), act->results())};
|
||||
@@ -510,14 +511,14 @@ auto Interpreter::StepExp() -> Transition {
|
||||
case Expression::Kind::StructTypeLiteral: {
|
||||
const auto& struct_type = cast<StructTypeLiteral>(exp);
|
||||
if (act->pos() < static_cast<int>(struct_type.fields().size())) {
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&struct_type.fields()[act->pos()].expression())};
|
||||
} else {
|
||||
VarValues fields;
|
||||
for (size_t i = 0; i < struct_type.fields().size(); ++i) {
|
||||
fields.push_back({struct_type.fields()[i].name(), act->results()[i]});
|
||||
}
|
||||
return Done{arena->New<StructType>(std::move(fields))};
|
||||
return Done{arena_->New<StructType>(std::move(fields))};
|
||||
}
|
||||
}
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
@@ -525,12 +526,12 @@ auto Interpreter::StepExp() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { { e.f :: C, E, F} :: S, H}
|
||||
// -> { { e :: [].f :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(&access.aggregate())};
|
||||
return Spawn{arena_->New<ExpressionAction>(&access.aggregate())};
|
||||
} else {
|
||||
// { { v :: [].f :: C, E, F} :: S, H}
|
||||
// -> { { v_f :: C, E, F} : S, H}
|
||||
return Done{act->results()[0]->GetField(
|
||||
arena, FieldPath(access.field()), exp.source_loc())};
|
||||
arena_, FieldPath(access.field()), exp.source_loc())};
|
||||
}
|
||||
}
|
||||
case Expression::Kind::IdentifierExpression: {
|
||||
@@ -538,23 +539,23 @@ auto Interpreter::StepExp() -> Transition {
|
||||
const auto& ident = cast<IdentifierExpression>(exp);
|
||||
// { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H}
|
||||
Address pointer = GetFromEnv(exp.source_loc(), ident.name());
|
||||
return Done{heap.Read(pointer, exp.source_loc())};
|
||||
return Done{heap_.Read(pointer, exp.source_loc())};
|
||||
}
|
||||
case Expression::Kind::IntLiteral:
|
||||
CHECK(act->pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
return Done{arena->New<IntValue>(cast<IntLiteral>(exp).value())};
|
||||
return Done{arena_->New<IntValue>(cast<IntLiteral>(exp).value())};
|
||||
case Expression::Kind::BoolLiteral:
|
||||
CHECK(act->pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
return Done{arena->New<BoolValue>(cast<BoolLiteral>(exp).value())};
|
||||
return Done{arena_->New<BoolValue>(cast<BoolLiteral>(exp).value())};
|
||||
case Expression::Kind::PrimitiveOperatorExpression: {
|
||||
const auto& op = cast<PrimitiveOperatorExpression>(exp);
|
||||
if (act->pos() != static_cast<int>(op.arguments().size())) {
|
||||
// { {v :: op(vs,[],e,es) :: C, E, F} :: S, H}
|
||||
// -> { {e :: op(vs,v,[],es) :: C, E, F} :: S, H}
|
||||
Nonnull<const Expression*> arg = op.arguments()[act->pos()];
|
||||
return Spawn{arena->New<ExpressionAction>(arg)};
|
||||
return Spawn{arena_->New<ExpressionAction>(arg)};
|
||||
} else {
|
||||
// { {v :: op(vs,[]) :: C, E, F} :: S, H}
|
||||
// -> { {eval_prim(op, (vs,v)) :: C, E, F} :: S, H}
|
||||
@@ -565,12 +566,12 @@ auto Interpreter::StepExp() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { {e1(e2) :: C, E, F} :: S, H}
|
||||
// -> { {e1 :: [](e2) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<CallExpression>(exp).function())};
|
||||
} else if (act->pos() == 1) {
|
||||
// { { v :: [](e) :: C, E, F} :: S, H}
|
||||
// -> { { e :: v([]) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<CallExpression>(exp).argument())};
|
||||
} else if (act->pos() == 2) {
|
||||
// { { v2 :: v1([]) :: C, E, F} :: S, H}
|
||||
@@ -579,7 +580,7 @@ auto Interpreter::StepExp() -> Transition {
|
||||
case Value::Kind::AlternativeConstructorValue: {
|
||||
const auto& alt =
|
||||
cast<AlternativeConstructorValue>(*act->results()[0]);
|
||||
return Done{arena->New<AlternativeValue>(
|
||||
return Done{arena_->New<AlternativeValue>(
|
||||
alt.alt_name(), alt.choice_name(), act->results()[1])};
|
||||
}
|
||||
case Value::Kind::FunctionValue:
|
||||
@@ -603,7 +604,7 @@ auto Interpreter::StepExp() -> Transition {
|
||||
switch (cast<IntrinsicExpression>(exp).intrinsic()) {
|
||||
case IntrinsicExpression::Intrinsic::Print:
|
||||
Address pointer = GetFromEnv(exp.source_loc(), "format_str");
|
||||
Nonnull<const Value*> pointee = heap.Read(pointer, exp.source_loc());
|
||||
Nonnull<const Value*> pointee = heap_.Read(pointer, exp.source_loc());
|
||||
CHECK(pointee->kind() == Value::Kind::StringValue);
|
||||
// TODO: This could eventually use something like llvm::formatv.
|
||||
llvm::outs() << cast<StringValue>(*pointee).value();
|
||||
@@ -612,50 +613,50 @@ auto Interpreter::StepExp() -> Transition {
|
||||
|
||||
case Expression::Kind::IntTypeLiteral: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<IntType>()};
|
||||
return Done{arena_->New<IntType>()};
|
||||
}
|
||||
case Expression::Kind::BoolTypeLiteral: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<BoolType>()};
|
||||
return Done{arena_->New<BoolType>()};
|
||||
}
|
||||
case Expression::Kind::TypeTypeLiteral: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<TypeType>()};
|
||||
return Done{arena_->New<TypeType>()};
|
||||
}
|
||||
case Expression::Kind::FunctionTypeLiteral: {
|
||||
if (act->pos() == 0) {
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<FunctionTypeLiteral>(exp).parameter())};
|
||||
} else if (act->pos() == 1) {
|
||||
// { { pt :: fn [] -> e :: C, E, F} :: S, H}
|
||||
// -> { { e :: fn pt -> []) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<FunctionTypeLiteral>(exp).return_type())};
|
||||
} else {
|
||||
// { { rt :: fn pt -> [] :: C, E, F} :: S, H}
|
||||
// -> { fn pt -> rt :: {C, E, F} :: S, H}
|
||||
return Done{arena->New<FunctionType>(std::vector<GenericBinding>(),
|
||||
act->results()[0],
|
||||
act->results()[1])};
|
||||
return Done{arena_->New<FunctionType>(std::vector<GenericBinding>(),
|
||||
act->results()[0],
|
||||
act->results()[1])};
|
||||
}
|
||||
}
|
||||
case Expression::Kind::ContinuationTypeLiteral: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<ContinuationType>()};
|
||||
return Done{arena_->New<ContinuationType>()};
|
||||
}
|
||||
case Expression::Kind::StringLiteral:
|
||||
CHECK(act->pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
return Done{arena->New<StringValue>(cast<StringLiteral>(exp).value())};
|
||||
return Done{arena_->New<StringValue>(cast<StringLiteral>(exp).value())};
|
||||
case Expression::Kind::StringTypeLiteral: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<StringType>()};
|
||||
return Done{arena_->New<StringType>()};
|
||||
}
|
||||
} // switch (exp->kind)
|
||||
}
|
||||
|
||||
auto Interpreter::StepPattern() -> Transition {
|
||||
Nonnull<Action*> act = stack.Top()->todo.Top();
|
||||
Nonnull<Action*> act = stack_.Top()->todo.Top();
|
||||
const Pattern& pattern = cast<PatternAction>(*act).pattern();
|
||||
if (trace_) {
|
||||
llvm::outs() << "--- step pattern " << pattern << " ("
|
||||
@@ -664,15 +665,15 @@ auto Interpreter::StepPattern() -> Transition {
|
||||
switch (pattern.kind()) {
|
||||
case Pattern::Kind::AutoPattern: {
|
||||
CHECK(act->pos() == 0);
|
||||
return Done{arena->New<AutoType>()};
|
||||
return Done{arena_->New<AutoType>()};
|
||||
}
|
||||
case Pattern::Kind::BindingPattern: {
|
||||
const auto& binding = cast<BindingPattern>(pattern);
|
||||
if (act->pos() == 0) {
|
||||
return Spawn{arena->New<PatternAction>(&binding.type())};
|
||||
return Spawn{arena_->New<PatternAction>(&binding.type())};
|
||||
} else {
|
||||
return Done{arena->New<BindingPlaceholderValue>(binding.name(),
|
||||
act->results()[0])};
|
||||
return Done{arena_->New<BindingPlaceholderValue>(binding.name(),
|
||||
act->results()[0])};
|
||||
}
|
||||
}
|
||||
case Pattern::Kind::TuplePattern: {
|
||||
@@ -682,27 +683,27 @@ auto Interpreter::StepPattern() -> Transition {
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
return Spawn{arena->New<PatternAction>(tuple.fields()[act->pos()])};
|
||||
return Spawn{arena_->New<PatternAction>(tuple.fields()[act->pos()])};
|
||||
} else {
|
||||
return Done{arena->New<TupleValue>(act->results())};
|
||||
return Done{arena_->New<TupleValue>(act->results())};
|
||||
}
|
||||
}
|
||||
case Pattern::Kind::AlternativePattern: {
|
||||
const auto& alternative = cast<AlternativePattern>(pattern);
|
||||
if (act->pos() == 0) {
|
||||
return Spawn{arena->New<ExpressionAction>(&alternative.choice_type())};
|
||||
return Spawn{arena_->New<ExpressionAction>(&alternative.choice_type())};
|
||||
} else if (act->pos() == 1) {
|
||||
return Spawn{arena->New<PatternAction>(&alternative.arguments())};
|
||||
return Spawn{arena_->New<PatternAction>(&alternative.arguments())};
|
||||
} else {
|
||||
CHECK(act->pos() == 2);
|
||||
const auto& choice_type = cast<ChoiceType>(*act->results()[0]);
|
||||
return Done{arena->New<AlternativeValue>(alternative.alternative_name(),
|
||||
choice_type.name(),
|
||||
act->results()[1])};
|
||||
return Done{arena_->New<AlternativeValue>(
|
||||
alternative.alternative_name(), choice_type.name(),
|
||||
act->results()[1])};
|
||||
}
|
||||
}
|
||||
case Pattern::Kind::ExpressionPattern:
|
||||
return Delegate{arena->New<ExpressionAction>(
|
||||
return Delegate{arena_->New<ExpressionAction>(
|
||||
&cast<ExpressionPattern>(pattern).expression())};
|
||||
}
|
||||
}
|
||||
@@ -737,7 +738,7 @@ static auto HasLocalScope(Nonnull<Action*> act) -> bool {
|
||||
}
|
||||
|
||||
auto Interpreter::StepStmt() -> Transition {
|
||||
Nonnull<Frame*> frame = stack.Top();
|
||||
Nonnull<Frame*> frame = stack_.Top();
|
||||
Nonnull<Action*> act = frame->todo.Top();
|
||||
const Statement& stmt = cast<StatementAction>(*act).statement();
|
||||
if (trace_) {
|
||||
@@ -751,8 +752,8 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { { (match (e) ...) :: C, E, F} :: S, H}
|
||||
// -> { { e :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
frame->scopes.Push(arena->New<Scope>(CurrentEnv()));
|
||||
return Spawn{arena->New<ExpressionAction>(&match_stmt.expression())};
|
||||
frame->scopes.Push(arena_->New<Scope>(CurrentEnv()));
|
||||
return Spawn{arena_->New<ExpressionAction>(&match_stmt.expression())};
|
||||
} else {
|
||||
// Regarding act->pos():
|
||||
// * odd: start interpreting the pattern of a clause
|
||||
@@ -775,7 +776,7 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// start interpreting the pattern of the clause
|
||||
// { {v :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
// -> { {pi :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<PatternAction>(&c.pattern())};
|
||||
return Spawn{arena_->New<PatternAction>(&c.pattern())};
|
||||
} else { // try to match
|
||||
auto v = act->results()[0];
|
||||
auto pat = act->results()[clause_num + 1];
|
||||
@@ -788,7 +789,7 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
frame->scopes.Top()->values.Set(name, value);
|
||||
frame->scopes.Top()->locals.push_back(name);
|
||||
}
|
||||
return Spawn{arena->New<StatementAction>(&c.statement())};
|
||||
return Spawn{arena_->New<StatementAction>(&c.statement())};
|
||||
} else {
|
||||
return RunAgain{};
|
||||
}
|
||||
@@ -801,11 +802,11 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// -> { { e :: (while ([]) s) :: C, E, F} :: S, H}
|
||||
act->Clear();
|
||||
return Spawn{
|
||||
arena->New<ExpressionAction>(&cast<While>(stmt).condition())};
|
||||
arena_->New<ExpressionAction>(&cast<While>(stmt).condition())};
|
||||
} else if (cast<BoolValue>(*act->results().back()).value()) {
|
||||
// { {true :: (while ([]) s) :: C, E, F} :: S, H}
|
||||
// -> { { s :: (while (e) s) :: C, E, F } :: S, H}
|
||||
return Spawn{arena->New<StatementAction>(&cast<While>(stmt).body())};
|
||||
return Spawn{arena_->New<StatementAction>(&cast<While>(stmt).body())};
|
||||
} else {
|
||||
// { {false :: (while ([]) s) :: C, E, F} :: S, H}
|
||||
// -> { { C, E, F } :: S, H}
|
||||
@@ -840,8 +841,8 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
const auto& block = cast<Block>(stmt);
|
||||
if (block.statement()) {
|
||||
frame->scopes.Push(arena->New<Scope>(CurrentEnv()));
|
||||
return Spawn{arena->New<StatementAction>(*block.statement())};
|
||||
frame->scopes.Push(arena_->New<Scope>(CurrentEnv()));
|
||||
return Spawn{arena_->New<StatementAction>(*block.statement())};
|
||||
} else {
|
||||
return Done{};
|
||||
}
|
||||
@@ -856,10 +857,10 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { {(var x = e) :: C, E, F} :: S, H}
|
||||
// -> { {e :: (var x = []) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<VariableDefinition>(stmt).init())};
|
||||
} else if (act->pos() == 1) {
|
||||
return Spawn{arena->New<PatternAction>(
|
||||
return Spawn{arena_->New<PatternAction>(
|
||||
&cast<VariableDefinition>(stmt).pattern())};
|
||||
} else {
|
||||
// { { v :: (x = []) :: C, E, F} :: S, H}
|
||||
@@ -881,7 +882,7 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { {e :: C, E, F} :: S, H}
|
||||
// -> { {e :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(
|
||||
return Spawn{arena_->New<ExpressionAction>(
|
||||
&cast<ExpressionStatement>(stmt).expression())};
|
||||
} else {
|
||||
return Done{};
|
||||
@@ -890,11 +891,11 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
if (act->pos() == 0) {
|
||||
// { {(lv = e) :: C, E, F} :: S, H}
|
||||
// -> { {lv :: ([] = e) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<LValAction>(&cast<Assign>(stmt).lhs())};
|
||||
return Spawn{arena_->New<LValAction>(&cast<Assign>(stmt).lhs())};
|
||||
} else if (act->pos() == 1) {
|
||||
// { { a :: ([] = e) :: C, E, F} :: S, H}
|
||||
// -> { { e :: (a = []) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<ExpressionAction>(&cast<Assign>(stmt).rhs())};
|
||||
return Spawn{arena_->New<ExpressionAction>(&cast<Assign>(stmt).rhs())};
|
||||
} else {
|
||||
// { { v :: (a = []) :: C, E, F} :: S, H}
|
||||
// -> { { C, E, F} :: S, H(a := v)}
|
||||
@@ -907,19 +908,20 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
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}
|
||||
return Spawn{arena->New<ExpressionAction>(&cast<If>(stmt).condition())};
|
||||
return Spawn{
|
||||
arena_->New<ExpressionAction>(&cast<If>(stmt).condition())};
|
||||
} else if (cast<BoolValue>(*act->results()[0]).value()) {
|
||||
// { {true :: if ([]) then_stmt else else_stmt :: C, E, F} ::
|
||||
// S, H}
|
||||
// -> { { then_stmt :: C, E, F } :: S, H}
|
||||
return Delegate{
|
||||
arena->New<StatementAction>(&cast<If>(stmt).then_statement())};
|
||||
arena_->New<StatementAction>(&cast<If>(stmt).then_statement())};
|
||||
} else if (cast<If>(stmt).else_statement()) {
|
||||
// { {false :: if ([]) then_stmt else else_stmt :: C, E, F} ::
|
||||
// S, H}
|
||||
// -> { { else_stmt :: C, E, F } :: S, H}
|
||||
return Delegate{
|
||||
arena->New<StatementAction>(*cast<If>(stmt).else_statement())};
|
||||
arena_->New<StatementAction>(*cast<If>(stmt).else_statement())};
|
||||
} else {
|
||||
return Done{};
|
||||
}
|
||||
@@ -928,7 +930,7 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// { {return e :: C, E, F} :: S, H}
|
||||
// -> { {e :: return [] :: C, E, F} :: S, H}
|
||||
return Spawn{
|
||||
arena->New<ExpressionAction>(&cast<Return>(stmt).expression())};
|
||||
arena_->New<ExpressionAction>(&cast<Return>(stmt).expression())};
|
||||
} else {
|
||||
// { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H}
|
||||
// -> { {v :: C', E', F'} :: S, H}
|
||||
@@ -939,11 +941,11 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// -> { { s1 :: s2 :: C, E, F} :: S, H}
|
||||
const auto& seq = cast<Sequence>(stmt);
|
||||
if (act->pos() == 0) {
|
||||
return Spawn{arena->New<StatementAction>(&seq.statement())};
|
||||
return Spawn{arena_->New<StatementAction>(&seq.statement())};
|
||||
} else {
|
||||
if (seq.next()) {
|
||||
return Delegate{
|
||||
arena->New<StatementAction>(*cast<Sequence>(stmt).next())};
|
||||
arena_->New<StatementAction>(*cast<Sequence>(stmt).next())};
|
||||
} else {
|
||||
return Done{};
|
||||
}
|
||||
@@ -953,17 +955,17 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
CHECK(act->pos() == 0);
|
||||
// Create a continuation object by creating a frame similar the
|
||||
// way one is created in a function call.
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(CurrentEnv()));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena_->New<Scope>(CurrentEnv()));
|
||||
Stack<Nonnull<Action*>> todo;
|
||||
todo.Push(arena->New<StatementAction>(
|
||||
arena->New<Return>(arena, stmt.source_loc())));
|
||||
todo.Push(arena->New<StatementAction>(&cast<Continuation>(stmt).body()));
|
||||
auto continuation_stack = arena->New<std::vector<Nonnull<Frame*>>>();
|
||||
todo.Push(arena_->New<StatementAction>(
|
||||
arena_->New<Return>(arena_, stmt.source_loc())));
|
||||
todo.Push(arena_->New<StatementAction>(&cast<Continuation>(stmt).body()));
|
||||
auto continuation_stack = arena_->New<std::vector<Nonnull<Frame*>>>();
|
||||
auto continuation_frame =
|
||||
arena->New<Frame>("__continuation", scopes, todo);
|
||||
arena_->New<Frame>("__continuation", scopes, todo);
|
||||
continuation_stack->push_back(continuation_frame);
|
||||
Address continuation_address =
|
||||
heap.AllocateValue(arena->New<ContinuationValue>(continuation_stack));
|
||||
Address continuation_address = heap_.AllocateValue(
|
||||
arena_->New<ContinuationValue>(continuation_stack));
|
||||
// Store the continuation's address in the frame.
|
||||
continuation_frame->continuation = continuation_address;
|
||||
// Bind the continuation object to the continuation variable
|
||||
@@ -977,21 +979,22 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
case Statement::Kind::Run:
|
||||
if (act->pos() == 0) {
|
||||
// Evaluate the argument of the run statement.
|
||||
return Spawn{arena->New<ExpressionAction>(&cast<Run>(stmt).argument())};
|
||||
return Spawn{
|
||||
arena_->New<ExpressionAction>(&cast<Run>(stmt).argument())};
|
||||
} else {
|
||||
frame->todo.Pop(1);
|
||||
// Push an expression statement action to ignore the result
|
||||
// value from the continuation.
|
||||
auto ignore_result =
|
||||
arena->New<StatementAction>(arena->New<ExpressionStatement>(
|
||||
arena_->New<StatementAction>(arena_->New<ExpressionStatement>(
|
||||
stmt.source_loc(),
|
||||
arena->New<TupleLiteral>(stmt.source_loc())));
|
||||
arena_->New<TupleLiteral>(stmt.source_loc())));
|
||||
frame->todo.Push(ignore_result);
|
||||
// Push the continuation onto the current stack.
|
||||
// Push the continuation onto the current stack_.
|
||||
std::vector<Nonnull<Frame*>>& continuation_vector =
|
||||
cast<ContinuationValue>(*act->results()[0]).stack();
|
||||
while (!continuation_vector.empty()) {
|
||||
stack.Push(continuation_vector.back());
|
||||
stack_.Push(continuation_vector.back());
|
||||
continuation_vector.pop_back();
|
||||
}
|
||||
return ManualTransition{};
|
||||
@@ -1002,11 +1005,11 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
frame->todo.Pop();
|
||||
std::vector<Nonnull<Frame*>> paused;
|
||||
do {
|
||||
paused.push_back(stack.Pop());
|
||||
paused.push_back(stack_.Pop());
|
||||
} while (paused.back()->continuation == std::nullopt);
|
||||
// Update the continuation with the paused stack.
|
||||
// Update the continuation with the paused stack_.
|
||||
const auto& continuation = cast<ContinuationValue>(
|
||||
*heap.Read(*paused.back()->continuation, stmt.source_loc()));
|
||||
*heap_.Read(*paused.back()->continuation, stmt.source_loc()));
|
||||
CHECK(continuation.stack().empty());
|
||||
continuation.stack() = std::move(paused);
|
||||
return ManualTransition{};
|
||||
@@ -1019,12 +1022,12 @@ class Interpreter::DoTransition {
|
||||
explicit DoTransition(Interpreter* interpreter) : interpreter(interpreter) {}
|
||||
|
||||
void operator()(const Done& done) {
|
||||
Nonnull<Frame*> frame = interpreter->stack.Top();
|
||||
Nonnull<Frame*> frame = interpreter->stack_.Top();
|
||||
if (frame->todo.Top()->kind() != Action::Kind::StatementAction) {
|
||||
CHECK(done.result);
|
||||
frame->todo.Pop();
|
||||
if (frame->todo.IsEmpty()) {
|
||||
interpreter->program_value = *done.result;
|
||||
interpreter->program_value_ = *done.result;
|
||||
} else {
|
||||
frame->todo.Top()->AddResult(*done.result);
|
||||
}
|
||||
@@ -1035,25 +1038,25 @@ class Interpreter::DoTransition {
|
||||
}
|
||||
|
||||
void operator()(const Spawn& spawn) {
|
||||
Nonnull<Frame*> frame = interpreter->stack.Top();
|
||||
Nonnull<Frame*> frame = interpreter->stack_.Top();
|
||||
Nonnull<Action*> action = frame->todo.Top();
|
||||
action->set_pos(action->pos() + 1);
|
||||
frame->todo.Push(spawn.child);
|
||||
}
|
||||
|
||||
void operator()(const Delegate& delegate) {
|
||||
Nonnull<Frame*> frame = interpreter->stack.Top();
|
||||
Nonnull<Frame*> frame = interpreter->stack_.Top();
|
||||
frame->todo.Pop();
|
||||
frame->todo.Push(delegate.delegate);
|
||||
}
|
||||
|
||||
void operator()(const RunAgain&) {
|
||||
Nonnull<Action*> action = interpreter->stack.Top()->todo.Top();
|
||||
Nonnull<Action*> action = interpreter->stack_.Top()->todo.Top();
|
||||
action->set_pos(action->pos() + 1);
|
||||
}
|
||||
|
||||
void operator()(const UnwindTo& unwind_to) {
|
||||
Nonnull<Frame*> frame = interpreter->stack.Top();
|
||||
Nonnull<Frame*> frame = interpreter->stack_.Top();
|
||||
while (frame->todo.Top() != unwind_to.new_top) {
|
||||
if (HasLocalScope(frame->todo.Top())) {
|
||||
interpreter->DeallocateScope(frame->scopes.Top());
|
||||
@@ -1064,36 +1067,36 @@ class Interpreter::DoTransition {
|
||||
}
|
||||
|
||||
void operator()(const UnwindFunctionCall& unwind) {
|
||||
interpreter->DeallocateLocals(interpreter->stack.Top());
|
||||
interpreter->stack.Pop();
|
||||
if (interpreter->stack.Top()->todo.IsEmpty()) {
|
||||
interpreter->program_value = unwind.return_val;
|
||||
interpreter->DeallocateLocals(interpreter->stack_.Top());
|
||||
interpreter->stack_.Pop();
|
||||
if (interpreter->stack_.Top()->todo.IsEmpty()) {
|
||||
interpreter->program_value_ = unwind.return_val;
|
||||
} else {
|
||||
interpreter->stack.Top()->todo.Top()->AddResult(unwind.return_val);
|
||||
interpreter->stack_.Top()->todo.Top()->AddResult(unwind.return_val);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const CallFunction& call) {
|
||||
interpreter->stack.Top()->todo.Pop();
|
||||
interpreter->stack_.Top()->todo.Pop();
|
||||
std::optional<Env> matches = interpreter->PatternMatch(
|
||||
&call.function->parameters(), call.args, call.source_loc);
|
||||
CHECK(matches.has_value())
|
||||
<< "internal error in call_function, pattern match failed";
|
||||
// Create the new frame and push it on the stack
|
||||
Env values = interpreter->globals;
|
||||
Env values = interpreter->globals_;
|
||||
std::vector<std::string> params;
|
||||
for (const auto& [name, value] : *matches) {
|
||||
values.Set(name, value);
|
||||
params.push_back(name);
|
||||
}
|
||||
auto scopes =
|
||||
Stack<Nonnull<Scope*>>(interpreter->arena->New<Scope>(values, params));
|
||||
Stack<Nonnull<Scope*>>(interpreter->arena_->New<Scope>(values, params));
|
||||
CHECK(call.function->body()) << "Calling a function that's missing a body";
|
||||
auto todo = Stack<Nonnull<Action*>>(
|
||||
interpreter->arena->New<StatementAction>(*call.function->body()));
|
||||
interpreter->arena_->New<StatementAction>(*call.function->body()));
|
||||
auto frame =
|
||||
interpreter->arena->New<Frame>(call.function->name(), scopes, todo);
|
||||
interpreter->stack.Push(frame);
|
||||
interpreter->arena_->New<Frame>(call.function->name(), scopes, todo);
|
||||
interpreter->stack_.Push(frame);
|
||||
}
|
||||
|
||||
void operator()(const ManualTransition&) {}
|
||||
@@ -1104,7 +1107,7 @@ class Interpreter::DoTransition {
|
||||
|
||||
// State transition.
|
||||
void Interpreter::Step() {
|
||||
Nonnull<Frame*> frame = stack.Top();
|
||||
Nonnull<Frame*> frame = stack_.Top();
|
||||
if (frame->todo.IsEmpty()) {
|
||||
std::visit(DoTransition(this),
|
||||
Transition{UnwindFunctionCall{TupleValue::Empty()}});
|
||||
@@ -1131,64 +1134,65 @@ void Interpreter::Step() {
|
||||
auto Interpreter::InterpProgram(llvm::ArrayRef<Nonnull<Declaration*>> fs,
|
||||
Nonnull<const Expression*> call_main) -> int {
|
||||
// Check that the interpreter is in a clean state.
|
||||
CHECK(globals.IsEmpty());
|
||||
CHECK(stack.IsEmpty());
|
||||
CHECK(program_value == std::nullopt);
|
||||
CHECK(globals_.IsEmpty());
|
||||
CHECK(stack_.IsEmpty());
|
||||
CHECK(program_value_ == std::nullopt);
|
||||
|
||||
if (trace_) {
|
||||
llvm::outs() << "********** initializing globals **********\n";
|
||||
}
|
||||
InitGlobals(fs);
|
||||
|
||||
auto todo = Stack<Nonnull<Action*>>(arena->New<ExpressionAction>(call_main));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(globals));
|
||||
stack = Stack<Nonnull<Frame*>>(arena->New<Frame>("top", scopes, todo));
|
||||
auto todo = Stack<Nonnull<Action*>>(arena_->New<ExpressionAction>(call_main));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena_->New<Scope>(globals_));
|
||||
stack_ = Stack<Nonnull<Frame*>>(arena_->New<Frame>("top", scopes, todo));
|
||||
|
||||
if (trace_) {
|
||||
llvm::outs() << "********** calling main function **********\n";
|
||||
PrintState(llvm::outs());
|
||||
}
|
||||
|
||||
while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) {
|
||||
while (stack_.Count() > 1 || !stack_.Top()->todo.IsEmpty()) {
|
||||
Step();
|
||||
if (trace_) {
|
||||
PrintState(llvm::outs());
|
||||
}
|
||||
}
|
||||
return cast<IntValue>(**program_value).value();
|
||||
return cast<IntValue>(**program_value_).value();
|
||||
}
|
||||
|
||||
auto Interpreter::InterpExp(Env values, Nonnull<const Expression*> e)
|
||||
-> Nonnull<const Value*> {
|
||||
CHECK(program_value == std::nullopt);
|
||||
CHECK(program_value_ == std::nullopt);
|
||||
auto program_value_guard =
|
||||
llvm::make_scope_exit([&] { program_value = std::nullopt; });
|
||||
auto todo = Stack<Nonnull<Action*>>(arena->New<ExpressionAction>(e));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(values));
|
||||
stack = Stack<Nonnull<Frame*>>(arena->New<Frame>("InterpExp", scopes, todo));
|
||||
llvm::make_scope_exit([&] { program_value_ = std::nullopt; });
|
||||
auto todo = Stack<Nonnull<Action*>>(arena_->New<ExpressionAction>(e));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena_->New<Scope>(values));
|
||||
stack_ =
|
||||
Stack<Nonnull<Frame*>>(arena_->New<Frame>("InterpExp", scopes, todo));
|
||||
|
||||
while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) {
|
||||
while (stack_.Count() > 1 || !stack_.Top()->todo.IsEmpty()) {
|
||||
Step();
|
||||
}
|
||||
CHECK(program_value != std::nullopt);
|
||||
return *program_value;
|
||||
CHECK(program_value_ != std::nullopt);
|
||||
return *program_value_;
|
||||
}
|
||||
|
||||
auto Interpreter::InterpPattern(Env values, Nonnull<const Pattern*> p)
|
||||
-> Nonnull<const Value*> {
|
||||
CHECK(program_value == std::nullopt);
|
||||
CHECK(program_value_ == std::nullopt);
|
||||
auto program_value_guard =
|
||||
llvm::make_scope_exit([&] { program_value = std::nullopt; });
|
||||
auto todo = Stack<Nonnull<Action*>>(arena->New<PatternAction>(p));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(values));
|
||||
stack =
|
||||
Stack<Nonnull<Frame*>>(arena->New<Frame>("InterpPattern", scopes, todo));
|
||||
llvm::make_scope_exit([&] { program_value_ = std::nullopt; });
|
||||
auto todo = Stack<Nonnull<Action*>>(arena_->New<PatternAction>(p));
|
||||
auto scopes = Stack<Nonnull<Scope*>>(arena_->New<Scope>(values));
|
||||
stack_ =
|
||||
Stack<Nonnull<Frame*>>(arena_->New<Frame>("InterpPattern", scopes, todo));
|
||||
|
||||
while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) {
|
||||
while (stack_.Count() > 1 || !stack_.Top()->todo.IsEmpty()) {
|
||||
Step();
|
||||
}
|
||||
CHECK(program_value != std::nullopt);
|
||||
return *program_value;
|
||||
CHECK(program_value_ != std::nullopt);
|
||||
return *program_value_;
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -26,7 +26,7 @@ using Env = Dictionary<std::string, Address>;
|
||||
class Interpreter {
|
||||
public:
|
||||
explicit Interpreter(Nonnull<Arena*> arena, bool trace)
|
||||
: arena(arena), globals(arena), heap(arena), trace_(trace) {}
|
||||
: arena_(arena), globals_(arena), heap_(arena), trace_(trace) {}
|
||||
|
||||
// Interpret the whole program.
|
||||
auto InterpProgram(llvm::ArrayRef<Nonnull<Declaration*>> fs,
|
||||
@@ -47,7 +47,7 @@ class Interpreter {
|
||||
|
||||
// Support TypeChecker allocating values on the heap.
|
||||
auto AllocateValue(Nonnull<const Value*> v) -> Address {
|
||||
return heap.AllocateValue(v);
|
||||
return heap_.AllocateValue(v);
|
||||
}
|
||||
|
||||
void InitEnv(const Declaration& d, Env* env);
|
||||
@@ -152,14 +152,14 @@ class Interpreter {
|
||||
|
||||
void PrintState(llvm::raw_ostream& out);
|
||||
|
||||
Nonnull<Arena*> arena;
|
||||
Nonnull<Arena*> arena_;
|
||||
|
||||
// Globally-defined entities, such as functions, structs, or choices.
|
||||
Env globals;
|
||||
Env globals_;
|
||||
|
||||
Stack<Nonnull<Frame*>> stack;
|
||||
Heap heap;
|
||||
std::optional<Nonnull<const Value*>> program_value;
|
||||
Stack<Nonnull<Frame*>> stack_;
|
||||
Heap heap_;
|
||||
std::optional<Nonnull<const Value*>> program_value_;
|
||||
|
||||
bool trace_;
|
||||
};
|
||||
|
||||
@@ -26,15 +26,15 @@ struct Stack {
|
||||
explicit Stack(T x) : Stack() { Push(std::move(x)); }
|
||||
|
||||
// Pushes `x` onto the top of the stack.
|
||||
void Push(T x) { elements.push_back(std::move(x)); }
|
||||
void Push(T x) { elements_.push_back(std::move(x)); }
|
||||
|
||||
// Removes and returns the top element of the stack.
|
||||
//
|
||||
// - Requires: !this->IsEmpty()
|
||||
auto Pop() -> T {
|
||||
CHECK(!IsEmpty()) << "Can't pop from empty stack.";
|
||||
auto r = std::move(elements.back());
|
||||
elements.pop_back();
|
||||
auto r = std::move(elements_.back());
|
||||
elements_.pop_back();
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ struct Stack {
|
||||
// - Requires: n >= 0 && n <= Count()
|
||||
void Pop(int n) {
|
||||
CHECK(n >= 0) << "Negative pop count disallowed.";
|
||||
CHECK(static_cast<size_t>(n) <= elements.size())
|
||||
CHECK(static_cast<size_t>(n) <= elements_.size())
|
||||
<< "Can only pop as many elements as stack has.";
|
||||
elements.erase(elements.end() - n, elements.end());
|
||||
elements_.erase(elements_.end() - n, elements_.end());
|
||||
}
|
||||
|
||||
// Returns the top element of the stack.
|
||||
@@ -53,21 +53,21 @@ struct Stack {
|
||||
// - Requires: !this->IsEmpty()
|
||||
auto Top() const -> T {
|
||||
CHECK(!IsEmpty()) << "Empty stack has no Top().";
|
||||
return elements.back();
|
||||
return elements_.back();
|
||||
}
|
||||
|
||||
// Returns `true` iff `Count() > 0`.
|
||||
auto IsEmpty() const -> bool { return elements.empty(); }
|
||||
auto IsEmpty() const -> bool { return elements_.empty(); }
|
||||
|
||||
// Returns the number of elements in `*this`.
|
||||
auto Count() const -> int { return elements.size(); }
|
||||
auto Count() const -> int { return elements_.size(); }
|
||||
|
||||
// Iterates over the Stack from top to bottom.
|
||||
auto begin() const -> const_iterator { return elements.crbegin(); }
|
||||
auto end() const -> const_iterator { return elements.crend(); }
|
||||
auto begin() const -> const_iterator { return elements_.crbegin(); }
|
||||
auto end() const -> const_iterator { return elements_.crend(); }
|
||||
|
||||
private:
|
||||
std::vector<T> elements;
|
||||
std::vector<T> elements_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -369,7 +369,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
|
||||
for (const auto& elt : cast<TupleValue>(*type).elements()) {
|
||||
elts.push_back(Substitute(dict, elt));
|
||||
}
|
||||
return arena->New<TupleValue>(elts);
|
||||
return arena_->New<TupleValue>(elts);
|
||||
}
|
||||
case Value::Kind::StructType: {
|
||||
VarValues fields;
|
||||
@@ -377,17 +377,17 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
|
||||
auto new_type = Substitute(dict, value);
|
||||
fields.push_back({name, new_type});
|
||||
}
|
||||
return arena->New<StructType>(std::move(fields));
|
||||
return arena_->New<StructType>(std::move(fields));
|
||||
}
|
||||
case Value::Kind::FunctionType: {
|
||||
const auto& fn_type = cast<FunctionType>(*type);
|
||||
auto param = Substitute(dict, &fn_type.parameters());
|
||||
auto ret = Substitute(dict, &fn_type.return_type());
|
||||
return arena->New<FunctionType>(std::vector<GenericBinding>(), param,
|
||||
ret);
|
||||
return arena_->New<FunctionType>(std::vector<GenericBinding>(), param,
|
||||
ret);
|
||||
}
|
||||
case Value::Kind::PointerType: {
|
||||
return arena->New<PointerType>(
|
||||
return arena_->New<PointerType>(
|
||||
Substitute(dict, &cast<PointerType>(*type).type()));
|
||||
}
|
||||
case Value::Kind::AutoType:
|
||||
@@ -421,7 +421,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
llvm::outs() << "checking expression " << *e << "\ntypes: ";
|
||||
PrintTypeEnv(types, llvm::outs());
|
||||
llvm::outs() << "\nvalues: ";
|
||||
interpreter.PrintEnv(values, llvm::outs());
|
||||
interpreter_.PrintEnv(values, llvm::outs());
|
||||
llvm::outs() << "\n";
|
||||
}
|
||||
switch (e->kind()) {
|
||||
@@ -433,7 +433,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
case Value::Kind::TupleValue: {
|
||||
const auto& tuple_type = cast<TupleValue>(aggregate_type);
|
||||
int i =
|
||||
cast<IntValue>(*interpreter.InterpExp(values, &index.offset()))
|
||||
cast<IntValue>(*interpreter_.InterpExp(values, &index.offset()))
|
||||
.value();
|
||||
if (i < 0 || i >= static_cast<int>(tuple_type.elements().size())) {
|
||||
FATAL_COMPILATION_ERROR(e->source_loc())
|
||||
@@ -454,7 +454,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
new_types = arg_res.types;
|
||||
arg_types.push_back(&arg->static_type());
|
||||
}
|
||||
SetStaticType(e, arena->New<TupleValue>(std::move(arg_types)));
|
||||
SetStaticType(e, arena_->New<TupleValue>(std::move(arg_types)));
|
||||
return TCResult(new_types);
|
||||
}
|
||||
case Expression::Kind::StructLiteral: {
|
||||
@@ -467,7 +467,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
new_args.push_back(FieldInitializer(arg.name(), &arg.expression()));
|
||||
arg_types.push_back({arg.name(), &arg.expression().static_type()});
|
||||
}
|
||||
SetStaticType(e, arena->New<StructType>(std::move(arg_types)));
|
||||
SetStaticType(e, arena_->New<StructType>(std::move(arg_types)));
|
||||
return TCResult(new_types);
|
||||
}
|
||||
case Expression::Kind::StructTypeLiteral: {
|
||||
@@ -478,7 +478,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
auto arg_res = TypeCheckExp(&arg.expression(), new_types, values);
|
||||
new_types = arg_res.types;
|
||||
ExpectIsConcreteType(arg.expression().source_loc(),
|
||||
interpreter.InterpExp(values, &arg.expression()));
|
||||
interpreter_.InterpExp(values, &arg.expression()));
|
||||
new_args.push_back(FieldInitializer(arg.name(), &arg.expression()));
|
||||
}
|
||||
if (struct_type.fields().empty()) {
|
||||
@@ -486,9 +486,9 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
// This applies only if there are no fields, because (unlike with
|
||||
// tuples) non-empty struct types are syntactically disjoint
|
||||
// from non-empty struct values.
|
||||
SetStaticType(&struct_type, arena->New<StructType>());
|
||||
SetStaticType(&struct_type, arena_->New<StructType>());
|
||||
} else {
|
||||
SetStaticType(&struct_type, arena->New<TypeType>());
|
||||
SetStaticType(&struct_type, arena_->New<TypeType>());
|
||||
}
|
||||
return TCResult(new_types);
|
||||
}
|
||||
@@ -533,7 +533,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
const auto& choice = cast<ChoiceType>(aggregate_type);
|
||||
for (const auto& vt : choice.alternatives()) {
|
||||
if (access.field() == vt.first) {
|
||||
SetStaticType(&access, arena->New<FunctionType>(
|
||||
SetStaticType(&access, arena_->New<FunctionType>(
|
||||
std::vector<GenericBinding>(),
|
||||
vt.second, &aggregate_type));
|
||||
return TCResult(res.types);
|
||||
@@ -561,10 +561,10 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
}
|
||||
}
|
||||
case Expression::Kind::IntLiteral:
|
||||
SetStaticType(e, arena->New<IntType>());
|
||||
SetStaticType(e, arena_->New<IntType>());
|
||||
return TCResult(types);
|
||||
case Expression::Kind::BoolLiteral:
|
||||
SetStaticType(e, arena->New<BoolType>());
|
||||
SetStaticType(e, arena_->New<BoolType>());
|
||||
return TCResult(types);
|
||||
case Expression::Kind::PrimitiveOperatorExpression: {
|
||||
auto& op = cast<PrimitiveOperatorExpression>(*e);
|
||||
@@ -579,60 +579,60 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
}
|
||||
switch (op.op()) {
|
||||
case Operator::Neg:
|
||||
ExpectExactType(e->source_loc(), "negation", arena->New<IntType>(),
|
||||
ExpectExactType(e->source_loc(), "negation", arena_->New<IntType>(),
|
||||
ts[0]);
|
||||
SetStaticType(&op, arena->New<IntType>());
|
||||
SetStaticType(&op, arena_->New<IntType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Add:
|
||||
ExpectExactType(e->source_loc(), "addition(1)", arena->New<IntType>(),
|
||||
ts[0]);
|
||||
ExpectExactType(e->source_loc(), "addition(2)", arena->New<IntType>(),
|
||||
ts[1]);
|
||||
SetStaticType(&op, arena->New<IntType>());
|
||||
ExpectExactType(e->source_loc(), "addition(1)",
|
||||
arena_->New<IntType>(), ts[0]);
|
||||
ExpectExactType(e->source_loc(), "addition(2)",
|
||||
arena_->New<IntType>(), ts[1]);
|
||||
SetStaticType(&op, arena_->New<IntType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Sub:
|
||||
ExpectExactType(e->source_loc(), "subtraction(1)",
|
||||
arena->New<IntType>(), ts[0]);
|
||||
arena_->New<IntType>(), ts[0]);
|
||||
ExpectExactType(e->source_loc(), "subtraction(2)",
|
||||
arena->New<IntType>(), ts[1]);
|
||||
SetStaticType(&op, arena->New<IntType>());
|
||||
arena_->New<IntType>(), ts[1]);
|
||||
SetStaticType(&op, arena_->New<IntType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Mul:
|
||||
ExpectExactType(e->source_loc(), "multiplication(1)",
|
||||
arena->New<IntType>(), ts[0]);
|
||||
arena_->New<IntType>(), ts[0]);
|
||||
ExpectExactType(e->source_loc(), "multiplication(2)",
|
||||
arena->New<IntType>(), ts[1]);
|
||||
SetStaticType(&op, arena->New<IntType>());
|
||||
arena_->New<IntType>(), ts[1]);
|
||||
SetStaticType(&op, arena_->New<IntType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::And:
|
||||
ExpectExactType(e->source_loc(), "&&(1)", arena->New<BoolType>(),
|
||||
ExpectExactType(e->source_loc(), "&&(1)", arena_->New<BoolType>(),
|
||||
ts[0]);
|
||||
ExpectExactType(e->source_loc(), "&&(2)", arena->New<BoolType>(),
|
||||
ExpectExactType(e->source_loc(), "&&(2)", arena_->New<BoolType>(),
|
||||
ts[1]);
|
||||
SetStaticType(&op, arena->New<BoolType>());
|
||||
SetStaticType(&op, arena_->New<BoolType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Or:
|
||||
ExpectExactType(e->source_loc(), "||(1)", arena->New<BoolType>(),
|
||||
ExpectExactType(e->source_loc(), "||(1)", arena_->New<BoolType>(),
|
||||
ts[0]);
|
||||
ExpectExactType(e->source_loc(), "||(2)", arena->New<BoolType>(),
|
||||
ExpectExactType(e->source_loc(), "||(2)", arena_->New<BoolType>(),
|
||||
ts[1]);
|
||||
SetStaticType(&op, arena->New<BoolType>());
|
||||
SetStaticType(&op, arena_->New<BoolType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Not:
|
||||
ExpectExactType(e->source_loc(), "!", arena->New<BoolType>(), ts[0]);
|
||||
SetStaticType(&op, arena->New<BoolType>());
|
||||
ExpectExactType(e->source_loc(), "!", arena_->New<BoolType>(), ts[0]);
|
||||
SetStaticType(&op, arena_->New<BoolType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Eq:
|
||||
ExpectExactType(e->source_loc(), "==", ts[0], ts[1]);
|
||||
SetStaticType(&op, arena->New<BoolType>());
|
||||
SetStaticType(&op, arena_->New<BoolType>());
|
||||
return TCResult(new_types);
|
||||
case Operator::Deref:
|
||||
ExpectPointerType(e->source_loc(), "*", ts[0]);
|
||||
SetStaticType(&op, &cast<PointerType>(*ts[0]).type());
|
||||
return TCResult(new_types);
|
||||
case Operator::Ptr:
|
||||
ExpectExactType(e->source_loc(), "*", arena->New<TypeType>(), ts[0]);
|
||||
SetStaticType(&op, arena->New<TypeType>());
|
||||
ExpectExactType(e->source_loc(), "*", arena_->New<TypeType>(), ts[0]);
|
||||
SetStaticType(&op, arena_->New<TypeType>());
|
||||
return TCResult(new_types);
|
||||
}
|
||||
break;
|
||||
@@ -648,7 +648,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
Nonnull<const Value*> return_type = &fun_t.return_type();
|
||||
if (!fun_t.deduced().empty()) {
|
||||
auto deduced_args =
|
||||
ArgumentDeduction(e->source_loc(), TypeEnv(arena), parameters,
|
||||
ArgumentDeduction(e->source_loc(), TypeEnv(arena_), parameters,
|
||||
&call.argument().static_type());
|
||||
for (auto& deduced_param : fun_t.deduced()) {
|
||||
// TODO: change the following to a CHECK once the real checking
|
||||
@@ -679,14 +679,14 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
case Expression::Kind::FunctionTypeLiteral: {
|
||||
auto& fn = cast<FunctionTypeLiteral>(*e);
|
||||
ExpectIsConcreteType(fn.parameter().source_loc(),
|
||||
interpreter.InterpExp(values, &fn.parameter()));
|
||||
interpreter_.InterpExp(values, &fn.parameter()));
|
||||
ExpectIsConcreteType(fn.return_type().source_loc(),
|
||||
interpreter.InterpExp(values, &fn.return_type()));
|
||||
SetStaticType(&fn, arena->New<TypeType>());
|
||||
interpreter_.InterpExp(values, &fn.return_type()));
|
||||
SetStaticType(&fn, arena_->New<TypeType>());
|
||||
return TCResult(types);
|
||||
}
|
||||
case Expression::Kind::StringLiteral:
|
||||
SetStaticType(e, arena->New<StringType>());
|
||||
SetStaticType(e, arena_->New<StringType>());
|
||||
return TCResult(types);
|
||||
case Expression::Kind::IntrinsicExpression:
|
||||
switch (cast<IntrinsicExpression>(*e).intrinsic()) {
|
||||
@@ -699,7 +699,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
|
||||
case Expression::Kind::StringTypeLiteral:
|
||||
case Expression::Kind::TypeTypeLiteral:
|
||||
case Expression::Kind::ContinuationTypeLiteral:
|
||||
SetStaticType(e, arena->New<TypeType>());
|
||||
SetStaticType(e, arena_->New<TypeType>());
|
||||
return TCResult(types);
|
||||
}
|
||||
}
|
||||
@@ -715,24 +715,24 @@ auto TypeChecker::TypeCheckPattern(
|
||||
llvm::outs() << "\ntypes: ";
|
||||
PrintTypeEnv(types, llvm::outs());
|
||||
llvm::outs() << "\nvalues: ";
|
||||
interpreter.PrintEnv(values, llvm::outs());
|
||||
interpreter_.PrintEnv(values, llvm::outs());
|
||||
llvm::outs() << "\n";
|
||||
}
|
||||
switch (p->kind()) {
|
||||
case Pattern::Kind::AutoPattern: {
|
||||
SetStaticType(p, arena->New<TypeType>());
|
||||
SetStaticType(p, arena_->New<TypeType>());
|
||||
return TCResult(types);
|
||||
}
|
||||
case Pattern::Kind::BindingPattern: {
|
||||
auto& binding = cast<BindingPattern>(*p);
|
||||
TypeCheckPattern(&binding.type(), types, values, std::nullopt);
|
||||
Nonnull<const Value*> type =
|
||||
interpreter.InterpPattern(values, &binding.type());
|
||||
interpreter_.InterpPattern(values, &binding.type());
|
||||
if (expected) {
|
||||
if (IsConcreteType(type)) {
|
||||
ExpectType(p->source_loc(), "name binding", type, *expected);
|
||||
} else {
|
||||
std::optional<Env> values = interpreter.PatternMatch(
|
||||
std::optional<Env> values = interpreter_.PatternMatch(
|
||||
type, *expected, binding.type().source_loc());
|
||||
if (values == std::nullopt) {
|
||||
FATAL_COMPILATION_ERROR(binding.type().source_loc())
|
||||
@@ -774,13 +774,13 @@ auto TypeChecker::TypeCheckPattern(
|
||||
new_types = field_result.types;
|
||||
field_types.push_back(&field->static_type());
|
||||
}
|
||||
SetStaticType(&tuple, arena->New<TupleValue>(std::move(field_types)));
|
||||
SetStaticType(&tuple, arena_->New<TupleValue>(std::move(field_types)));
|
||||
return TCResult(new_types);
|
||||
}
|
||||
case Pattern::Kind::AlternativePattern: {
|
||||
auto& alternative = cast<AlternativePattern>(*p);
|
||||
Nonnull<const Value*> choice_type =
|
||||
interpreter.InterpExp(values, &alternative.choice_type());
|
||||
interpreter_.InterpExp(values, &alternative.choice_type());
|
||||
if (choice_type->kind() != Value::Kind::ChoiceType) {
|
||||
FATAL_COMPILATION_ERROR(alternative.source_loc())
|
||||
<< "alternative pattern does not name a choice type.";
|
||||
@@ -841,7 +841,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
auto& while_stmt = cast<While>(*s);
|
||||
TypeCheckExp(&while_stmt.condition(), types, values);
|
||||
ExpectType(s->source_loc(), "condition of `while`",
|
||||
arena->New<BoolType>(), &while_stmt.condition().static_type());
|
||||
arena_->New<BoolType>(),
|
||||
&while_stmt.condition().static_type());
|
||||
TypeCheckStmt(&while_stmt.body(), types, values, return_type_context);
|
||||
return TCResult(types);
|
||||
}
|
||||
@@ -891,7 +892,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
case Statement::Kind::If: {
|
||||
auto& if_stmt = cast<If>(*s);
|
||||
TypeCheckExp(&if_stmt.condition(), types, values);
|
||||
ExpectType(s->source_loc(), "condition of `if`", arena->New<BoolType>(),
|
||||
ExpectType(s->source_loc(), "condition of `if`", arena_->New<BoolType>(),
|
||||
&if_stmt.condition().static_type());
|
||||
TypeCheckStmt(&if_stmt.then_statement(), types, values,
|
||||
return_type_context);
|
||||
@@ -931,14 +932,15 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
case Statement::Kind::Continuation: {
|
||||
auto& cont = cast<Continuation>(*s);
|
||||
TypeCheckStmt(&cont.body(), types, values, return_type_context);
|
||||
types.Set(cont.continuation_variable(), arena->New<ContinuationType>());
|
||||
types.Set(cont.continuation_variable(), arena_->New<ContinuationType>());
|
||||
return TCResult(types);
|
||||
}
|
||||
case Statement::Kind::Run: {
|
||||
auto& run = cast<Run>(*s);
|
||||
TypeCheckExp(&run.argument(), types, values);
|
||||
ExpectType(s->source_loc(), "argument of `run`",
|
||||
arena->New<ContinuationType>(), &run.argument().static_type());
|
||||
arena_->New<ContinuationType>(),
|
||||
&run.argument().static_type());
|
||||
return TCResult(types);
|
||||
}
|
||||
case Statement::Kind::Await: {
|
||||
@@ -1030,18 +1032,18 @@ auto TypeChecker::TypeCheckFunDef(FunctionDeclaration* f, TypeEnv types,
|
||||
Env values) -> TCResult {
|
||||
// Bring the deduced parameters into scope
|
||||
for (const auto& deduced : f->deduced_parameters()) {
|
||||
// auto t = interpreter.InterpExp(values, deduced.type);
|
||||
types.Set(deduced.name, arena->New<VariableType>(deduced.name));
|
||||
Address a = interpreter.AllocateValue(*types.Get(deduced.name));
|
||||
// auto t = interpreter_.InterpExp(values, deduced.type);
|
||||
types.Set(deduced.name, arena_->New<VariableType>(deduced.name));
|
||||
Address a = interpreter_.AllocateValue(*types.Get(deduced.name));
|
||||
values.Set(deduced.name, a);
|
||||
}
|
||||
// Type check the parameter pattern
|
||||
auto param_res =
|
||||
TypeCheckPattern(&f->param_pattern(), types, values, std::nullopt);
|
||||
// Evaluate the return type expression
|
||||
auto return_type = interpreter.InterpPattern(values, &f->return_type());
|
||||
auto return_type = interpreter_.InterpPattern(values, &f->return_type());
|
||||
if (f->name() == "main") {
|
||||
ExpectType(f->source_loc(), "return type of `main`", arena->New<IntType>(),
|
||||
ExpectType(f->source_loc(), "return type of `main`", arena_->New<IntType>(),
|
||||
return_type);
|
||||
// TODO: Check that main doesn't have any parameters.
|
||||
}
|
||||
@@ -1060,9 +1062,9 @@ auto TypeChecker::TypeCheckFunDef(FunctionDeclaration* f, TypeEnv types,
|
||||
ExpectReturnOnAllPaths(body_stmt, f->source_loc());
|
||||
}
|
||||
ExpectIsConcreteType(f->return_type().source_loc(), return_type);
|
||||
SetStaticType(f, arena->New<FunctionType>(f->deduced_parameters(),
|
||||
&f->param_pattern().static_type(),
|
||||
return_type));
|
||||
SetStaticType(f, arena_->New<FunctionType>(f->deduced_parameters(),
|
||||
&f->param_pattern().static_type(),
|
||||
return_type));
|
||||
return TCResult(types);
|
||||
}
|
||||
|
||||
@@ -1071,22 +1073,23 @@ auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values,
|
||||
-> Nonnull<const Value*> {
|
||||
// Bring the deduced parameters into scope
|
||||
for (const auto& deduced : fun_def->deduced_parameters()) {
|
||||
// auto t = interpreter.InterpExp(values, deduced.type);
|
||||
types.Set(deduced.name, arena->New<VariableType>(deduced.name));
|
||||
Address a = interpreter.AllocateValue(*types.Get(deduced.name));
|
||||
// auto t = interpreter_.InterpExp(values, deduced.type);
|
||||
types.Set(deduced.name, arena_->New<VariableType>(deduced.name));
|
||||
Address a = interpreter_.AllocateValue(*types.Get(deduced.name));
|
||||
values.Set(deduced.name, a);
|
||||
}
|
||||
// Type check the parameter pattern
|
||||
TypeCheckPattern(&fun_def->param_pattern(), types, values, std::nullopt);
|
||||
// Evaluate the return type expression
|
||||
auto ret = interpreter.InterpPattern(values, &fun_def->return_type());
|
||||
auto ret = interpreter_.InterpPattern(values, &fun_def->return_type());
|
||||
if (ret->kind() == Value::Kind::AutoType) {
|
||||
// FIXME do this unconditionally?
|
||||
TypeCheckFunDef(fun_def, types, values);
|
||||
return &fun_def->static_type();
|
||||
}
|
||||
return arena->New<FunctionType>(fun_def->deduced_parameters(),
|
||||
&fun_def->param_pattern().static_type(), ret);
|
||||
return arena_->New<FunctionType>(fun_def->deduced_parameters(),
|
||||
&fun_def->param_pattern().static_type(),
|
||||
ret);
|
||||
}
|
||||
|
||||
auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/,
|
||||
@@ -1106,14 +1109,14 @@ auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/,
|
||||
FATAL_COMPILATION_ERROR(binding.source_loc())
|
||||
<< "Struct members must have explicit types";
|
||||
}
|
||||
auto type = interpreter.InterpExp(ct_top, &binding_type->expression());
|
||||
auto type = interpreter_.InterpExp(ct_top, &binding_type->expression());
|
||||
fields.push_back(std::make_pair(*binding.name(), type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return arena->New<NominalClassType>(sd->name(), std::move(fields),
|
||||
std::move(methods));
|
||||
return arena_->New<NominalClassType>(sd->name(), std::move(fields),
|
||||
std::move(methods));
|
||||
}
|
||||
|
||||
static auto GetName(const Declaration& d) -> const std::string& {
|
||||
@@ -1163,7 +1166,7 @@ void TypeChecker::TypeCheck(Nonnull<Declaration*> d, const TypeEnv& types,
|
||||
<< "Type of a top-level variable must be an expression.";
|
||||
}
|
||||
Nonnull<const Value*> declared_type =
|
||||
interpreter.InterpExp(values, &binding_type->expression());
|
||||
interpreter_.InterpExp(values, &binding_type->expression());
|
||||
ExpectType(var.source_loc(), "initializer of variable", declared_type,
|
||||
&var.initializer().static_type());
|
||||
return;
|
||||
@@ -1177,7 +1180,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
FunctionDeclaration& func_def = cast<FunctionDeclaration>(*d);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1185,7 +1188,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
const ClassDefinition& class_def =
|
||||
cast<ClassDeclaration>(*d).definition();
|
||||
auto st = TypeOfClassDef(&class_def, tops->types, tops->values);
|
||||
Address a = interpreter.AllocateValue(st);
|
||||
Address a = interpreter_.AllocateValue(st);
|
||||
tops->values.Set(class_def.name(), a); // Is this obsolete?
|
||||
tops->types.Set(class_def.name(), st);
|
||||
break;
|
||||
@@ -1195,11 +1198,11 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
const auto& choice = cast<ChoiceDeclaration>(*d);
|
||||
VarValues alts;
|
||||
for (const auto& alternative : choice.alternatives()) {
|
||||
auto t = interpreter.InterpExp(tops->values, &alternative.signature());
|
||||
auto t = interpreter_.InterpExp(tops->values, &alternative.signature());
|
||||
alts.push_back(std::make_pair(alternative.name(), t));
|
||||
}
|
||||
auto ct = arena->New<ChoiceType>(choice.name(), std::move(alts));
|
||||
Address a = interpreter.AllocateValue(ct);
|
||||
auto ct = arena_->New<ChoiceType>(choice.name(), std::move(alts));
|
||||
Address a = interpreter_.AllocateValue(ct);
|
||||
tops->values.Set(choice.name(), a); // Is this obsolete?
|
||||
tops->types.Set(choice.name(), ct);
|
||||
break;
|
||||
@@ -1212,7 +1215,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
Expression& type =
|
||||
cast<ExpressionPattern>(var.binding().type()).expression();
|
||||
Nonnull<const Value*> declared_type =
|
||||
interpreter.InterpExp(tops->values, &type);
|
||||
interpreter_.InterpExp(tops->values, &type);
|
||||
tops->types.Set(*var.binding().name(), declared_type);
|
||||
break;
|
||||
}
|
||||
@@ -1221,7 +1224,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
|
||||
auto TypeChecker::TopLevel(std::vector<Nonnull<Declaration*>>* fs)
|
||||
-> TypeCheckContext {
|
||||
TypeCheckContext tops(arena);
|
||||
TypeCheckContext tops(arena_);
|
||||
bool found_main = false;
|
||||
|
||||
for (auto const& d : *fs) {
|
||||
|
||||
@@ -21,7 +21,7 @@ using TypeEnv = Dictionary<std::string, Nonnull<const Value*>>;
|
||||
class TypeChecker {
|
||||
public:
|
||||
explicit TypeChecker(Nonnull<Arena*> arena, bool trace)
|
||||
: arena(arena), interpreter(arena, trace), trace_(trace) {}
|
||||
: arena_(arena), interpreter_(arena, trace), trace_(trace) {}
|
||||
|
||||
struct TypeCheckContext {
|
||||
explicit TypeCheckContext(Nonnull<Arena*> arena)
|
||||
@@ -137,8 +137,8 @@ class TypeChecker {
|
||||
auto Substitute(TypeEnv dict, Nonnull<const Value*> type)
|
||||
-> Nonnull<const Value*>;
|
||||
|
||||
Nonnull<Arena*> arena;
|
||||
Interpreter interpreter;
|
||||
Nonnull<Arena*> arena_;
|
||||
Interpreter interpreter_;
|
||||
|
||||
bool trace_;
|
||||
};
|
||||
|
||||
@@ -94,7 +94,7 @@ auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
|
||||
auto Value::GetField(Nonnull<Arena*> arena, const FieldPath& path,
|
||||
SourceLocation source_loc) const -> Nonnull<const Value*> {
|
||||
Nonnull<const Value*> value(this);
|
||||
for (const std::string& field : path.components) {
|
||||
for (const std::string& field : path.components_) {
|
||||
value = GetMember(arena, value, field, source_loc);
|
||||
}
|
||||
return value;
|
||||
@@ -154,7 +154,7 @@ auto Value::SetField(Nonnull<Arena*> arena, const FieldPath& path,
|
||||
Nonnull<const Value*> field_value,
|
||||
SourceLocation source_loc) const -> Nonnull<const Value*> {
|
||||
return SetFieldImpl(arena, Nonnull<const Value*>(this),
|
||||
path.components.begin(), path.components.end(),
|
||||
path.components_.begin(), path.components_.end(),
|
||||
field_value, source_loc);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class BisonWrap {
|
||||
public:
|
||||
// Assigning a value initializes the wrapper.
|
||||
auto operator=(T&& rhs) -> BisonWrap& {
|
||||
val = std::move(rhs);
|
||||
val_ = std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ class BisonWrap {
|
||||
// Deliberately releases the contained value. Errors if not initialized.
|
||||
// Called directly in parser.ypp when releasing pairs.
|
||||
auto Release() -> T {
|
||||
CHECK(val.has_value());
|
||||
T ret = std::move(*val);
|
||||
val.reset();
|
||||
CHECK(val_.has_value());
|
||||
T ret = std::move(*val_);
|
||||
val_.reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<T> val;
|
||||
std::optional<T> val_;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -18,13 +18,13 @@ class ParseAndLexContext {
|
||||
public:
|
||||
// Creates an instance analyzing the given input file.
|
||||
ParseAndLexContext(Nonnull<const std::string*> input_file_name, bool trace)
|
||||
: input_file_name(input_file_name), trace_(trace) {}
|
||||
: input_file_name_(input_file_name), trace_(trace) {}
|
||||
|
||||
// Writes a syntax error diagnostic containing message to standard error.
|
||||
auto PrintDiagnostic(const std::string& message) -> void;
|
||||
|
||||
auto source_loc() -> SourceLocation {
|
||||
return SourceLocation(input_file_name,
|
||||
return SourceLocation(input_file_name_,
|
||||
static_cast<int>(current_token_position.begin.line));
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class ParseAndLexContext {
|
||||
private:
|
||||
// A path to the file processed, relative to the current working directory
|
||||
// when *this is called.
|
||||
Nonnull<const std::string*> input_file_name;
|
||||
Nonnull<const std::string*> input_file_name_;
|
||||
|
||||
bool trace_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user