00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <mmxlight/mmxlight_glue.hpp>
00014 #include <mmxlight/base_evaluator.hpp>
00015 #include <basix/source_track.hpp>
00016 namespace mmx {
00017
00018
00019
00020
00021
00022 generic
00023 mmx_foreign (const generic& x) {
00024 (void) x;
00025 return void_value ();
00026 }
00027
00028
00029
00030
00031
00032 generic
00033 mmx_begin (const generic& x) {
00034 nat i, n= N(x);
00035 if (n==1) return void_value ();
00036 for (i=1; i<n-1; i++) {
00037
00038 generic aux= eval (x[i]);
00039 if (is<exception> (aux)) return aux;
00040 }
00041 return eval (x[i]);
00042 }
00043
00044
00045
00046
00047
00048 generic
00049 mmx_seqand (const generic& x) {
00050 if (N(x) != 3) return wrong_nr_args (x);
00051 generic r= eval_as<bool> (x[1]);
00052 if (is<exception> (r) || !as<bool> (r)) return r;
00053 return eval_as<bool> (x[2]);
00054 }
00055
00056 generic
00057 mmx_seqor (const generic& x) {
00058 if (N(x) != 3) return wrong_nr_args (x);
00059 generic r= eval_as<bool> (x[1]);
00060 if (is<exception> (r) || as<bool> (r)) return r;
00061 return eval_as<bool> (x[2]);
00062 }
00063
00064 bool
00065 mmx_not (const bool& x) {
00066 return !x;
00067 }
00068
00069 bool
00070 mmx_xor (const bool& x1, const bool& x2) {
00071 return x1 ^ x2;
00072 }
00073
00074
00075
00076
00077
00078 generic
00079 mmx_if (const generic& x) {
00080 if (N(x) < 3 || N(x) > 4) return wrong_nr_args (x);
00081 generic cond= eval_as<bool> (x[1]);
00082 if (is<exception> (cond)) return cond;
00083 if (as<bool> (cond)) return eval (x[2]);
00084 else if (N(x) == 4) return eval (x[3]);
00085 else return void_value ();
00086 }
00087
00088
00089
00090
00091
00092 generic
00093 mmx_loop (const generic& x) {
00094 nat i, n= N(x)-1;
00095 if (n < 1) return wrong_nr_args (x);
00096 bool stop= false;
00097 generic aux, ret= void_value ();
00098 select_evaluator (base_evaluator (current_ev));
00099
00100 table<iterator<generic>, generic> its;
00101 table<nat, generic> tps (0);
00102 for (i=1; i<n; i++)
00103 if (is_func (x[i], GEN_FOR, 1) && is_func (x[i][1], GEN_IN, 2)) {
00104 generic var= x[i][1][1];
00105 if (is_func (var, GEN_TYPE, 2)) {
00106 generic tp= eval (var[2]);
00107 if (is<exception> (tp)) { ret= tp; stop= true; break; }
00108 nat tid= type_id (tp);
00109 if (tid == 1) {
00110 ret= type_mismatch (GEN_TYPE_TYPE, var[2]); stop= true; break; }
00111 var= var[1];
00112 tps [var]= tid;
00113 }
00114 generic val= eval_as<iterator<generic> > (x[i][1][2]);
00115 if (is<exception> (val)) { ret= val; stop= true; break; }
00116 its [var]= as<iterator<generic> > (val);
00117 }
00118 else if (is_func (x[i], GEN_FOR, 1)) {
00119 aux= eval (x[i][1]);
00120 if (is<exception> (aux)) {
00121 stop= true;
00122 ret= aux;
00123 break;
00124 }
00125 }
00126
00127 while (!stop) {
00128 for (i=1; i<n; i++)
00129 if (is_func (x[i], GEN_FOR, 1) && is_func (x[i][1], GEN_IN, 2)) {
00130 generic var= x[i][1][1];
00131 bool typed= is_func (var, GEN_TYPE, 2);
00132 if (typed) var= var[1];
00133 iterator<generic>& it= its [var];
00134 if (done (it)) { stop= true; break; }
00135 aux= *it; ++it;
00136 if (typed) aux= convert_to (aux, read (tps, var), x[i][1][2]);
00137 if (is<exception> (aux)) { ret= aux; stop= true; break; }
00138 current_ev->set (var, aux);
00139 }
00140 else if (is_func (x[i], GEN_WHILE, 1)) {
00141 generic cond= eval_as<bool> (x[i][1]);
00142 if (is<exception> (cond)) { ret= cond; stop= true; break; }
00143 if (!as<bool> (cond)) { stop= true; break; }
00144 }
00145 if (stop) break;
00146
00147 select_evaluator (base_evaluator (current_ev));
00148 aux= eval (x[n]);
00149 restore_evaluator ();
00150
00151 if (is<exception> (aux)) {
00152 generic msg= *as<exception> (aux);
00153 if (exact_eq (msg, gen (GEN_CONTINUE)));
00154 else if (exact_eq (msg, gen (GEN_BREAK))) break;
00155 else { ret= aux; break; }
00156 }
00157
00158 for (i=1; i<n; i++)
00159 if (is_func (x[i], GEN_UNTIL, 1)) {
00160 generic cond= eval_as<bool> (x[i][1]);
00161 if (is<exception> (cond)) { ret= cond; stop= true; break; }
00162 if (as<bool> (cond)) { stop= true; break; }
00163 }
00164 else if (is_func (x[i], GEN_STEP, 1)) {
00165 aux= eval (x[i][1]);
00166 if (is<exception> (aux)) { ret= aux; stop= true; break; }
00167 }
00168 }
00169
00170 restore_evaluator ();
00171 return ret;
00172 }
00173
00174 generic
00175 mmx_break (const generic& x) {
00176 if (N(x) != 1) return wrong_nr_args (x);
00177 return as<generic> (exception (gen (GEN_BREAK)));
00178 }
00179
00180 generic
00181 mmx_continue (const generic& x) {
00182 if (N(x) != 1) return wrong_nr_args (x);
00183 return as<generic> (exception (gen (GEN_CONTINUE)));
00184 }
00185
00186
00187
00188
00189
00190 class count_iterator_rep: public iterator_rep<generic> {
00191 int start, end;
00192 public:
00193 count_iterator_rep (const int& s, const int& e): start (s), end (e) {}
00194 ~count_iterator_rep () {}
00195 protected:
00196 bool is_busy () { return start < end; }
00197 void advance () { start++; }
00198 generic current () { return as<generic> (start); }
00199 iterator_rep<generic>* clone () {
00200 return new count_iterator_rep (start, end); }
00201 };
00202
00203 static iterator<generic>
00204 count_iterator (const int& start, const int& end) {
00205 return iterator<generic> (new count_iterator_rep (start, end));
00206 }
00207
00208 generic
00209 mmx_count (const int& end) {
00210 return as<generic> (count_iterator (0, end));
00211 }
00212
00213 generic
00214 mmx_range (const generic& start, const generic& end) {
00215 return as<generic> (range_iterator<generic> (start, end, 1, true));
00216 }
00217
00218 generic
00219 mmx_to (const generic& start, const generic& end) {
00220 return as<generic> (range_iterator<generic> (start, end, 1, false));
00221 }
00222
00223 generic
00224 mmx_downto (const generic& start, const generic& end) {
00225 return as<generic> (range_iterator<generic> (start, end, -1, false));
00226 }
00227
00228
00229
00230
00231
00232 class extract_iterator_rep: public iterator_rep<generic> {
00233 evaluator ev;
00234 generic var;
00235 iterator<generic> it;
00236 generic cond;
00237 generic body;
00238 generic value;
00239
00240 void spool () {
00241 select_evaluator (ev);
00242 while (busy (it)) {
00243 generic val= *it;
00244 current_ev->set (var, val);
00245 generic ok= eval_as<bool> (cond);
00246 if (is<exception> (ok)) {
00247 value= ok;
00248 break;
00249 }
00250 else if (as<bool> (ok)) {
00251 value= eval (body);
00252 break;
00253 }
00254 else ++it;
00255 }
00256 restore_evaluator ();
00257 if (done (it)) value= void_value ();
00258 }
00259
00260 public:
00261 extract_iterator_rep (const evaluator& e, const generic& v,
00262 const iterator<generic>& i, const generic& c,
00263 const generic& b):
00264 ev (e), var (v), it (i), cond (c), body (b) { spool (); }
00265 ~extract_iterator_rep () {
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275
00276 protected:
00277 bool is_busy () { return busy (it); }
00278 void advance () { ++it; spool(); }
00279 generic current () { return value; }
00280 iterator_rep<generic>* clone () {
00281 extract_iterator_rep* rep=
00282 new extract_iterator_rep (ev, var, it, cond, body);
00283 rep->value= value;
00284 return rep;
00285 }
00286 };
00287
00288
00289 inline iterator<generic>
00290 extract_iterator (const evaluator& ev, const generic& var,
00291 const iterator<generic>& it, const generic& cond,
00292 const generic& v)
00293 {
00294 return iterator<generic> (new extract_iterator_rep (ev, var, it, cond, v));
00295 }
00296
00297 class unnest_iterator_rep: public iterator_rep<generic> {
00298 iterator<generic> it;
00299 iterator<generic> subit;
00300
00301 void spool () {
00302 while (busy (it)) {
00303 generic val= *it; ++it;
00304 if (!is<exception> (val) && !is<iterator<generic> > (val))
00305 val= type_mismatch (gen (GEN_GENERATOR_TYPE, GEN_GENERIC_TYPE), val);
00306 if (is<exception> (val)) subit= seq<generic> (val);
00307 else subit= as<iterator<generic> > (val);
00308 if (busy (subit)) break;
00309 }
00310 }
00311
00312 public:
00313 unnest_iterator_rep (const iterator<generic>& i):
00314 it (i) { spool (); }
00315 unnest_iterator_rep (const iterator<generic>& i, const iterator<generic>& j):
00316 it (i), subit (j) {}
00317 ~unnest_iterator_rep () {}
00318
00319 protected:
00320 bool is_busy () { return busy (subit); }
00321 void advance () { ++subit; if (done (subit)) spool(); }
00322 generic current () { return *subit; }
00323 iterator_rep<generic>* clone () {
00324 unnest_iterator_rep* rep= new unnest_iterator_rep (it, subit);
00325 return rep;
00326 }
00327 };
00328
00329 inline iterator<generic>
00330 unnest_iterator (const iterator<generic>& it) {
00331 return iterator<generic> (new unnest_iterator_rep (it));
00332 }
00333
00334 generic
00335 mmx_where (const generic& x) {
00336 nat i, n= N(x);
00337 if (n < 3) return wrong_nr_args (x);
00338 if (is_func (x[1], GEN_IN, 2)) {
00339
00340
00341 return mmx_where (append (gen (x[0], x[1][1], x[1]), range (x, 2, N(x))));
00342 }
00343 if (!is_func (x[2], GEN_IN, 2))
00344 return std_exception ("'variable in generator' expected", x[2]);
00345 for (i=3; i<n; i++)
00346 if (is_func (x[i], GEN_IN, 2))
00347 break;
00348 if (i == n) {
00349 generic cond= GEN_TRUE;
00350 if (i > 3) {
00351 cond= x[i-1];
00352 for (nat j=i-2; j>=3; j--)
00353 cond= gen (GEN_SEQAND, x[j], cond);
00354 }
00355 generic body= x[1];
00356 generic var = x[2][1];
00357 if (is_func (var, GEN_TYPE, 2)) {
00358
00359 var = var[1];
00360 }
00361 if (!is<literal> (var)) return type_mismatch (GEN_LITERAL_TYPE, var);
00362 generic val= eval_as<iterator<generic> > (x[2][2]);
00363 if (is<exception> (val)) return val;
00364 evaluator ev= base_evaluator (current_ev);
00365 iterator<generic> it= as<iterator<generic> > (val);
00366 iterator<generic> r = extract_iterator (ev, var, it, cond, body);
00367 generic ret= as<generic> (r);
00368 return ret;
00369 }
00370 else {
00371 generic inner= append (gen (x[0], x[1]), range (x, i, n));
00372 generic outer= append (gen (x[0], inner), range (x, 2, i));
00373 generic it= mmx_where (outer);
00374 if (is<exception> (it)) return it;
00375 return as<generic> (unnest_iterator (as<iterator<generic> > (it)));
00376 }
00377 }
00378
00379
00380
00381
00382
00383 tuple<generic>
00384 mmx_fill (const generic& x, const int& nr) {
00385 ASSERT (nr >= 0, "positive integer expected");
00386 return as_tuple (fill<generic> (x, nr));
00387 }
00388
00389 tuple<generic>
00390 mmx_tuple (const tuple<generic>& t) {
00391 return t;
00392 }
00393
00394 iterator<generic>
00395 mmx_explode (const iterator<generic>& it) {
00396 return it;
00397 }
00398
00399 generic
00400 mmx_protect (const generic& x) {
00401 if (N(x) != 2) return wrong_nr_args (x);
00402 generic it= eval (x[1]);
00403 if (is<exception> (it)) return it;
00404 else return gen ("protect", it);
00405 }
00406
00407 generic
00408 mmx_unprotect (const generic& x) {
00409 if (N(x) != 2) return wrong_nr_args (x);
00410 generic it= eval (x[1]);
00411 if (is<compound> (it) && N(it) == 2 && it[0] == "protect") return it[1];
00412 return std_exception ("protected generator expected", x[1]);
00413 }
00414
00415
00416
00417
00418
00419 extern nat backtrace_depth;
00420
00421 class backtrace_depth_rep: public alias_rep<int> {
00422 MMX_ALLOCATORS
00423 int prec;
00424 public:
00425 inline backtrace_depth_rep () {}
00426 int get () const { return backtrace_depth; }
00427 int& open () const { return *((int*) ((void*) (&backtrace_depth))); }
00428 void close () const {}
00429 };
00430
00431 class var_exception {
00432 MMX_ALLOCATORS
00433 generic rep;
00434 public:
00435 inline generic operator * () const { return rep; }
00436 inline var_exception (const generic& g): rep (g) {}
00437 };
00438
00439 inline syntactic flatten (const var_exception& e) { return flatten (*e); }
00440 WRAP_INDIRECT_IMPL(inline,var_exception)
00441
00442 var_exception
00443 mmx_exception (const string& msg, const generic& where) {
00444 return var_exception (std_exception (msg, where));
00445 }
00446
00447 string
00448 mmx_exception_as_string (const var_exception& exc) {
00449 return source_exception (as<exception> (*exc));
00450 }
00451
00452 generic
00453 mmx_try (const generic& x) {
00454 if (N(x) < 2) return wrong_nr_args (x);
00455
00456 generic body= x[1];
00457 if (!is_func (body, GEN_BEGIN)) body= gen (GEN_BEGIN, body);
00458 vector<generic> v= compound_to_vector (x);
00459 v= range (v, 2, N(v));
00460 v << cdr (compound_to_vector (body));
00461 body= gen (GEN_BEGIN, v);
00462
00463 select_evaluator (base_evaluator (current_ev));
00464 generic r= eval (body);
00465 if (is<exception> (r)) {
00466 generic err= *as<exception> (r), ret;
00467 if (is<vector<generic> > (err[1]))
00468 ret= current_ev->apply (GEN_CATCH, as<vector<generic> > (err[1]));
00469 else ret= current_ev->apply (GEN_CATCH, as<generic> (var_exception (r)));
00470 if (!is_func (ret, GEN_CATCH)) r= ret;
00471 }
00472 restore_evaluator ();
00473
00474 return r;
00475 }
00476
00477 generic
00478 mmx_raise (const generic& x) {
00479 vector<generic> args;
00480 for (nat i=1; i<N(x); i++) {
00481 generic r= eval (x[i]);
00482 if (is<exception> (r)) return r;
00483 else args << r;
00484 }
00485 if (N(args) == 1 && is<var_exception> (args[0]))
00486 return *as<var_exception> (args[0]);
00487 else return user_exception (args, x);
00488 }
00489
00490
00491
00492
00493
00494 void
00495 glue_control () {
00496 static alias<int> depth= new backtrace_depth_rep ();
00497 define_constant<alias<int> > ("backtrace_depth", depth);
00498 define_type<var_exception> ("Exception");
00499 define_type<iterator<generic> > (gen("Generator",generic("Generic")));
00500 define_primitive (GEN_FOREIGN, mmx_foreign);
00501 define_primitive (GEN_BEGIN, mmx_begin);
00502 define_primitive (GEN_SEQAND, mmx_seqand);
00503 define_primitive (GEN_SEQOR, mmx_seqor);
00504 define (GEN_NOT, mmx_not);
00505 define (GEN_XOR, mmx_xor);
00506 define_primitive (GEN_IF, mmx_if);
00507 define_primitive (GEN_LOOP, mmx_loop);
00508 define_primitive (GEN_BREAK, mmx_break);
00509 define_primitive (GEN_CONTINUE, mmx_continue);
00510 define (GEN_RANGE, mmx_range);
00511 define ("count", mmx_count);
00512 define (GEN_TO, mmx_to);
00513 define (GEN_DOWNTO, mmx_downto);
00514 define_primitive (GEN_WHERE, mmx_where);
00515 define_primitive (GEN_VWHERE, mmx_where);
00516 define (GEN_FILL, mmx_fill);
00517 define (GEN_TUPLE, mmx_tuple);
00518 define (GEN_EXPLODE, mmx_explode);
00519 define_primitive ("protect", mmx_protect);
00520 define_primitive ("unprotect", mmx_unprotect);
00521 define ("exception", mmx_exception);
00522 define ("as_string", mmx_exception_as_string);
00523 define_primitive (GEN_TRY, mmx_try);
00524 define_primitive (GEN_RAISE, mmx_raise);
00525 }
00526
00527 }