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