diff --git a/executable_semantics/interpreter/BUILD b/executable_semantics/interpreter/BUILD index 707cbbe9735a..0934c7fc0b86 100644 --- a/executable_semantics/interpreter/BUILD +++ b/executable_semantics/interpreter/BUILD @@ -18,8 +18,8 @@ cc_library( hdrs = [ "action.h", "assoc_list.h", - "cons_list.h", "interpreter.h", + "list_node.h", "stack.h", "typecheck.h", "value.h", diff --git a/executable_semantics/interpreter/action.h b/executable_semantics/interpreter/action.h index 8ce5be6210bf..72643287b1cc 100644 --- a/executable_semantics/interpreter/action.h +++ b/executable_semantics/interpreter/action.h @@ -10,7 +10,7 @@ #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/statement.h" -#include "executable_semantics/interpreter/cons_list.h" +#include "executable_semantics/interpreter/stack.h" #include "executable_semantics/interpreter/value.h" namespace Carbon { diff --git a/executable_semantics/interpreter/cons_list.h b/executable_semantics/interpreter/cons_list.h deleted file mode 100644 index 6340874e66a5..000000000000 --- a/executable_semantics/interpreter/cons_list.h +++ /dev/null @@ -1,40 +0,0 @@ -// 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_CONS_LIST_H_ -#define EXECUTABLE_SEMANTICS_INTERPRETER_CONS_LIST_H_ - -namespace Carbon { - -template -struct Stack; - -template -struct Cons { - friend struct Stack; - - private: - Cons(T e, Cons* n) : curr(e), next(n) {} - - const T curr; - Cons* const next; - - // Cons cells are part of a "persistent data structure" and are thus - // immutable. - Cons& operator=(const Cons&) = delete; - Cons& operator=(Cons&&) = delete; -}; - -template -auto Length(Cons* ls) -> unsigned int { - if (ls) { - return 1 + Length(ls->next); - } else { - return 0; - } -} - -} // namespace Carbon - -#endif // EXECUTABLE_SEMANTICS_INTERPRETER_CONS_LIST_H_ diff --git a/executable_semantics/interpreter/dictionary.h b/executable_semantics/interpreter/dictionary.h new file mode 100644 index 000000000000..4cec806a0984 --- /dev/null +++ b/executable_semantics/interpreter/dictionary.h @@ -0,0 +1,60 @@ +// 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_DICTIONARY_H_ +#define EXECUTABLE_SEMANTICS_INTERPRETER_DICTIONARY_H_ + +#include +#include +#include +#include + +#include "executable_semantics/interpreter/list_node.h" + +namespace Carbon { + +// A persistent dictionary with a simple implementation. +// Copying the dictionary is O(1) time. +template +class Dictionary { + public: + // Create an empty dictionary. + Dictionary() { head = nullptr; } + + // Return the value associated with the given key. + // Time complexity: O(n) where n is the number of times + // any value has been set across all keys. + auto Get(const K& key) -> std::optional { + for (auto kv : *this) { + if (kv.first == key) { + return kv.second; + } + } + return std::nullopt; + } + + // Associate the value v with key k in the dictionary. + // Time complexity: O(1). + auto Set(const K& k, const V& v) -> void { + head = new ListNode>(std::make_pair(k, v), head); + } + + typedef ListNodeIterator> Iterator; + + // The position of the first element of the dictionary + // or `end()` if the dictionary is empty. + auto begin() const -> Iterator { return Iterator(head); } + + // The position one past that of the last element. + auto end() const -> Iterator { return Iterator(nullptr); } + + private: + Dictionary(ListNode>* h) : head(h) {} + + ListNode>* head; +}; + +} // namespace Carbon + +#endif // EXECUTABLE_SEMANTICS_INTERPRETER_DICTIONARY_H_ diff --git a/executable_semantics/interpreter/list_node.h b/executable_semantics/interpreter/list_node.h new file mode 100644 index 000000000000..bf5ad15d9233 --- /dev/null +++ b/executable_semantics/interpreter/list_node.h @@ -0,0 +1,63 @@ +// 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_LIST_NODE_H_ +#define EXECUTABLE_SEMANTICS_INTERPRETER_LIST_NODE_H_ + +namespace Carbon { + +template +struct ListNode { + ListNode(T e, ListNode* n) : curr(e), next(n) {} + + const T curr; + ListNode* const next; + + // ListNode cells are part of a "persistent data structure" and are thus + // immutable. + ListNode& operator=(const ListNode&) = delete; + ListNode& operator=(ListNode&&) = delete; +}; + +// A forward iterator over elements of a `ListNode` list. +template +struct ListNodeIterator { + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = const T*; + using reference = const T&; + using iterator_category = std::forward_iterator_tag; + + ListNodeIterator(ListNode* x) : p(x) {} + ListNodeIterator(const ListNodeIterator& iter) : p(iter.p) {} + ListNodeIterator& operator++() { + p = p->next; + return *this; + } + ListNodeIterator operator++(int) { + ListNodeIterator tmp(*this); + operator++(); + return tmp; + } + bool operator==(const ListNodeIterator& rhs) const { return p == rhs.p; } + bool operator!=(const ListNodeIterator& rhs) const { return p != rhs.p; } + const T& operator*() { return p->curr; } + const T* operator->() { return &p->curr; } + + private: + ListNode* p; +}; + +template +auto Length(ListNode* ls) -> unsigned int { + if (ls) { + return 1 + Length(ls->next); + } else { + return 0; + } +} + +} // namespace Carbon + +#endif // EXECUTABLE_SEMANTICS_INTERPRETER_LIST_NODE_H_ diff --git a/executable_semantics/interpreter/stack.h b/executable_semantics/interpreter/stack.h index 6b0dee533bdb..eb2a8666ab7a 100644 --- a/executable_semantics/interpreter/stack.h +++ b/executable_semantics/interpreter/stack.h @@ -9,6 +9,8 @@ #include #include +#include "executable_semantics/interpreter/list_node.h" + namespace Carbon { /// A persistent stack data structure. @@ -24,7 +26,7 @@ struct Stack { using reference = const T&; using iterator_category = std::forward_iterator_tag; - Iterator(Cons* x) : p(x) {} + Iterator(ListNode* x) : p(x) {} Iterator(const Iterator& mit) : p(mit.p) {} Iterator& operator++() { p = p->next; @@ -41,7 +43,7 @@ struct Stack { const T* operator->() { return &p->curr; } private: - Cons* p; + ListNode* p; }; /// The position of the first/`Top()` element, or `end()` if @@ -58,7 +60,7 @@ struct Stack { Stack(T x) : Stack() { Push(x); } /// Pushes `x` onto the top of the stack. - void Push(T x) { head = new Cons(x, head); } + void Push(T x) { head = new ListNode(x, head); } /// Returns a copy of `*this`, with `x` pushed onto the top. auto Pushing(T x) const -> Stack { @@ -128,7 +130,7 @@ struct Stack { private: /// An linked list of cells containing the elements of self. - Cons* head; + ListNode* head; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index d9880d9dc26f..0e361f77dce0 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -12,7 +12,6 @@ #include #include "executable_semantics/ast/function_definition.h" -#include "executable_semantics/interpreter/cons_list.h" #include "executable_semantics/interpreter/interpreter.h" namespace Carbon {