C++で書くScheme処理系のオブジェクト表現を考え中
今日職場で色々アドバイスをもらい改善したものを、帰宅後拡張して混乱中。
C++難しい><。
small int や null などは即値として扱いたいという意図でおおもとは Gauche のオブジェクト表現を参考にしています。
null(SCHEME_NULL)の初期化がいまいちです。
どんなことでも良いので誤りや改善ポイントに気づかれたらアドバイスいただけると助かります<(_ _)>
使い方
int main(int argc, char *argv[]) { Object o1 = Object::makeInt(3); if (o1.isInt()) { printf("%d\n", o1.toInt()); } Object o2 = UCS4_STR("hige"); if (o2.isString()) { printf("string!\n"); } Object o3 = Object::makeVector(3, o1); if (o3.isVector()) { printf("vector!\n"); o3.toVector()->set(0, Object::makeInt(1234)); printf("vector %d\n", o3.toVector()->ref(0).toInt()); } Object a = Object::makeInt(3); Object b = Object::makeInt(3); if (a.equal(b)) { printf("equal\n"); } if (!a.equal(o2)) { printf("not equal\n"); } Object d = SCHEME_NULL; if (d.isNull()) { printf("null\n"); } Object p = Object::cons(o2, o3); if (p.isPair()) { printf("pair\n"); printf("vector? %d\n", p.toPair()->cdr.isVector()); } return 0; }
コード
#include <stdio.h> #include <stdint.h> typedef intptr_t word; typedef word UCS4Char; #define UCS4_STR(a) (reinterpret_cast<const UCS4Char*>(L##""a)) #define GEN_HEAP_OBJECT_TYPE(i) (((i) << 2) | 0x03) struct HeapObject { public: HeapObject(word type, word obj) : type(type), obj(obj) {} word type; word obj; enum { String = GEN_HEAP_OBJECT_TYPE(1), Vector = GEN_HEAP_OBJECT_TYPE(2), forbidden_comma }; }; class Vector; struct Pair; class Object { public: Object(); Object(const UCS4Char* str); // String static Object makeInt(signed long int n); static Object makeConst(uint8_t c); static Object makeVector(int n, Object o); static Object cons(Object car, Object cdr); signed long int toInt() const; Vector* toVector() const; Pair* toPair() const; bool equal(Object o); bool isInt() const; bool isString() const; bool isVector() const; bool isNull() const; bool isPair() const; protected: bool isHeapObject() const; bool isPointer() const; uint8_t tag() const; Object(word n); // int or constant; Object(int num, Object o); // vector word value_; // これは const にしたいが。 }; struct Pair { Pair(Object car, Object cdr) : car(car), cdr(cdr) {} Object car; Object cdr; }; class String { public: String(const UCS4Char* s) { } }; class Vector { public: Vector(int num); Vector(int num, Object obj); virtual ~Vector(); Object ref(int index); void set(int index, Object obj); int length() const; Object* data(); protected: Object* objects_; const int num_; }; Object::Object() : value_(6) { } Object SCHEME_NULL = Object::makeConst(0); Object::Object(word value) : value_(value) { } Object Object::makeInt(signed long int n) { return Object((n << 2) + 1); } Object Object::makeConst(uint8_t i) { return Object((i << 4) + 6); } Object Object::cons(Object car, Object cdr) { return Object(reinterpret_cast<word>(new Pair(car, cdr))); } Object Object::makeVector(int n, Object obj) { return Object(n, obj); } bool Object::isNull() const { return value_ == SCHEME_NULL.value_; } Object::Object(const UCS4Char* str) : value_(reinterpret_cast<word>(new HeapObject(HeapObject::String, reinterpret_cast<word>(new String(str))))) { } Object::Object(int n, Object o) : value_(reinterpret_cast<word>(new HeapObject(HeapObject::Vector, reinterpret_cast<word>(new Vector(n, o))))) { } Pair* Object::toPair() const { return reinterpret_cast<Pair*>(value_); } Vector* Object::toVector() const { return reinterpret_cast<Vector*>(reinterpret_cast<HeapObject*>(value_)->obj); } signed long int Object::toInt() const { return static_cast<signed long int>(value_) >> 2; } bool Object::isInt() const { return tag() == 1; } bool Object::isPair() const { return isPointer() && ((toPair()->car.value_ & 0x03) != 0x03); } bool Object::isString() const { return isHeapObject() && reinterpret_cast<HeapObject*>(value_)->type == HeapObject::String; } bool Object::isVector() const { return isHeapObject() && reinterpret_cast<HeapObject*>(value_)->type == HeapObject::Vector; } bool Object::equal(Object o) { return value_ == o.value_; } bool Object::isPointer() const { return (value_ & 0x03) == 0; } bool Object::isHeapObject() const { return isPointer() && (reinterpret_cast<HeapObject*>(value_)->type & 0x03 == 0x03); } uint8_t Object::tag() const { return (static_cast<word>(value_)) & 0x03; } Vector::Vector(int num) : num_(num) { objects_ = new Object[num]; } Vector::Vector(int num, Object obj) : num_(num) { objects_ = new Object[num]; for (int i = 0; i < num; i++) { objects_[i] = obj; } } Vector::~Vector() {} Object Vector::ref(int index) { return objects_[index]; } void Vector::set(int index, Object obj) { objects_[index] = obj; } int Vector::length() const { return num_; } Object* Vector::data() { return objects_; }