Skip to content

Instantly share code, notes, and snippets.

@Superstar64
Created April 4, 2022 22:54
Show Gist options
  • Save Superstar64/40f51c4a0d23f91b6371b1426569dd55 to your computer and use it in GitHub Desktop.
Save Superstar64/40f51c4a0d23f91b6371b1426569dd55 to your computer and use it in GitHub Desktop.
Covariant shared pointers for abstract syntax trees
#include <cstddef>
#include <string>
#include <type_traits>
template <class Object> class Ref;
class Object {
template <class> friend class Ref;
size_t reference;
protected:
Object() : reference(1) {}
Object(const Object &) = delete;
Object(Object &&) = delete;
Object &operator=(const Object &) = delete;
Object &operator=(Object &&) = delete;
virtual ~Object() = default;
};
template <class Object> class Ref {
static_assert(std::is_base_of<::Object, Object>::value,
"Trying to make shared pointer of non object");
template <class> friend class Ref;
Object *object;
Ref(Object *object) : object(object) {}
public:
template <class... A> static Ref<Object> make(A... arguments) {
return Ref<Object>(new Object(arguments...));
}
Ref(const Ref<Object> &ref) : object(ref.object) { object->reference++; }
~Ref() {
object->reference--;
if (object->reference == 0) {
delete object;
}
}
template <class Base> operator Ref<Base>() {
return Ref<Base>(static_cast<Base *>(object));
}
};
struct Term : Object {};
struct Var : Term {
std::string name;
Var(std::string name) : name(name) {}
virtual ~Var() = default;
};
struct App : Term {
Ref<Term> function;
Ref<Term> argument;
App(Ref<Term> function, Ref<Term> argument) : function(function), argument(argument) {}
virtual ~App() = default;
};
Ref<Term> fx() {
return Ref<App>::make(Ref<Var>::make("f"), Ref<Var>::make("x"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment