0
|
1 #ifndef __vm_value_h__
|
|
2 #define __vm_value_h__
|
|
3
|
|
4 #include <iostream>
|
|
5 #include <exception>
|
|
6 #include <string>
|
|
7
|
|
8 namespace vm {
|
|
9
|
|
10 // 参照カウンタ付きstring
|
|
11 class string {
|
|
12 public:
|
|
13 string(): ref_(0)
|
|
14 {
|
|
15 }
|
|
16 string(const std::string &str): ref_(1), str_(str)
|
|
17 {
|
|
18 }
|
|
19
|
|
20 void addref()
|
|
21 {
|
|
22 ref_++;
|
|
23 }
|
|
24
|
|
25 void release()
|
|
26 {
|
|
27 if (--ref_ == 0)
|
|
28 delete this;
|
|
29 }
|
|
30
|
|
31 public:
|
|
32 int ref_;
|
|
33 std::string str_;
|
|
34 } ;
|
|
35
|
|
36 // 変数
|
|
37 class value {
|
|
38 enum {
|
|
39 type_integer,
|
|
40 type_string,
|
|
41 } ;
|
|
42
|
|
43 public:
|
|
44 value()
|
|
45 {
|
|
46 s_ = 0;
|
|
47 type_ = type_integer;
|
|
48 }
|
|
49
|
|
50 value(int ival)
|
|
51 {
|
|
52 i_ = ival;
|
|
53 type_ = type_integer;
|
|
54 }
|
|
55
|
|
56 value(const std::string &str)
|
|
57 {
|
|
58 s_ = new string(str);
|
|
59 type_ = type_string;
|
|
60 }
|
|
61
|
|
62 value(string *p)
|
|
63 {
|
|
64 s_ = p;
|
|
65 type_ = type_string;
|
|
66 }
|
|
67
|
|
68 ~value()
|
|
69 {
|
|
70 clear();
|
|
71 }
|
|
72
|
|
73 value(const value &a)
|
|
74 {
|
|
75 copy(a);
|
|
76 }
|
|
77
|
|
78 value& operator=(const value &a)
|
|
79 {
|
|
80 if (this == &a)
|
|
81 return *this;
|
|
82
|
|
83 clear();
|
|
84 copy(a);
|
|
85
|
|
86 return *this;
|
|
87 }
|
|
88
|
|
89 void clear()
|
|
90 {
|
|
91 if (type_ == type_string)
|
|
92 s_->release();
|
|
93 }
|
|
94
|
|
95 void copy(const value &a)
|
|
96 {
|
|
97 type_ = a.type_;
|
|
98 s_ = a.s_;
|
|
99 if (type_ == type_string)
|
|
100 s_->addref();
|
|
101 }
|
|
102
|
|
103 public:
|
|
104 union {
|
|
105 string *s_;
|
|
106 int i_;
|
|
107 } ;
|
|
108 char type_;
|
|
109 } ;
|
|
110
|
|
111 class stack_overflow: public std::exception {
|
|
112 public:
|
|
113 const char *what() const throw()
|
|
114 {
|
|
115 return "stack overflow";
|
|
116 }
|
|
117 } ;
|
|
118
|
|
119 // 固定サイズのスタック
|
|
120 // スタックオーバーフローの場合は例外を送出
|
|
121
|
|
122 template< typename Ty, int Size >
|
|
123 class stack {
|
|
124 public:
|
|
125 stack(): size_(0)
|
|
126 {
|
|
127 }
|
|
128
|
|
129 ~stack()
|
|
130 {
|
|
131 resize(0);
|
|
132 }
|
|
133
|
|
134 void push(const Ty& value)
|
|
135 {
|
|
136 if (Size <= size_)
|
|
137 throw stack_overflow();
|
|
138 *(::new(data_[size_++]) Ty) = value;
|
|
139 }
|
|
140
|
|
141 void pop()
|
|
142 {
|
|
143 ((Ty *)data_[--size_])->~Ty();
|
|
144 }
|
|
145
|
|
146 void pop(int count)
|
|
147 {
|
|
148 resize(size_ - count);
|
|
149 }
|
|
150
|
|
151 void resize(int newsize)
|
|
152 {
|
|
153 int oldsize = size_;
|
|
154
|
|
155 if (oldsize > newsize) {
|
|
156 for (int i = newsize; i < oldsize; ++i)
|
|
157 ((Ty *)data_[i])->~Ty();
|
|
158 }
|
|
159 if (oldsize < newsize) {
|
|
160 if (Size < newsize)
|
|
161 throw stack_overflow();
|
|
162 for (int i = oldsize; i < newsize; ++i)
|
|
163 ::new(data_[i]) Ty;
|
|
164 }
|
|
165 size_ = newsize;
|
|
166 }
|
|
167
|
|
168 const Ty& top() const { return *(const Ty *)data_[size_ - 1]; }
|
|
169 Ty& top() { return *(Ty *)data_[size_ - 1]; }
|
|
170
|
|
171 bool overflow() const { return size_ >= Size; }
|
|
172 bool empty() const { return size_ == 0; }
|
|
173 int size() const { return size_; }
|
|
174
|
|
175 const Ty& operator[](int index) const { return *(const Ty *)data_[index]; }
|
|
176 Ty& operator[](int index) { return *(Ty *)data_[index]; }
|
|
177
|
|
178 protected:
|
|
179 char data_[Size][sizeof(Ty)];
|
|
180 int size_;
|
|
181 } ;
|
|
182
|
|
183 } // namespace
|
|
184
|
|
185 #endif
|