00001
00002
00003 #include "cppscript"
00004 #include "dynamic/extensions.hpp"
00005
00006 static_call( register_pickle_type( cmp_sequence, range_ex(0,0) ) );
00007
00008
00009 namespace dynamic
00010 {
00011 namespace types
00012 {
00014 class iterator : public dynamic::shared_var_impl
00015 {
00016 int m_current, m_step, m_end;
00017
00018 public:
00019 iterator(int current, int step, int end) :
00020 m_current(current), m_step(step), m_end(end)
00021 {
00022 }
00023
00024 bool as_bool()
00025 {
00026 return m_current != m_end;
00027 }
00028
00029 void op_inc()
00030 {
00031 m_current += m_step;
00032 }
00033
00034 void op_dec()
00035 {
00036 m_current -= m_step;
00037 }
00038
00039 var key()
00040 {
00041 return m_current;
00042 }
00043
00044 var value()
00045 {
00046 return m_current;
00047 }
00048
00049 void mark_children(gc::garbage_collector &)
00050 {
00051 }
00052
00053 var_cmp_result compare(const var & other)
00054 {
00055 iterator * other_iterator = dynamic_cast<iterator*>(other.impl().shared_var());
00056
00057 if(other_iterator)
00058 {
00059 int diff = m_current - other_iterator->m_current;
00060 return diff<0 ? cmp_lt : diff>0 ? cmp_gt : cmp_equal;
00061 }
00062 return cmp_not_equal;
00063 }
00064
00065 std::string class_name() { return "range::iterator"; }
00066 };
00067
00068
00070 class range_impl : public dynamic::shared_var_impl
00071 {
00072 int m_start, m_size, m_step;
00073
00074 public:
00075 range_impl(int min, int size, int step) : m_start(min), m_size(size), m_step(step)
00076 {
00077 }
00078
00079 var_cmp_index comparison_index()
00080 {
00081 return cmp_sequence;
00082 }
00083
00084 std::string class_name()
00085 {
00086 return "sequence";
00087 }
00088
00089 int size()
00090 {
00091 return m_size;
00092 }
00093
00094 void resize(std::size_t i)
00095 {
00096 m_size = i;
00097 }
00098
00099 var clone()
00100 {
00101 return new range_impl(*this);
00102 }
00103
00104 void mark_children(gc::garbage_collector &)
00105 {
00106 }
00107
00108 int as_int()
00109 {
00110 return m_start;
00111 }
00112
00113 bool as_bool()
00114 {
00115 return m_size!=0;
00116 }
00117
00118 var keys()
00119 {
00120 return new range_impl(0, m_size, 1);
00121 }
00122
00123 var values()
00124 {
00125 return this;
00126 }
00127
00128 var_cmp_result compare2(const var & other)
00129 {
00130 range_impl * other_impl = dynamic_cast<range_impl*>(other.impl().shared_var());
00131 if(!other_impl) return cmp_not_equal;
00132
00133 if(m_start != other_impl->m_start)
00134 {
00135 return m_start < other_impl->m_start ? cmp_lt : cmp_gt;
00136 }
00137
00138 if(m_size != other_impl->m_size)
00139 {
00140 return m_size < other_impl->m_size ? cmp_lt : cmp_gt;
00141 }
00142
00143 if(m_size && m_step != other_impl->m_step)
00144 {
00145 return m_step < other_impl->m_step ? cmp_lt : cmp_gt;
00146 }
00147
00148 return cmp_equal;
00149 }
00150
00151 void output(dynamic::ostream & os)
00152 {
00153 os << "sequence(" << m_start << "," << m_size << "," << m_step << ")";
00154 }
00155
00156 void output(dynamic::wostream & os)
00157 {
00158 os << L"sequence(";
00159 write_int_to_stream(os, m_start);
00160 os << L",";
00161 write_int_to_stream(os, m_size);
00162 os << L",";
00163 write_int_to_stream(os, m_step);
00164 os << L")";
00165 }
00166
00167 int get_index(int i)
00168 {
00169 return i>=0 ? i : m_size+i;
00170 }
00171
00172 var get_member(int i)
00173 {
00174 return m_start + get_index(i) * m_step;
00175 }
00176
00177 var get_member(const var & v)
00178 {
00179 return m_start + get_index(v.as_int()) * m_step;
00180 }
00181
00182 var begin()
00183 {
00184 return new iterator(m_start, m_step, m_start+m_step*m_size);
00185 }
00186
00187 var rbegin()
00188 {
00189 return new iterator(m_start + (m_size-1)*m_step, -m_step, m_start-m_step);
00190 }
00191
00192 var end()
00193 {
00194 return new iterator(m_start + m_size * m_step, m_step, m_start+m_step*m_size);
00195 }
00196
00197 var rend()
00198 {
00199 return new iterator(m_start-m_step, -m_step, m_start-m_step);
00200 }
00201
00202 var enumerator()
00203 {
00204 return begin();
00205 }
00206
00207 var reverse_enumerator()
00208 {
00209 return rbegin();
00210 }
00211
00212 void pickle(pickler & p)
00213 {
00214 p.write_object_type(cmp_sequence);
00215 p.write_int(m_start);
00216 p.write_int(m_size);
00217 p.write_int(m_step);
00218 }
00219
00220 void unpickle(unpickler & p)
00221 {
00222 m_start = p.read_int();
00223 m_size = p.read_int();
00224 m_step = p.read_int();
00225 }
00226
00227 var front()
00228 {
00229 return m_size ? var(m_start) : var();
00230 }
00231
00232 var back()
00233 {
00234 return m_size ? var(m_start + (m_size-1)*m_step) : var();
00235 }
00236
00237 var pop_front()
00238 {
00239 if(m_size>0)
00240 {
00241 --m_size;
00242 m_start += m_step;
00243 return m_start - m_step;
00244 }
00245 else
00246 {
00247 return var();
00248 }
00249 }
00250
00251 var pop_back()
00252 {
00253 if(m_size>0)
00254 {
00255 --m_size;
00256 return m_start + m_size*m_step;
00257 }
00258 else
00259 {
00260 return var();
00261 }
00262 }
00263
00264 void clear()
00265 {
00266 m_size=0;
00267 }
00268
00269 bool contains(const var & v)
00270 {
00271 int i = v.as_int();
00272 return i>=0 && i<m_size;
00273 }
00274
00275 void op_inc()
00276 {
00277 ++m_start;
00278 }
00279
00280 void op_dec()
00281 {
00282 --m_start;
00283 }
00284
00285 void assign_add(const var & v)
00286 {
00287 m_start += v.as_int();
00288 }
00289
00290 void assign_sub(const var & v)
00291 {
00292 m_start -= v.as_int();
00293 }
00294
00295 void assign_mul(const var & v)
00296 {
00297 m_size *= v.as_int();
00298 }
00299
00300 var op_add(const var & v)
00301 {
00302 return new range_impl(m_start+v.as_int(), m_size, m_step);
00303 }
00304
00305 var op_sub(const var & v)
00306 {
00307 return new range_impl(m_start-v.as_int(), m_size, m_step);
00308 }
00309
00310 var op_mul(const var & v)
00311 {
00312 return new range_impl(m_start, m_size*v.as_int(), m_step);
00313 }
00314
00315 bool empty()
00316 {
00317 return m_size==0;
00318 }
00319
00320 void get_range(std::size_t size, std::pair<std::size_t,std::size_t> & out)
00321 {
00322 out.first = m_start<0 ? size-m_start : m_start;
00323 int end = m_start + m_size*m_step;
00324 out.second = end<0 ? size+end : end;
00325 if(out.first > out.second)
00326 {
00327 std::swap(out.first, out.second);
00328 ++out.first;
00329 ++out.second;
00330 }
00331 }
00332 };
00333 }
00334 };
00335
00336
00337 var dynamic::range(const var & min, const var & max)
00338 {
00339 int min_i = min.as_int();
00340 int max_i = max.as_int();
00341
00342 if(min_i <= max_i)
00343 return new types::range_impl(min_i, (max_i - min_i)+1, 1);
00344 else
00345 return new types::range_impl(min_i, (min_i - max_i)+1, -1);
00346 }
00347
00348
00349 var dynamic::range(const var & min, const var & max, const var & step)
00350 {
00351 int min_i = min.as_int();
00352 int max_i = max.as_int();
00353 int step_i = step.as_int();
00354
00355 if(min_i <= max_i)
00356 return new types::range_impl(min_i, (max_i - min_i)/step_i+1, step_i);
00357 else
00358 return new types::range_impl(min_i, (min_i - max_i)/step_i+1, -step_i);
00359 }
00360
00361
00362 var dynamic::range_ex(const var & min, const var & max)
00363 {
00364 int min_i = min.as_int();
00365 int max_i = max.as_int();
00366 if(min_i <= max_i)
00367 return new types::range_impl(min_i, (max_i - min_i), 1);
00368 else
00369 return new types::range_impl(min_i, (min_i - max_i), -1);
00370 }
00371
00372
00373 var dynamic::range_ex(const var & min, const var & max, const var & step)
00374 {
00375 int min_i = min.as_int();
00376 int max_i = max.as_int();
00377 int step_i = step.as_int();
00378
00379 if(min_i <= max_i)
00380 return new types::range_impl(min_i, (max_i - min_i)/step_i, step_i);
00381 else
00382 return new types::range_impl(min_i, (min_i - max_i)/step_i, -step_i);
00383 }
00384
00385
00386 var dynamic::sequence(const var & start, const var & size)
00387 {
00388 return new types::range_impl(start.as_int(), size.as_int(), 1);
00389 }
00390
00391
00392 var dynamic::sequence(const var & start, const var & size, const var & step)
00393 {
00394 return new types::range_impl(start.as_int(), size.as_int(), step.as_int());
00395 }