namespace factor { template<typename Type> cell tag(Type *value) { return RETAG(value,Type::type_number); } inline static cell tag_dynamic(object *value) { return RETAG(value,value->type()); } template<typename Type> struct tagged { cell value_; cell type() const { return TAG(value_); } bool type_p(cell type_) const { return type() == type_; } bool type_p() const { if(Type::type_number == TYPE_COUNT) return true; else return type_p(Type::type_number); } cell value() const { #ifdef FACTOR_DEBUG assert(type_p()); #endif return value_; } Type *untagged() const { #ifdef FACTOR_DEBUG assert(type_p()); #endif return (Type *)(UNTAG(value_)); } Type *untag_check(factor_vm *parent) const { if(!type_p()) parent->type_error(Type::type_number,value_); return untagged(); } explicit tagged(cell tagged) : value_(tagged) {} explicit tagged(Type *untagged) : value_(factor::tag(untagged)) {} Type *operator->() const { return untagged(); } cell *operator&() const { return &value_; } const tagged<Type> &operator=(const Type *x) { value_ = tag(x); return *this; } const tagged<Type> &operator=(const cell &x) { value_ = x; return *this; } bool operator==(const tagged<Type> &x) { return value_ == x.value_; } bool operator!=(const tagged<Type> &x) { return value_ != x.value_; } template<typename NewType> tagged<NewType> as() { return tagged<NewType>(value_); } }; template<typename Type> Type *factor_vm::untag_check(cell value) { return tagged<Type>(value).untag_check(this); } template<typename Type> Type *untag(cell value) { return tagged<Type>(value).untagged(); } }