Skip to content

Instantly share code, notes, and snippets.

@y2q-actionman
Created December 13, 2012 15:01
Show Gist options
  • Save y2q-actionman/4276951 to your computer and use it in GitHub Desktop.
Save y2q-actionman/4276951 to your computer and use it in GitHub Desktop.
Lisp advent calender 2012 sample : 実例1
#include <iostream>
#include <cassert>
#include <cstring>
class Cons;
enum class Tag { int_, cons, string };
class Lisp_ptr {
public:
Lisp_ptr(int i) : tag_(Tag::int_), u_(i){}
Lisp_ptr(Cons* c) : tag_(Tag::cons), u_(static_cast<void*>(c)){}
Lisp_ptr(const char* s) : tag_(Tag::string), u_(static_cast<const void*>(s)){}
Tag tag() const { return tag_; }
template<typename T>
T get() const;
private:
Tag tag_;
union U {
U(void* p) : ptr_(p){}
U(const void* p) : cptr_(p){}
U(int i) : int_(i){}
void* ptr_;
const void* cptr_;
int int_;
} u_;
};
template<>
int Lisp_ptr::get<int>() const {
assert(tag_ == Tag::int_);
return u_.int_;
}
template<>
Cons* Lisp_ptr::get<Cons*>() const {
assert(tag_ == Tag::cons);
return static_cast<Cons*>(u_.ptr_);
}
template<>
const char* Lisp_ptr::get<const char*>() const{
assert(tag_ == Tag::string);
return static_cast<const char*>(u_.cptr_);
}
bool operator==(Lisp_ptr a, Lisp_ptr b){
if(a.tag() != b.tag()) return false;
switch(a.tag()){
case Tag::int_: return (a.get<int>() == b.get<int>());
case Tag::cons: return (a.get<Cons*>() == b.get<Cons*>());
case Tag::string: return (strcmp(a.get<const char*>(), b.get<const char*>()) == 0);
default: return false;
}
}
bool operator!=(const Lisp_ptr& a, const Lisp_ptr& b){
return !(a == b);
}
struct Cons {
Lisp_ptr car;
Lisp_ptr cdr;
Cons(Lisp_ptr a, Lisp_ptr d) : car(a), cdr(d){};
};
constexpr auto NIL = static_cast<Cons*>(nullptr);
std::ostream& operator<<(std::ostream& o, Lisp_ptr p){
switch(p.tag()){
case Tag::int_:
o << p.get<int>();
break;
case Tag::cons:
o << '(';
for(auto i = p; i.tag() == Tag::cons && i.get<Cons*>(); i = i.get<Cons*>()->cdr){
o << i.get<Cons*>()->car << ' ';
}
o << "\b)";
break;
case Tag::string:
o << p.get<const char*>();
break;
}
return o;
}
///////////////////////////////////////////////////////////////
#include <initializer_list>
Lisp_ptr make_cons_list(std::initializer_list<Lisp_ptr> ilist){
Lisp_ptr head = NIL;
Lisp_ptr* next = &head;
for(auto p : ilist){
auto c = new Cons{p, NIL};
*next = c;
next = &(c->cdr);
}
return head;
}
int main(){
{
// (1 2 3)
Lisp_ptr lis1 = new Cons{1 , new Cons{2, new Cons{3, NIL}}};
std::cout << "lis1: " << lis1 << '\n';
// (1 (2 3) (4 5))
Lisp_ptr lis2 = new Cons{1,
new Cons{new Cons{2, new Cons{3, NIL}},
new Cons{new Cons{4, new Cons{5, NIL}},
NIL}}};
std::cout << "lis2: " << lis2 << '\n';
}
{
// (1 2 3)
Lisp_ptr lis1 = make_cons_list({1, 2, 3});
std::cout << "lis1: " << lis1 << '\n';
// (1 (2 3) (4 5))
Lisp_ptr lis2 = make_cons_list({1,
make_cons_list({2, 3}),
make_cons_list({4, 5})});
std::cout << "lis2: " << lis2 << '\n';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment