@@ -36,6 +36,7 @@
36#include <string>
36#include <string>
37#include <array>
37#include <array>
38#include <deque>
38#include <deque>
39+#include <unordered_map>
39#include <utility>
40#include <utility>
40#include <stdexcept>
41#include <stdexcept>
41#include <iso646.h> // mostly for MS Visual Studio compiler
42#include <iso646.h> // mostly for MS Visual Studio compiler
@@ -61,14 +62,14 @@ namespace Private {
61 using Symbol = const SymbolGeneratorAnchor *;
62 using Symbol = const SymbolGeneratorAnchor *;
64−#define define_symbol(S) namespace PureScript { \
65+#define DEFINE_SYMBOL(S) namespace PureScript { \
65 namespace Private { \
66 namespace Private { \
66 namespace Symbols { \
67 namespace Symbols { \
67 struct S_ ## S {}; \
68 struct S_ ## S {}; \
71−#define symbol(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
72+#define SYM(S) (&Private::SymbolGenerator<::PureScript::Private::Symbols::S_ ## S>::anchor)
73constexpr bool undefined = false;
74constexpr bool undefined = false;
@@ -93,6 +94,7 @@ class any {
97 EffClosure,
99 EffClosure,
@@ -106,15 +108,17 @@ class any {
107 static constexpr as_thunk unthunk = as_thunk{};
109 static constexpr as_thunk unthunk = as_thunk{};
109− using map_pair = std::pair<const Private::Symbol, const any>;
111+ using dict_pair = std::pair<const Private::Symbol, const any>;
111 template <size_t N>
113 template <size_t N>
112− using map = std::array<const map_pair, N>;
114+ using dict = std::array<const dict_pair, N>;
114 template <size_t N>
116 template <size_t N>
115 using data = std::array<const any, N>;
117 using data = std::array<const any, N>;
117− using array = std::deque<any WITH_ALLOCATOR(any)>;
119+ using array = std::deque<any WITH_ALLOCATOR(any)>;
120+ using record = std::unordered_map<std::string, any WITH_ALLOCATOR(any)>;
118 using fn = auto (*)(const any&) -> any;
122 using fn = auto (*)(const any&) -> any;
119 using eff_fn = auto (*)() -> any;
123 using eff_fn = auto (*)() -> any;
120 using thunk = auto (*)(const as_thunk) -> const any&;
124 using thunk = auto (*)(const as_thunk) -> const any&;
@@ -164,6 +168,7 @@ class any {
164 mutable void * v;
168 mutable void * v;
165 mutable managed<string> s;
169 mutable managed<string> s;
166 mutable managed<array> a;
170 mutable managed<array> a;
171+ mutable managed<record> r;
167 mutable managed<Closure> l;
172 mutable managed<Closure> l;
168 mutable managed<EffClosure> k;
173 mutable managed<EffClosure> k;
169 mutable managed<void> p;
174 mutable managed<void> p;
@@ -191,7 +196,7 @@ class any {
191 any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
196 any(managed<string>&& val) noexcept : tag(Tag::String), s(std::move(val)) {}
193 template <size_t N>
198 template <size_t N>
194− any(map<N>&& val) noexcept : tag(Tag::Map), p(make_managed<map<N>>(std::move(val))) {}
199+ any(dict<N>&& val) noexcept : tag(Tag::Map), p(make_managed<dict<N>>(std::move(val))) {}
196 template <size_t N>
201 template <size_t N>
197 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
202 any(data<N>&& val) noexcept : tag(Tag::Data), p(make_managed<data<N>>(std::move(val))) {}
@@ -199,6 +204,9 @@ class any {
199 any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
204 any(const array& val) : tag(Tag::Array), a(make_managed<array>(val)) {}
200 any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
205 any(array&& val) noexcept : tag(Tag::Array), a(make_managed<array>(std::move(val))) {}
207+ any(const record& val) : tag(Tag::Record), r(make_managed<record>(val)) {}
208+ any(record&& val) noexcept : tag(Tag::Record), r(make_managed<record>(std::move(val))) {}
202 template <typename T>
210 template <typename T>
203 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
211 any(const T& val, typename std::enable_if<std::is_convertible<T,fn>::value>::type* = 0) noexcept
204 : tag(Tag::Function), f(val) {}
212 : tag(Tag::Function), f(val) {}
@@ -269,6 +277,7 @@ class any {
270 case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
278 case Tag::String: new (&s) managed<string>(move_if_rvalue<T>(other.s)); break;
271 case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
279 case Tag::Array: new (&a) managed<array>(move_if_rvalue<T>(other.a)); break;
280+ case Tag::Record: new (&r) managed<record>(move_if_rvalue<T>(other.r)); break;
272 case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
281 case Tag::Closure: new (&l) managed<Closure>(move_if_rvalue<T>(other.l)); break;
273 case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
282 case Tag::EffClosure: new (&k) managed<EffClosure>(move_if_rvalue<T>(other.k)); break;
274 case Tag::Map:
283 case Tag::Map:
@@ -283,6 +292,7 @@ class any {
283 switch (tag) {
292 switch (tag) {
284 case Tag::String: s.~managed<string>(); break;
293 case Tag::String: s.~managed<string>(); break;
285 case Tag::Array: a.~managed<array>(); break;
294 case Tag::Array: a.~managed<array>(); break;
295+ case Tag::Record: r.~managed<record>(); break;
286 case Tag::Closure: l.~managed<Closure>(); break;
296 case Tag::Closure: l.~managed<Closure>(); break;
287 case Tag::EffClosure: k.~managed<EffClosure>(); break;
297 case Tag::EffClosure: k.~managed<EffClosure>(); break;
288 case Tag::Map:
298 case Tag::Map:
@@ -337,9 +347,10 @@ class any {
337 operator const string&() const;
347 operator const string&() const;
338 operator const char *() const;
348 operator const char *() const;
339 operator const array&() const;
349 operator const array&() const;
350+ operator const record&() const;
341 auto operator[](const size_t) const -> const any&;
352 auto operator[](const size_t) const -> const any&;
342−
353+ auto at(const std::string&) const -> const any&;
343 auto size() const -> size_t;
354 auto size() const -> size_t;
344 auto empty() const -> bool;
355 auto empty() const -> bool;
345 auto contains(const Private::Symbol) const -> bool;
356 auto contains(const Private::Symbol) const -> bool;
@@ -419,7 +430,7 @@ namespace Private {
419 struct TagHelper {};
430 struct TagHelper {};
421 template <size_t N>
432 template <size_t N>
422− struct TagHelper<any::map<N>> {
433+ struct TagHelper<any::dict<N>> {
423 static constexpr any::Tag tag = any::Tag::Map;
434 static constexpr any::Tag tag = any::Tag::Map;
@@ -450,14 +461,16 @@ inline auto cast(const any& a) ->
450template <typename T>
461template <typename T>
451inline auto cast(const any& a) ->
462inline auto cast(const any& a) ->
452 typename std::enable_if<std::is_same<T, string>::value ||
463 typename std::enable_if<std::is_same<T, string>::value ||
453− std::is_same<T, any::array>::value, const T&>::type {
464+ std::is_same<T, any::array>::value ||
465+ std::is_same<T, any::record>::value, const T&>::type {
454 return a;
466 return a;
457template <typename T,
469template <typename T,
458 typename = typename std::enable_if<std::is_class<T>::value &&
470 typename = typename std::enable_if<std::is_class<T>::value &&
459 !std::is_same<T,string>::value &&
471 !std::is_same<T,string>::value &&
460− !std::is_same<T,any::array>::value>::type>
472+ !std::is_same<T,any::array>::value &&
473+ !std::is_same<T,any::record>::value>::type>
461inline auto cast(const any& a) -> T& {
474inline auto cast(const any& a) -> T& {
462 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
475 return *static_cast<T*>(a.extractPointer(IF_DEBUG(Private::TagHelper<T>::tag)));
@@ -476,7 +489,7 @@ inline auto cast(const any& a) ->
476 return a.rawPointer();
489 return a.rawPointer();
479−namespace map {
492+namespace dict {
480 template <size_t N, typename T>
493 template <size_t N, typename T>
481 inline auto get(const T& a) ->
494 inline auto get(const T& a) ->
482 typename std::enable_if<!std::is_same<any, T>::value, const any&>::type {
495 typename std::enable_if<!std::is_same<any, T>::value, const any&>::type {
@@ -485,29 +498,29 @@ namespace map {
486 template <size_t N>
499 template <size_t N>
487 inline auto get(const any& a) -> const any& {
500 inline auto get(const any& a) -> const any& {
488− return cast<any::map<N+1>>(a)[N].second;
501+ return cast<any::dict<N+1>>(a)[N].second;
491 template <size_t N>
504 template <size_t N>
492− inline auto get(const Private::Symbol key, const any::map<N>& a) -> const any& {
505+ inline auto get(const Private::Symbol key, const any::dict<N>& a) -> const any& {
493− static_assert(N > 0, "map size must be greater than zero");
506+ static_assert(N > 0, "dict size must be greater than zero");
494 typename std::remove_reference<decltype(a)>::type::size_type i = 0;
507 typename std::remove_reference<decltype(a)>::type::size_type i = 0;
496 if (a[i].first == key) {
509 if (a[i].first == key) {
497 return a[i].second;
510 return a[i].second;
499 } while (a[++i].first != nullptr);
512 } while (a[++i].first != nullptr);
500− assert(false && "map key not found");
513+ assert(false && "dict key not found");
501 static const any invalid_key(nullptr);
514 static const any invalid_key(nullptr);
502 return invalid_key;
515 return invalid_key;
505 inline auto get(const Private::Symbol key, const any& a) -> const any& {
518 inline auto get(const Private::Symbol key, const any& a) -> const any& {
506− return get(key, cast<any::map<unknown_size>>(a));
519+ return get(key, cast<any::dict<unknown_size>>(a));
509− #define P(N) any::map_pair&& arg ## N
522+ #define P(N) any::dict_pair&& arg ## N
510− #define T(N) any::map<N+1>
523+ #define T(N) any::dict<N+1>
511 #define E(N) std::forward<decltype(arg ## N)>(arg ## N)
524 #define E(N) std::forward<decltype(arg ## N)>(arg ## N)
512 #define M(...) {{ __VA_ARGS__, { nullptr, nullptr } }}
525 #define M(...) {{ __VA_ARGS__, { nullptr, nullptr } }}
@@ -542,8 +555,6 @@ namespace map {
545−namespace record = map;
547namespace data {
558namespace data {
548 template <size_t N, typename T>
559 template <size_t N, typename T>
549 inline auto get(const T& a) ->
560 inline auto get(const T& a) ->