Skip to content

Instantly share code, notes, and snippets.

@shawwn
Created October 13, 2022 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shawwn/63e0f010479efd95ebffdf2108645ad3 to your computer and use it in GitHub Desktop.
Save shawwn/63e0f010479efd95ebffdf2108645ad3 to your computer and use it in GitHub Desktop.
#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