]> gitweb.factorcode.org Git - factor.git/blob - vm/tagged.hpp
vm: tagged typechecks work better with DEBUG=1
[factor.git] / vm / tagged.hpp
1 namespace factor
2 {
3
4 template<typename Type> cell tag(Type *value)
5 {
6         return RETAG(value,tag_for(Type::type_number));
7 }
8
9 inline static cell tag_dynamic(object *value)
10 {
11         return RETAG(value,tag_for(value->h.hi_tag()));
12 }
13
14 template<typename Type>
15 struct tagged
16 {
17         cell value_;
18
19         cell type() const {
20                 cell tag = TAG(value_);
21                 if(tag == OBJECT_TYPE)
22                         return ((object *)UNTAG(value_))->h.hi_tag();
23                 else
24                         return tag;
25         }
26
27         bool type_p(cell type_) const
28         {
29                 return type() == type_;
30         }
31
32         bool type_p() const
33         {
34                 if(Type::type_number == TYPE_COUNT)
35                         return true;
36                 else
37                         return type_p(Type::type_number);
38         }
39
40         cell value() const {
41 #ifdef FACTOR_DEBUG
42                 assert(type_p());
43 #endif
44                 return value_;
45         }
46         Type *untagged() const {
47 #ifdef FACTOR_DEBUG
48                 assert(type_p());
49 #endif
50                 return (Type *)(UNTAG(value_));
51         }
52
53         Type *untag_check(factor_vm *parent) const {
54                 if(!type_p())
55                         parent->type_error(Type::type_number,value_);
56                 return untagged();
57         }
58
59         explicit tagged(cell tagged) : value_(tagged) {}
60         explicit tagged(Type *untagged) : value_(factor::tag(untagged)) {}
61
62         Type *operator->() const { return untagged(); }
63         cell *operator&() const { return &value_; }
64
65         const tagged<Type> &operator=(const Type *x) { value_ = tag(x); return *this; }
66         const tagged<Type> &operator=(const cell &x) { value_ = x; return *this; }
67
68         bool operator==(const tagged<Type> &x) { return value_ == x.value_; }
69         bool operator!=(const tagged<Type> &x) { return value_ != x.value_; }
70
71         template<typename NewType> tagged<NewType> as() { return tagged<NewType>(value_); }
72 };
73
74 template<typename Type> Type *factor_vm::untag_check(cell value)
75 {
76         return tagged<Type>(value).untag_check(this);
77 }
78
79 template<typename Type> Type *untag(cell value)
80 {
81         return tagged<Type>(value).untagged();
82 }
83
84 }