bug fix in xrange() that would cause it to yield bogus values
[vox.git] / src / core / baselib_system.cpp
blobc292299c6853eb581d4c991f805f37202af2fb37
2 #include "baselib.hpp"
3 #include "string.hpp"
5 #define VX_PRINT_REPR
7 VXInteger vox_printfunc_callback(VXState* v, VXInteger start, VXPrintFunc vpf)
9 const char* data_str;
10 VXInteger data_len;
11 VXInteger top;
12 VXInteger i;
13 if(vpf)
15 top = v->GetTop();
16 for(i=start; i<=top; i++)
18 VXObject res;
19 VXObject& ob = v->StackGet(i);
20 #if defined(VX_PRINT_REPR)
21 VXOType tp = ob.Type();
22 if(tp != VX_OT_STRING && !ob.IsNumeric())
24 const std::string& s = VXRepr(v, ob).str();
25 data_str = s.c_str();
26 data_len = s.length();
28 else
30 v->ToString(ob, res);
31 res.String()->Get(&data_str, &data_len);
33 #else
34 v->ToString(ob, res);
35 res.String->Get(&data_str, &data_len);
36 #endif
37 if(VX_FAILED(vpf(v, false, data_str, data_len)))
39 goto _printfunc_failed;
42 if(VX_FAILED(vpf(v, true, data_str, data_len)))
44 goto _printfunc_failed;
47 return 0;
49 _printfunc_failed:
50 return v->ThrowError("Internal error: call to printfunc failed");
54 VXInteger _println_callback(VXState* v, bool isend, const char* str, VXInteger len)
56 if(v->Shared()->_printfunc)
58 if(isend)
60 v->Shared()->_printfunc(v, "\n");
62 else
64 v->Shared()->_printfunc(v, "%s", str);
66 return VX_OK;
68 return VX_ERROR;
71 VXInteger _print_callback(VXState* v, bool isend, const char* str, VXInteger len)
73 if(_ss(v)->_printfunc)
75 if(!isend)
77 _ss(v)->_printfunc(v, "%s", str);
79 return VX_OK;
81 return VX_ERROR;
84 VXInteger system_repr(VXState* v)
86 VXInteger status;
87 VXRepr ser(v, v->StackGet(2));
88 status = ser.status();
89 if(status == VX_OK)
91 const std::string& data = ser.str();
92 v->Push(v->NewString(data.c_str(), data.length()));
93 return 1;
95 return status;
98 VXInteger system_dummy(VXState*)
100 return 0;
103 VXInteger system_gc_collect(VXState* v)
105 v->Push(v->CollectGarbage());
106 return 1;
109 VXInteger system_gc_resurrect(VXState* v)
111 v->ResurrectUnreachable();
112 return 1;
115 VXInteger system_gc_release(VXState* v)
117 VXObject& ob = v->StackGet(2);
118 ob.Null();
119 return 0;
122 VXInteger system_getroottable(VXState* v)
124 v->Push(v->_roottable);
125 return 1;
128 VXInteger system_getconsttable(VXState* v)
130 v->Push(v->Shared()->_consts);
131 return 1;
134 VXInteger system_setroottable(VXState* v)
136 VXObject oldroot = v->_roottable;
137 VXObject newroot = v->StackGet(2);
138 if(newroot.Type() == VX_OT_TABLE || newroot.Type() == VX_OT_NULL)
140 v->_roottable = newroot;
141 v->Push(oldroot);
142 return 1;
144 return v->ThrowError("wrong type (expected 'table' or 'null')");
147 VXInteger system_setconsttable(VXState* v)
149 VXObject oldtable = v->Shared()->_consts;
150 VXObject newtable = v->StackGet(2);
151 if(newtable.Type() == VX_OT_TABLE)
153 v->Shared()->_consts = newtable;
154 v->Push(oldtable);
155 return 1;
157 return VX_ERROR;;
160 VXInteger system_seterrorhandler(VXState* v)
162 v->SetErrorHandler(v->StackGet(2));
163 return 0;
166 VXInteger system_setdebughook(VXState* v)
168 v->SetDebugHook(v->StackGet(2));
169 return 0;
172 VXInteger system_enabledebuginfo(VXState* v)
174 bool val;
175 v->GetBool(2, &val);
176 v->EnableDebugInfo(val);
177 return 0;
181 VXInteger system_getstackinfos(VXState* v)
183 VXInteger level;
184 v->GetInteger(-1, &level);
185 return __getcallstackinfos(v,level);
188 VXInteger system_assert(VXState* v)
190 const char* message;
191 if(VXState::IsFalse(v->StackGet(2)))
193 if(VX_FAILED(v->GetString(3, &message, NULL)))
195 return v->ThrowError("assertion failed");
197 else
199 return v->ThrowError("assertion failed: %s", message);
202 return 0;
207 VXInteger system_print(VXState* v)
209 return vox_printfunc_callback(v, 2, _print_callback);
212 VXInteger system_println(VXState* v)
214 return vox_printfunc_callback(v, 2, _println_callback);
218 VXInteger system_compilestring(VXState* v)
220 const char* src;
221 const char* name;
222 VXInteger size;
223 v->GetString(2, &src, &size);
224 if(VX_FAILED(v->GetString(3, &name, NULL)))
226 name = "unnamedbuffer";
228 if(VX_SUCCEEDED(v->CompileBuffer(src,size,name,false)))
230 return 1;
232 return VX_ERROR;
235 VXInteger system_newthread(VXState* v)
237 VXObject &func = v->StackGet(2);
238 VXInteger stksize = (func.Closure()->_function->_stacksize << 1) +2;
239 VXState* newv = v->NewThread(v, (stksize < MIN_STACK_OVERHEAD + 2)?
240 MIN_STACK_OVERHEAD + 2 : stksize);
241 VXState::MoveIndex(newv, v, -2);
242 return 1;
245 VXInteger system_suspend(VXState* v)
247 return v->Suspend();
250 VXInteger system_type(VXState* v)
252 VXObject &o = v->StackGet(2);
253 v->PushString(o.TypeString());
254 return 1;
257 VXInteger system_callee(VXState* v)
259 if(v->_callsstacksize > 1)
261 v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
262 return 1;
264 return v->ThrowError("no closure in the calls stack");
267 VXInteger system_loadfile(VXState* v)
269 const char *filename;
270 bool printerror = false;
271 v->GetString(2, &filename, NULL);
272 if(VX_FAILED(v->GetBool(3, &printerror)))
274 printerror = false;
276 if(VX_SUCCEEDED(v->LoadFile(filename,printerror)))
278 return 1;
280 return v->ThrowError("loadfile('%s'): %s", filename, v->LastError());
285 VXInteger system_writeclosuretofile(VXState* v)
287 const char *filename;
288 v->GetString(2, &filename, NULL);
289 if(VX_SUCCEEDED(v->WriteClosureToFile(filename)))
291 return 1;
293 return VX_ERROR;
296 VXInteger system_dofile(VXState* v)
298 const char *filename;
299 bool printerror;
300 v->GetString(2, &filename, NULL);
301 if(VX_FAILED(v->GetBool(3, &printerror)))
303 /* by default, do not print the yielded error */
304 printerror = false;
306 v->Push(v->GetRootTable());
307 if(VX_SUCCEEDED(v->DoFile(filename, true, printerror)))
309 return 1;
311 return v->ThrowError("dofile('%s'): %s", filename, v->LastError());
316 VXInteger system_dostring(VXState* v)
318 VXInteger ret;
319 std::string source;
320 const char* buffername;
321 bool printerror;
322 v->GetString(2, &source);
323 if(VX_FAILED(v->GetBool(3, &printerror)))
325 /* by default, do not print the yielded error */
326 printerror = false;
328 if(VX_FAILED(v->GetString(4, &buffername, NULL)))
330 buffername = NULL;
332 v->Push(v->GetRootTable());
333 ret = v->DoString(
334 source.c_str(),
335 source.length(),
336 buffername, true, printerror);
337 if(VX_SUCCEEDED(ret))
339 return 1;
341 /* only throw custom errormessage if buffername is not NULL.
342 reason: if system.errorhandler() is called from vox,
343 the buffername is not reachable, so we'll just act as if
344 it got called natively */
345 if(buffername != NULL)
347 return v->ThrowError("dostring(%s): %s", buffername , v->LastError());
349 return VX_ERROR;
352 VXInteger system_platform_group(VXState* v)
354 v->Push(v->NewString(VOX_PLATFORM_GROUP_NAME));
355 return 1;
358 VXInteger system_platform(VXState* v)
360 v->Push(v->NewString(VOX_PLATFORM_NAME));
361 return 1;
364 VXInteger system_atexit(VXState* v)
366 VXObject& o = v->StackGet(2);
367 return v->AtExit(o);
370 VXInteger system_errorhandler(VXState* v)
372 v->CallErrorHandler(v->StackGet(2));
373 return VX_OK;
377 /* ---------- */
378 struct XRange
380 VXInteger count;
381 VXInteger start;
382 VXInteger stop;
383 VXInteger step;
384 VXArrayObj* values;
388 VXInteger xrange_releasehook(VXUserPointer p, VXInteger size)
390 XRange* self = (XRange*)p;
391 delete self;
392 return 0;
396 VXInteger xrange_ctor(VXState* v)
398 VXInteger i;
399 VXInteger pstart;
400 VXInteger pstop;
401 VXInteger pstep;
402 XRange* self = new XRange;
403 self->values = v->NewArray();
404 if(VX_FAILED(v->GetInteger(2, &pstart)))
406 return v->Raise_ParamTypeError(2, VX_OT_INTEGER, v->StackGet(2).Type());
408 if(VX_FAILED(v->GetInteger(3, &pstop)))
410 pstop = pstart;
411 pstart = 0;
413 if(VX_FAILED(v->GetInteger(4, &pstep)))
415 pstep = 1;
417 self->start = pstart;
418 self->stop = pstop;
419 self->step = pstep;
420 self->count = 0;
421 for(i=pstart; (pstop>-1)?(i<pstop):(i!=pstop); i+=pstep)
423 self->values->Append(VXObject(i));
425 v->SetInstanceUp(1, (VXUserPointer*)&self);
426 v->SetReleaseHook(1, xrange_releasehook);
427 return 0;
430 VXInteger xrange_values(VXState* v)
432 XRange* self;
433 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
434 v->Push(self->values);
435 return 1;
438 VXInteger xrange_get(VXState* v)
440 XRange* self;
441 VXObject val;
442 VXObject idx;
443 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
444 idx = v->StackGet(2);
445 if(!self->values->Get(idx.Integer(), val))
447 if(idx.IsNumeric())
449 return v->ThrowError("xrange::__get__: bad index");
451 else
453 return v->ThrowError();
456 v->Push(val);
457 return 1;
461 VXInteger xrange_nexti(VXState* v)
463 XRange* self;
464 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
465 if(self->count != self->values->Size())
467 v->Push(self->count++);
468 return 1;
470 return 0;
473 VXInteger xrange_tostring(VXState* v)
475 XRange* self;
476 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
477 std::stringstream str;
478 str << "<xrange at " << ((void*)self) << " ";
479 str << "("
480 << "start:" << self->start
481 << ", stop:" << self->stop
482 << ", step:" << self->step
483 << ")>";
484 v->PushString(str.str().c_str(), str.str().length());
485 return 1;
488 VXInteger xrange_typeof(VXState* v)
490 XRange* self;
491 v->GetInstanceUp(1, (VXUserPointer*)&self, 0);
492 v->PushString("xrange");
493 return 1;
496 VXRegFunction xrange_funcs[]=
498 {"constructor", xrange_ctor, -1, NULL},
499 {"values", xrange_values, -1, ".x"},
500 {"__get__", xrange_get, -1, NULL},
501 {"__nexti__", xrange_nexti, -1, NULL},
502 {"__tostring__", xrange_tostring, -1, NULL},
503 {"__typeof__", xrange_typeof, -1, NULL},
504 {0, 0, 0, 0},
507 VXRegFunction system_funcs[]=
509 {"platform", system_platform, 1, NULL},
510 {"platform_group", system_platform_group, 1, NULL},
511 {"seterrorhandler", system_seterrorhandler, 2, NULL},
512 {"debughook", system_setdebughook, 2, NULL},
513 {"enabledebug", system_enabledebuginfo, 2, NULL},
514 {"stackinfos", system_getstackinfos, 2, ".n"},
515 {"getroot", system_getroottable, 1, NULL},
516 {"setroot", system_setroottable, 2, NULL},
517 {"getconsttable", system_getconsttable, 1, NULL},
518 {"setconsttable", system_setconsttable, 2, NULL},
519 {"compilestring", system_compilestring, -2, ".ss"},
520 {"newthread", system_newthread, 2, ".c"},
521 {"suspend", system_suspend, -1, NULL},
522 {"type", system_type, 2, NULL},
523 {"callee", system_callee, 0, NULL},
524 {"dummy", system_dummy, 0, NULL},
525 {"loadfile", system_loadfile, -2, ".sb"},
526 {"loadstring", system_compilestring, -2, ".ss"},
527 {"dofile", system_dofile, -2, ".sb"},
528 {"dostring", system_dostring, -2, ".sbs"},
529 {"writeclosuretofile", system_writeclosuretofile, 3, ".sc"},
530 {"atexit", system_atexit, 2, ".c"},
531 //{"repr", system_repr, 2, NULL},
532 {"errorhandler", system_errorhandler, 2, NULL},
533 {"gc_collect", system_gc_collect, 0, NULL},
534 {"gc_resurrect", system_gc_resurrect, 0, NULL},
535 {"gc_release", system_gc_release, 2, "."},
537 /** NOTE: these declarations are going to be deprecated in some
538 future release. remember to remove them at some point...
539 Main reason(s) for removal are usually:
540 + overly verbose function name (writeclosuretofile is way too long)
541 + ambigious/idiotic function name (gc_collect vs gccollect)
543 {"getstackinfos", system_getstackinfos, 2, ".n"},
544 {"setdebughook", system_setdebughook, 2, NULL},
545 {"enabledebuginfo", system_enabledebuginfo, 2, NULL},
546 {"seterrorhandler", system_seterrorhandler, 2, NULL},
547 {"getroottable", system_getroottable, 1, NULL},
548 {"setroottable", system_setroottable, 2, NULL},
549 {"getconsttable", system_getconsttable, 1, NULL},
550 {"setconsttable", system_setconsttable, 2, NULL},
551 {0, 0, 0, 0}
554 VXRegFunction system_globalfuncs[] =
556 {"assert", system_assert, -2, ".bs"},
557 {"print", system_print, -1, NULL},
558 {"println", system_println, -1, NULL},
559 {0, 0, 0, 0}
563 VXInteger voxstd_register_system(VXState* v)
565 VXTableObj* systb = v->NewTable();
566 systb->NewSlot(v->NewString("argv"), v->GetSysArgv());
567 v->RegisterLib("system", system_funcs, true, systb);
568 v->RegisterLib(NULL, system_globalfuncs, true);
569 v->GetRootTable()->NewSlot(v->NewString("xrange"), v->RegClass(xrange_funcs));
570 return VX_OK;