Created
October 13, 2022 19:09
-
-
Save shawwn/63e0f010479efd95ebffdf2108645ad3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "maybe.hpp" | |
#include <concepts> | |
#include <numbers> | |
#include <limits> | |
#include <thread> | |
#include <sstream> | |
#include <string> | |
#include <utility> | |
#include <vector> | |
#include <map> | |
#include <functional> | |
#include <memory> | |
#include <iostream> | |
#include <any> | |
//using Object = std::any; | |
template<typename T> | |
using Object = std::is_object<T>; | |
template <typename T> | |
concept Shape = requires (const T& t) | |
{ | |
{ t.area() }; | |
}; | |
struct Foo { | |
float area() const { return 1.0f; } | |
}; | |
struct Bar { | |
}; | |
static_assert(Shape<Foo>); | |
static_assert(!Shape<Bar>); | |
template <typename T> | |
concept Seqable = requires (T t) { | |
{ t.seq() }; | |
}; | |
template<typename T> | |
concept IPersistentCollection = requires (T t) { | |
{ t.count() } -> std::same_as<size_t>; | |
{ t.cons({}) } /*-> std::same_as<IPersistentCollection<T, O>>*/; | |
{ t.empty() } /*-> std::same_as<IPersistentCollection<T, O>>*/; | |
{ t.equiv({}) } -> std::same_as<bool>; | |
}; | |
template <typename T> | |
concept ISeq = requires (T t) { | |
std::is_object_v<T>; | |
{ t.first() }; | |
{ t.next() }; | |
// { t.more() }; | |
{ t.cons({}) }; | |
}; | |
template <typename T> | |
struct ASeq {}; | |
template <typename T> | |
struct Cons : std::enable_shared_from_this<Cons<T>> { | |
maybe<T> car = nil; | |
maybe<std::shared_ptr<Cons<T>>> cdr = nil; | |
// auto getptr() { | |
// return shared_from_this(); | |
// } | |
Cons() { | |
static_assert(ISeq<Cons<T>>); | |
} | |
Cons(T car) : car(car) {} | |
Cons(T car, std::shared_ptr<Cons<T>> cdr) : car(car), cdr(cdr) {} | |
auto first() { return *car; } | |
auto next() { return *cdr; } | |
auto cons(auto x) { return Cons{x, std::shared_ptr<Cons<T>>(this)}; } | |
}; | |
using Any = std::any; | |
template<typename T> | |
requires std::is_integral_v<T> | |
static Any V(auto x) { | |
return x; | |
} | |
static Any V(auto x) { | |
return x; | |
} | |
static Any V(const char* s) { | |
return std::string(s); | |
} | |
static Any V(std::nullopt_t x) { | |
return x; | |
} | |
struct any_s { | |
Any val; | |
any_s(auto&& x) : val(V(std::move(x))) {} | |
operator Any() const { return val; } | |
operator Any&() { return val; } | |
}; | |
using any_t = Any; | |
struct Pair; | |
using pair_t = std::shared_ptr<Pair>; | |
static pair_t V(pair_t x) { return x; } | |
struct Pair : std::enable_shared_from_this<Pair> { | |
Any car = nil; | |
Any cdr = nil; | |
Pair(Any car, Any cdr) : car(std::move(car)), cdr(std::move(cdr)) {} | |
// auto getptr() { | |
// return shared_from_this(); | |
// } | |
Pair() { | |
static_assert(ISeq<Pair>); | |
} | |
Any first() const { return car; } | |
Any next() const { return cdr; } | |
pair_t cons(Any x) const; | |
// pair_t cons(any_t x) const { return cons(x.val); } | |
}; | |
pair_t join(auto x, auto y) { | |
return std::make_shared<Pair>(std::move(x), std::move(y)); | |
} | |
static pair_t join() { return join(nil, nil); } | |
pair_t join(auto x) { return join(x, nil); } | |
//pair_t join(auto x, const pair_t& y) { | |
// return y->cons(V(x)); | |
//} | |
//extern pair_t join(any_t x, any_t y); | |
template<typename T> | |
auto as(Any& x) { | |
return std::any_cast<T>(&x); | |
} | |
template<typename T> | |
auto as_a(Any& x, const T& y) { | |
return std::any_cast<T>(&x); | |
} | |
template<typename T> | |
auto as_a(Any& x) { | |
return std::any_cast<T>(&x); | |
} | |
template<typename T> | |
requires std::is_integral_v<T> | |
auto as(Any& x) { | |
if (auto it = as<T>(x)) { | |
return maybe<T>(it); | |
} | |
return nil; | |
} | |
static std::string type(any_t x) { | |
if (auto it = as<Any>(x)) | |
return type(*it); | |
else if (auto it = as<pair_t>(x)) | |
return "pair"; | |
else | |
return "symbol"; | |
} | |
template<typename T> | |
requires requires (T x) { !x; } | |
bool falsy(T x) { return !x; } | |
static bool falsy(std::nullopt_t x) { return true; } | |
static bool falsy(any_t x) { | |
if (auto v = as_a<bool>(x)) | |
return falsy(*v); | |
if (auto v = as_a(x, nil)) | |
return falsy(nil); | |
return false; | |
} | |
template<typename T> | |
requires std::is_reference_v<T> | |
bool id(any_t x, any_t y) { | |
if (auto a = as<T>(x)) { | |
if (auto b = as<T>(y)) { | |
return a == b; | |
} | |
} | |
return false; | |
} | |
template<typename T> | |
concept Comparable = requires (T x, T y) { x == y; }; | |
template<typename T> | |
bool id(Any x, T&& y) { | |
if (auto a = as_a(x, y)) | |
return id(*a, y); | |
return false; | |
} | |
template<typename T> | |
bool id(T&& x, Any y) { | |
if (auto a = as_a(y, x)) | |
return id(x, *a); | |
return false; | |
} | |
template<typename T> | |
requires Comparable<T> | |
bool id(T&& x, T&& y) { | |
return x == y; | |
} | |
//template<typename T> | |
//bool id(T&& x, any_t y) { | |
// return id(x, y.val); | |
//} | |
// | |
//template<typename T> | |
//bool id(any_t x, T&& y) { | |
// return id(x.val, y); | |
//} | |
//template<typename T> | |
//bool id(T&& x, T&& y) { | |
// return &x == &y; | |
//} | |
static bool id(any_t x, std::nullopt_t y) { | |
// return x.val.type().name() == Any(nil).type().name(); | |
if (auto it = std::any_cast<std::nullopt_t>(&x)) | |
return true; | |
return false; | |
} | |
static bool id(std::nullopt_t x, any_t y) { | |
return id(y, x); | |
} | |
static bool id(std::nullopt_t x, std::nullopt_t y) { | |
return true; | |
} | |
static bool no(any_t x) { | |
// return as<std::nullopt_t>(x); | |
// return id(std::move(x), nil); | |
return falsy(x); | |
} | |
static bool yes(auto x) { | |
return !no(x); | |
} | |
extern Any smark; | |
static bool atom(any_t x) { | |
return !id(type(x), type(smark)); | |
} | |
#include <cassert> | |
template<typename T> | |
maybe<T> ref(any_t x) { | |
if (auto v = as<T>(x)) | |
return *v; | |
return nil; | |
} | |
static Any car(const Pair& x) { return x.car; } | |
static Any cdr(const Pair& x) { return x.cdr; } | |
static Any car(pair_t x) { return x ? car(*x) : nil; } | |
static Any cdr(pair_t x) { return x ? cdr(*x) : nil; } | |
static Any car(maybe<pair_t> x) { return x ? car(*x) : nil; } | |
static Any cdr(maybe<pair_t> x) { return x ? cdr(*x) : nil; } | |
static Any car(const Any& x) { return no(x) ? x : car(ref<pair_t>(x)); } | |
static Any cdr(const Any& x) { return no(x) ? x : cdr(ref<pair_t>(x)); } | |
auto all(auto f, Any xs) { | |
while (true) { | |
if (no(xs)) | |
return true; | |
if (no(f(car(xs)))) | |
return false; | |
xs = cdr(xs); | |
} | |
// if (no(xs)) | |
// return true; | |
// if (yes(f(car(xs)))) | |
// return false; | |
// return all(f, cdr(xs)); | |
} | |
auto some(auto f, Any xs) { | |
while (true) { | |
if (no(xs)) | |
return xs; | |
if (yes(f(car(xs)))) | |
return xs; | |
xs = cdr(xs); | |
} | |
} | |
/* | |
(def reduce (f xs) | |
(if (no (cdr xs)) | |
(car xs) | |
(f (car xs) (reduce f (cdr xs))))) | |
*/ | |
auto reduce(auto f, Any xs) { | |
if (no(cdr(xs))) | |
return car(xs); | |
return f(car(xs), reduce(f, cdr(xs))); | |
} | |
static auto cons(Any x, Any y) { | |
return join(x, y); | |
} | |
auto cons(Any x, Any y, auto ...xs) { | |
return join(x, cons(y, xs...)); | |
} | |
static void str1(Any x, std::ostream& out) { | |
if (auto s = as<std::string>(x)) { | |
out << *s; | |
return; | |
} | |
else if (auto s = as<const char*>(x)) { | |
out << *s; | |
return; | |
} | |
else if (auto s = std::any_cast<std::nullopt_t>(&x)) { | |
out << "nil"; | |
return; | |
} else if (auto s = std::any_cast<char>(&x)) { | |
out << *s; | |
return; | |
} else if (auto s = std::any_cast<int>(&x)) { | |
out << *s; | |
return; | |
} else { | |
out << "#<type "; | |
out << x.type().name(); | |
out << ">"; | |
} | |
} | |
static void str(Any x, std::ostream& out, bool inside = false) { | |
if (atom(x)) { | |
return str1(x, out); | |
} | |
out << (inside ? " " : "("); | |
str(car(x), out); | |
if (yes(cdr(x))) { | |
if (atom(cdr(x))) | |
out << " . "; | |
str(cdr(x), out, true); | |
} | |
out << (inside ? "" : ")"); | |
} | |
static std::string str(Any x) { | |
std::ostringstream out; | |
str(x, out); | |
return out.str(); | |
} | |
static void disp(Any x) { | |
str(x, std::cout); | |
} | |
static Any pr1(Any x) { | |
disp(x); | |
return x; | |
} | |
static Any pr(auto x) { | |
disp(V(x)); | |
return x; | |
} | |
static Any pr(auto x, auto ...ys) { | |
return pr1(V(x)), pr(ys...); | |
} | |
static Any prn(auto x, auto ...ys) { | |
return pr(x, ys..., V("\n")); | |
} | |
// | |
//template<typename T> | |
//requires Comparable<T> | |
//bool id(Any x, Any y) { | |
// if (auto a = std::any_cast<T>(&x)) { | |
// if (auto b = std::any_cast<T>(&y)) { | |
// return *a == *b; | |
// } | |
// } | |
// return false; | |
//} | |
#include <iostream> | |
static void test_Cons() { | |
auto c0 = join(0); | |
auto c1 = join(1, c0); | |
// auto c2 = c->cons(2); | |
auto c2 = join("two", c1); | |
auto c3 = join(c2, c2); | |
auto c4 = join(4, c3); | |
auto c5 = join(c3, c4); | |
auto x1 = cons(1,2,3,4); | |
// auto x1 = join(1, join(2, join(3, join(4, nil)))); | |
std::cout << c1->first().type().name() << " " << c1->next().type().name() << std::endl; | |
std::cout << c2->first().type().name() << " " << c2->next().type().name() << std::endl; | |
std::cout << no(c0) << std::endl; | |
std::cout << no(c0->next()) << std::endl; | |
std::cout << id(c2, c2) << std::endl; | |
std::cout << id(c1, c2) << std::endl; | |
std::cout << "xx " << all(atom, c2) << std::endl; | |
std::cout << "yy " << all(atom, c3) << std::endl; | |
std::cout << "id(some(c5), c4) " << id(some(atom, c5), c4) << std::endl; | |
std::cout << no(x1) << std::endl; | |
std::cout << all(atom, x1) << std::endl; | |
// std::cout << id(Any(true), true) << std::endl; | |
// std::cout << c.first().type().name() << " " << std::endl; | |
prn("foo", "bar"); | |
prn(x1); | |
prn(c5); | |
} | |
#if 1 | |
template<typename T> | |
concept Addable = requires (T x) { x + x; }; | |
template<Addable T> | |
T add(T a, T b) { return a + b; } | |
#elif 1 | |
template<typename T> | |
requires requires (T x) { x + x; } | |
T add(T a, T b) { return a + b; } | |
#elif 1 | |
template<typename T> | |
concept Addable = requires (T a, T b) { | |
a + b; | |
}; | |
#endif | |
// | |
// | |
//template<typename T> | |
//concept C = requires { | |
// typename T::inner; | |
// typename S<T>; | |
//}; | |
//// Asserts that the named type is valid |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment