Johan Wikman / SQUIRREL3

Dependents:   Squirrel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sqbaselib.cpp Source File

sqbaselib.cpp

00001 /*
00002     see copyright notice in squirrel.h
00003 */
00004 #include "sqpcheader.h"
00005 #include "sqvm.h"
00006 #include "sqstring.h"
00007 #include "sqtable.h"
00008 #include "sqarray.h"
00009 #include "sqfuncproto.h"
00010 #include "sqclosure.h"
00011 #include "sqclass.h"
00012 #include <stdlib.h>
00013 #include <stdarg.h>
00014 #include <ctype.h>
00015 
00016 bool str2num(const SQChar *s,SQObjectPtr &res)
00017 {
00018     SQChar *end;
00019     const SQChar *e = s;
00020     SQBool isfloat = SQFalse;
00021     SQChar c;
00022     while((c = *e) != _SC('\0'))
00023     {
00024         if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation
00025             isfloat = SQTrue;
00026             break;
00027         }
00028         e++;
00029     }
00030     if(isfloat){
00031         SQFloat r = SQFloat(scstrtod(s,&end));
00032         if(s == end) return false;
00033         res = r;
00034     }
00035     else{
00036         SQInteger r = SQInteger(scstrtol(s,&end,10));
00037         if(s == end) return false;
00038         res = r;
00039     }
00040     return true;
00041 }
00042 
00043 static SQInteger base_dummy(HSQUIRRELVM v)
00044 {
00045     return 0;
00046 }
00047 
00048 #ifndef NO_GARBAGE_COLLECTOR
00049 static SQInteger base_collectgarbage(HSQUIRRELVM v)
00050 {
00051     sq_pushinteger(v, sq_collectgarbage(v));
00052     return 1;
00053 }
00054 static SQInteger base_resurectureachable(HSQUIRRELVM v)
00055 {
00056     sq_resurrectunreachable(v);
00057     return 1;
00058 }
00059 #endif
00060 
00061 static SQInteger base_getroottable(HSQUIRRELVM v)
00062 {
00063     v->Push(v->_roottable);
00064     return 1;
00065 }
00066 
00067 static SQInteger base_getconsttable(HSQUIRRELVM v)
00068 {
00069     v->Push(_ss(v)->_consts);
00070     return 1;
00071 }
00072 
00073 
00074 static SQInteger base_setroottable(HSQUIRRELVM v)
00075 {
00076     SQObjectPtr o = v->_roottable;
00077     if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
00078     v->Push(o);
00079     return 1;
00080 }
00081 
00082 static SQInteger base_setconsttable(HSQUIRRELVM v)
00083 {
00084     SQObjectPtr o = _ss(v)->_consts;
00085     if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
00086     v->Push(o);
00087     return 1;
00088 }
00089 
00090 static SQInteger base_seterrorhandler(HSQUIRRELVM v)
00091 {
00092     sq_seterrorhandler(v);
00093     return 0;
00094 }
00095 
00096 static SQInteger base_setdebughook(HSQUIRRELVM v)
00097 {
00098     sq_setdebughook(v);
00099     return 0;
00100 }
00101 
00102 static SQInteger base_enabledebuginfo(HSQUIRRELVM v)
00103 {
00104     SQObjectPtr &o=stack_get(v,2);
00105     
00106     sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue);
00107     return 0;
00108 }
00109 
00110 static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)
00111 {
00112     SQStackInfos si;
00113     SQInteger seq = 0;
00114     const SQChar *name = NULL;
00115     
00116     if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
00117     {
00118         const SQChar *fn = _SC("unknown");
00119         const SQChar *src = _SC("unknown");
00120         if(si.funcname)fn = si.funcname;
00121         if(si.source)src = si.source;
00122         sq_newtable(v);
00123         sq_pushstring(v, _SC("func"), -1);
00124         sq_pushstring(v, fn, -1);
00125         sq_newslot(v, -3, SQFalse);
00126         sq_pushstring(v, _SC("src"), -1);
00127         sq_pushstring(v, src, -1);
00128         sq_newslot(v, -3, SQFalse);
00129         sq_pushstring(v, _SC("line"), -1);
00130         sq_pushinteger(v, si.line);
00131         sq_newslot(v, -3, SQFalse);
00132         sq_pushstring(v, _SC("locals"), -1);
00133         sq_newtable(v);
00134         seq=0;
00135         while ((name = sq_getlocal(v, level, seq))) {
00136             sq_pushstring(v, name, -1);
00137             sq_push(v, -2);
00138             sq_newslot(v, -4, SQFalse);
00139             sq_pop(v, 1);
00140             seq++;
00141         }
00142         sq_newslot(v, -3, SQFalse);
00143         return 1;
00144     }
00145 
00146     return 0;
00147 }
00148 static SQInteger base_getstackinfos(HSQUIRRELVM v)
00149 {
00150     SQInteger level;
00151     sq_getinteger(v, -1, &level);
00152     return __getcallstackinfos(v,level);
00153 }
00154 
00155 static SQInteger base_assert(HSQUIRRELVM v)
00156 {
00157     if(SQVM::IsFalse(stack_get(v,2))){
00158         return sq_throwerror(v,_SC("assertion failed"));
00159     }
00160     return 0;
00161 }
00162 
00163 static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)
00164 {
00165     SQInteger top = sq_gettop(v);
00166     sidx=0;
00167     eidx=0;
00168     o=stack_get(v,1);
00169     SQObjectPtr &start=stack_get(v,2);
00170     if(type(start)!=OT_NULL && sq_isnumeric(start)){
00171         sidx=tointeger(start);
00172     }
00173     if(top>2){
00174         SQObjectPtr &end=stack_get(v,3);
00175         if(sq_isnumeric(end)){
00176             eidx=tointeger(end);
00177         }
00178     }
00179     else {
00180         eidx = sq_getsize(v,1);
00181     }
00182     return 1;
00183 }
00184 
00185 static SQInteger base_print(HSQUIRRELVM v)
00186 {
00187     const SQChar *str;
00188     sq_tostring(v,2);
00189     sq_getstring(v,-1,&str);
00190     if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
00191     return 0;
00192 }
00193 
00194 static SQInteger base_error(HSQUIRRELVM v)
00195 {
00196     const SQChar *str;
00197     sq_tostring(v,2);
00198     sq_getstring(v,-1,&str);
00199     if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);
00200     return 0;
00201 }
00202 
00203 static SQInteger base_compilestring(HSQUIRRELVM v)
00204 {
00205     SQInteger nargs=sq_gettop(v);
00206     const SQChar *src=NULL,*name=_SC("unnamedbuffer");
00207     SQInteger size;
00208     sq_getstring(v,2,&src);
00209     size=sq_getsize(v,2);
00210     if(nargs>2){
00211         sq_getstring(v,3,&name);
00212     }
00213     if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
00214         return 1;
00215     else
00216         return SQ_ERROR;
00217 }
00218 
00219 static SQInteger base_newthread(HSQUIRRELVM v)
00220 {
00221     SQObjectPtr &func = stack_get(v,2);
00222     SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;
00223     HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
00224     sq_move(newv,v,-2);
00225     return 1;
00226 }
00227 
00228 static SQInteger base_suspend(HSQUIRRELVM v)
00229 {
00230     return sq_suspendvm(v);
00231 }
00232 
00233 static SQInteger base_array(HSQUIRRELVM v)
00234 {
00235     SQArray *a;
00236     SQObject &size = stack_get(v,2);
00237     if(sq_gettop(v) > 2) {
00238         a = SQArray::Create(_ss(v),0);
00239         a->Resize(tointeger(size),stack_get(v,3));
00240     }
00241     else {
00242         a = SQArray::Create(_ss(v),tointeger(size));
00243     }
00244     v->Push(a);
00245     return 1;
00246 }
00247 
00248 static SQInteger base_type(HSQUIRRELVM v)
00249 {
00250     SQObjectPtr &o = stack_get(v,2);
00251     v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
00252     return 1;
00253 }
00254 
00255 static SQInteger base_callee(HSQUIRRELVM v)
00256 {
00257     if(v->_callsstacksize > 1)
00258     {
00259         v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
00260         return 1;
00261     }
00262     return sq_throwerror(v,_SC("no closure in the calls stack"));
00263 }
00264 
00265 static SQRegFunction base_funcs[]={
00266     //generic
00267     {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
00268     {_SC("setdebughook"),base_setdebughook,2, NULL},
00269     {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
00270     {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
00271     {_SC("getroottable"),base_getroottable,1, NULL},
00272     {_SC("setroottable"),base_setroottable,2, NULL},
00273     {_SC("getconsttable"),base_getconsttable,1, NULL},
00274     {_SC("setconsttable"),base_setconsttable,2, NULL},
00275     {_SC("assert"),base_assert,2, NULL},
00276     {_SC("print"),base_print,2, NULL},
00277     {_SC("error"),base_error,2, NULL},
00278     {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
00279     {_SC("newthread"),base_newthread,2, _SC(".c")},
00280     {_SC("suspend"),base_suspend,-1, NULL},
00281     {_SC("array"),base_array,-2, _SC(".n")},
00282     {_SC("type"),base_type,2, NULL},
00283     {_SC("callee"),base_callee,0,NULL},
00284     {_SC("dummy"),base_dummy,0,NULL},
00285 #ifndef NO_GARBAGE_COLLECTOR
00286     {_SC("collectgarbage"),base_collectgarbage,0, NULL},
00287     {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},
00288 #endif
00289     {0,0}
00290 };
00291 
00292 void sq_base_register(HSQUIRRELVM v)
00293 {
00294     SQInteger i=0;
00295     sq_pushroottable(v);
00296     while(base_funcs[i].name!=0) {
00297         sq_pushstring(v,base_funcs[i].name,-1);
00298         sq_newclosure(v,base_funcs[i].f,0);
00299         sq_setnativeclosurename(v,-1,base_funcs[i].name);
00300         sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
00301         sq_newslot(v,-3, SQFalse);
00302         i++;
00303     }
00304     
00305     sq_pushstring(v,_SC("_versionnumber_"),-1);
00306     sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);
00307     sq_newslot(v,-3, SQFalse);
00308     sq_pushstring(v,_SC("_version_"),-1);
00309     sq_pushstring(v,SQUIRREL_VERSION,-1);
00310     sq_newslot(v,-3, SQFalse);
00311     sq_pushstring(v,_SC("_charsize_"),-1);
00312     sq_pushinteger(v,sizeof(SQChar));
00313     sq_newslot(v,-3, SQFalse);
00314     sq_pushstring(v,_SC("_intsize_"),-1);
00315     sq_pushinteger(v,sizeof(SQInteger));
00316     sq_newslot(v,-3, SQFalse);
00317     sq_pushstring(v,_SC("_floatsize_"),-1);
00318     sq_pushinteger(v,sizeof(SQFloat));
00319     sq_newslot(v,-3, SQFalse);
00320     sq_pop(v,1);
00321 }
00322 
00323 static SQInteger default_delegate_len(HSQUIRRELVM v)
00324 {
00325     v->Push(SQInteger(sq_getsize(v,1)));
00326     return 1;
00327 }
00328 
00329 static SQInteger default_delegate_tofloat(HSQUIRRELVM v)
00330 {
00331     SQObjectPtr &o=stack_get(v,1);
00332     switch(type(o)){
00333     case OT_STRING:{
00334         SQObjectPtr res;
00335         if(str2num(_stringval(o),res)){
00336             v->Push(SQObjectPtr(tofloat(res)));
00337             break;
00338         }}
00339         return sq_throwerror(v, _SC("cannot convert the string"));
00340         break;
00341     case OT_INTEGER:case OT_FLOAT:
00342         v->Push(SQObjectPtr(tofloat(o)));
00343         break;
00344     case OT_BOOL:
00345         v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
00346         break;
00347     default:
00348         v->PushNull();
00349         break;
00350     }
00351     return 1;
00352 }
00353 
00354 static SQInteger default_delegate_tointeger(HSQUIRRELVM v)
00355 {
00356     SQObjectPtr &o=stack_get(v,1);
00357     switch(type(o)){
00358     case OT_STRING:{
00359         SQObjectPtr res;
00360         if(str2num(_stringval(o),res)){
00361             v->Push(SQObjectPtr(tointeger(res)));
00362             break;
00363         }}
00364         return sq_throwerror(v, _SC("cannot convert the string"));
00365         break;
00366     case OT_INTEGER:case OT_FLOAT:
00367         v->Push(SQObjectPtr(tointeger(o)));
00368         break;
00369     case OT_BOOL:
00370         v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));
00371         break;
00372     default:
00373         v->PushNull();
00374         break;
00375     }
00376     return 1;
00377 }
00378 
00379 static SQInteger default_delegate_tostring(HSQUIRRELVM v)
00380 {
00381     sq_tostring(v,1);
00382     return 1;
00383 }
00384 
00385 static SQInteger obj_delegate_weakref(HSQUIRRELVM v)
00386 {
00387     sq_weakref(v,1);
00388     return 1;
00389 }
00390 
00391 static SQInteger obj_clear(HSQUIRRELVM v)
00392 {
00393     return sq_clear(v,-1);
00394 }
00395 
00396 
00397 static SQInteger number_delegate_tochar(HSQUIRRELVM v)
00398 {
00399     SQObject &o=stack_get(v,1);
00400     SQChar c = (SQChar)tointeger(o);
00401     v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
00402     return 1;
00403 }
00404 
00405 
00406 
00407 /////////////////////////////////////////////////////////////////
00408 //TABLE DEFAULT DELEGATE
00409 
00410 static SQInteger table_rawdelete(HSQUIRRELVM v)
00411 {
00412     if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
00413         return SQ_ERROR;
00414     return 1;
00415 }
00416 
00417 
00418 static SQInteger container_rawexists(HSQUIRRELVM v)
00419 {
00420     if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
00421         sq_pushbool(v,SQTrue);
00422         return 1;
00423     }
00424     sq_pushbool(v,SQFalse);
00425     return 1;
00426 }
00427 
00428 static SQInteger container_rawset(HSQUIRRELVM v)
00429 {
00430     return sq_rawset(v,-3);
00431 }
00432 
00433 
00434 static SQInteger container_rawget(HSQUIRRELVM v)
00435 {
00436     return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
00437 }
00438 
00439 static SQInteger table_setdelegate(HSQUIRRELVM v)
00440 {
00441     if(SQ_FAILED(sq_setdelegate(v,-2)))
00442         return SQ_ERROR;
00443     sq_push(v,-1); // -1 because sq_setdelegate pops 1
00444     return 1;
00445 }
00446 
00447 static SQInteger table_getdelegate(HSQUIRRELVM v)
00448 {
00449     return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;
00450 }
00451 
00452 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
00453     {_SC("len"),default_delegate_len,1, _SC("t")},
00454     {_SC("rawget"),container_rawget,2, _SC("t")},
00455     {_SC("rawset"),container_rawset,3, _SC("t")},
00456     {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
00457     {_SC("rawin"),container_rawexists,2, _SC("t")},
00458     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00459     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00460     {_SC("clear"),obj_clear,1, _SC(".")},
00461     {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
00462     {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
00463     {0,0}
00464 };
00465 
00466 //ARRAY DEFAULT DELEGATE///////////////////////////////////////
00467 
00468 static SQInteger array_append(HSQUIRRELVM v)
00469 {
00470     return sq_arrayappend(v,-2);
00471 }
00472 
00473 static SQInteger array_extend(HSQUIRRELVM v)
00474 {
00475     _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
00476     return 0;
00477 }
00478 
00479 static SQInteger array_reverse(HSQUIRRELVM v)
00480 {
00481     return sq_arrayreverse(v,-1);
00482 }
00483 
00484 static SQInteger array_pop(HSQUIRRELVM v)
00485 {
00486     return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
00487 }
00488 
00489 static SQInteger array_top(HSQUIRRELVM v)
00490 {
00491     SQObject &o=stack_get(v,1);
00492     if(_array(o)->Size()>0){
00493         v->Push(_array(o)->Top());
00494         return 1;
00495     }
00496     else return sq_throwerror(v,_SC("top() on a empty array"));
00497 }
00498 
00499 static SQInteger array_insert(HSQUIRRELVM v)
00500 {
00501     SQObject &o=stack_get(v,1);
00502     SQObject &idx=stack_get(v,2);
00503     SQObject &val=stack_get(v,3);
00504     if(!_array(o)->Insert(tointeger(idx),val))
00505         return sq_throwerror(v,_SC("index out of range"));
00506     return 0;
00507 }
00508 
00509 static SQInteger array_remove(HSQUIRRELVM v)
00510 {
00511     SQObject &o = stack_get(v, 1);
00512     SQObject &idx = stack_get(v, 2);
00513     if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
00514     SQObjectPtr val;
00515     if(_array(o)->Get(tointeger(idx), val)) {
00516         _array(o)->Remove(tointeger(idx));
00517         v->Push(val);
00518         return 1;
00519     }
00520     return sq_throwerror(v, _SC("idx out of range"));
00521 }
00522 
00523 static SQInteger array_resize(HSQUIRRELVM v)
00524 {
00525     SQObject &o = stack_get(v, 1);
00526     SQObject &nsize = stack_get(v, 2);
00527     SQObjectPtr fill;
00528     if(sq_isnumeric(nsize)) {
00529         if(sq_gettop(v) > 2)
00530             fill = stack_get(v, 3);
00531         _array(o)->Resize(tointeger(nsize),fill);
00532         return 0;
00533     }
00534     return sq_throwerror(v, _SC("size must be a number"));
00535 }
00536 
00537 static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {
00538     SQObjectPtr temp;
00539     SQInteger size = src->Size();
00540     for(SQInteger n = 0; n < size; n++) {
00541         src->Get(n,temp);
00542         v->Push(src);
00543         v->Push(temp);
00544         if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {
00545             return SQ_ERROR;
00546         }
00547         dest->Set(n,v->GetUp(-1));
00548         v->Pop();
00549     }
00550     return 0;
00551 }
00552 
00553 static SQInteger array_map(HSQUIRRELVM v)
00554 {
00555     SQObject &o = stack_get(v,1);
00556     SQInteger size = _array(o)->Size();
00557     SQObjectPtr ret = SQArray::Create(_ss(v),size);
00558     if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))
00559         return SQ_ERROR;
00560     v->Push(ret);
00561     return 1;
00562 }
00563 
00564 static SQInteger array_apply(HSQUIRRELVM v)
00565 {
00566     SQObject &o = stack_get(v,1);
00567     if(SQ_FAILED(__map_array(_array(o),_array(o),v)))
00568         return SQ_ERROR;
00569     return 0;
00570 }
00571 
00572 static SQInteger array_reduce(HSQUIRRELVM v)
00573 {
00574     SQObject &o = stack_get(v,1);
00575     SQArray *a = _array(o);
00576     SQInteger size = a->Size();
00577     if(size == 0) {
00578         return 0;
00579     }
00580     SQObjectPtr res;
00581     a->Get(0,res);
00582     if(size > 1) {
00583         SQObjectPtr other;
00584         for(SQInteger n = 1; n < size; n++) {
00585             a->Get(n,other);
00586             v->Push(o);
00587             v->Push(res);
00588             v->Push(other);
00589             if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
00590                 return SQ_ERROR;
00591             }
00592             res = v->GetUp(-1);
00593             v->Pop();
00594         }
00595     }
00596     v->Push(res);
00597     return 1;
00598 }
00599 
00600 static SQInteger array_filter(HSQUIRRELVM v)
00601 {
00602     SQObject &o = stack_get(v,1);
00603     SQArray *a = _array(o);
00604     SQObjectPtr ret = SQArray::Create(_ss(v),0);
00605     SQInteger size = a->Size();
00606     SQObjectPtr val;
00607     for(SQInteger n = 0; n < size; n++) {
00608         a->Get(n,val);
00609         v->Push(o);
00610         v->Push(n);
00611         v->Push(val);
00612         if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
00613             return SQ_ERROR;
00614         }
00615         if(!SQVM::IsFalse(v->GetUp(-1))) {
00616             _array(ret)->Append(val);
00617         }
00618         v->Pop();
00619     }
00620     v->Push(ret);
00621     return 1;
00622 }
00623 
00624 static SQInteger array_find(HSQUIRRELVM v)
00625 {
00626     SQObject &o = stack_get(v,1);
00627     SQObjectPtr &val = stack_get(v,2);
00628     SQArray *a = _array(o);
00629     SQInteger size = a->Size();
00630     SQObjectPtr temp;
00631     for(SQInteger n = 0; n < size; n++) {
00632         bool res = false;
00633         a->Get(n,temp);
00634         if(SQVM::IsEqual(temp,val,res) && res) {
00635             v->Push(n);
00636             return 1;
00637         }
00638     }
00639     return 0;
00640 }
00641 
00642 
00643 bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)
00644 {
00645     if(func < 0) {
00646         if(!v->ObjCmp(a,b,ret)) return false;
00647     }
00648     else {
00649         SQInteger top = sq_gettop(v);
00650         sq_push(v, func);
00651         sq_pushroottable(v);
00652         v->Push(a);
00653         v->Push(b);
00654         if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) {
00655             if(!sq_isstring( v->_lasterror)) 
00656                 v->Raise_Error(_SC("compare func failed"));
00657             return false;
00658         }
00659         if(SQ_FAILED(sq_getinteger(v, -1, &ret))) {
00660             v->Raise_Error(_SC("numeric value expected as return value of the compare function"));
00661             return false;
00662         }
00663         sq_settop(v, top);
00664         return true;
00665     }
00666     return true;
00667 }
00668 
00669 bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)
00670 {
00671     SQInteger maxChild;
00672     SQInteger done = 0;
00673     SQInteger ret;
00674     SQInteger root2;
00675     while (((root2 = root * 2) <= bottom) && (!done))
00676     {
00677         if (root2 == bottom) {
00678             maxChild = root2;
00679         }
00680         else {
00681             if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
00682                 return false;
00683             if (ret > 0) {
00684                 maxChild = root2;
00685             }
00686             else {
00687                 maxChild = root2 + 1;
00688             }
00689         }
00690 
00691         if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
00692             return false;
00693         if (ret < 0) {
00694             if (root == maxChild) {
00695                 v->Raise_Error(_SC("inconsistent compare function"));
00696                 return false; // We'd be swapping ourselve. The compare function is incorrect
00697             }
00698 
00699             _Swap(arr->_values[root],arr->_values[maxChild]);
00700             root = maxChild;
00701         }
00702         else {
00703             done = 1;
00704         }
00705     }
00706     return true;
00707 }
00708 
00709 bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)
00710 {
00711     SQArray *a = _array(arr);
00712     SQInteger i;
00713     SQInteger array_size = a->Size();
00714     for (i = (array_size / 2); i >= 0; i--) {
00715         if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
00716     }
00717 
00718     for (i = array_size-1; i >= 1; i--)
00719     {
00720         _Swap(a->_values[0],a->_values[i]);
00721         if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
00722     }
00723     return true;
00724 }
00725 
00726 static SQInteger array_sort(HSQUIRRELVM v)
00727 {
00728     SQInteger func = -1;
00729     SQObjectPtr &o = stack_get(v,1);
00730     if(_array(o)->Size() > 1) {
00731         if(sq_gettop(v) == 2) func = 2;
00732         if(!_hsort(v, o, 0, _array(o)->Size()-1, func))
00733             return SQ_ERROR;
00734 
00735     }
00736     return 0;
00737 }
00738 
00739 static SQInteger array_slice(HSQUIRRELVM v)
00740 {
00741     SQInteger sidx,eidx;
00742     SQObjectPtr o;
00743     if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
00744     SQInteger alen = _array(o)->Size();
00745     if(sidx < 0)sidx = alen + sidx;
00746     if(eidx < 0)eidx = alen + eidx;
00747     if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));
00748     if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));
00749     SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
00750     SQObjectPtr t;
00751     SQInteger count=0;
00752     for(SQInteger i=sidx;i<eidx;i++){
00753         _array(o)->Get(i,t);
00754         arr->Set(count++,t);
00755     }
00756     v->Push(arr);
00757     return 1;
00758     
00759 }
00760 
00761 SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
00762     {_SC("len"),default_delegate_len,1, _SC("a")},
00763     {_SC("append"),array_append,2, _SC("a")},
00764     {_SC("extend"),array_extend,2, _SC("aa")},
00765     {_SC("push"),array_append,2, _SC("a")},
00766     {_SC("pop"),array_pop,1, _SC("a")},
00767     {_SC("top"),array_top,1, _SC("a")},
00768     {_SC("insert"),array_insert,3, _SC("an")},
00769     {_SC("remove"),array_remove,2, _SC("an")},
00770     {_SC("resize"),array_resize,-2, _SC("an")},
00771     {_SC("reverse"),array_reverse,1, _SC("a")},
00772     {_SC("sort"),array_sort,-1, _SC("ac")},
00773     {_SC("slice"),array_slice,-1, _SC("ann")},
00774     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00775     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00776     {_SC("clear"),obj_clear,1, _SC(".")},
00777     {_SC("map"),array_map,2, _SC("ac")}, 
00778     {_SC("apply"),array_apply,2, _SC("ac")}, 
00779     {_SC("reduce"),array_reduce,2, _SC("ac")}, 
00780     {_SC("filter"),array_filter,2, _SC("ac")},
00781     {_SC("find"),array_find,2, _SC("a.")},
00782     {0,0}
00783 };
00784 
00785 //STRING DEFAULT DELEGATE//////////////////////////
00786 static SQInteger string_slice(HSQUIRRELVM v)
00787 {
00788     SQInteger sidx,eidx;
00789     SQObjectPtr o;
00790     if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
00791     SQInteger slen = _string(o)->_len;
00792     if(sidx < 0)sidx = slen + sidx;
00793     if(eidx < 0)eidx = slen + eidx;
00794     if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));
00795     if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));
00796     v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
00797     return 1;
00798 }
00799 
00800 static SQInteger string_find(HSQUIRRELVM v)
00801 {
00802     SQInteger top,start_idx=0;
00803     const SQChar *str,*substr,*ret;
00804     if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){
00805         if(top>2)sq_getinteger(v,3,&start_idx);
00806         if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){
00807             ret=scstrstr(&str[start_idx],substr);
00808             if(ret){
00809                 sq_pushinteger(v,(SQInteger)(ret-str));
00810                 return 1;
00811             }
00812         }
00813         return 0;
00814     }
00815     return sq_throwerror(v,_SC("invalid param"));
00816 }
00817 
00818 #define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \
00819 { \
00820     SQObject str=stack_get(v,1); \
00821     SQInteger len=_string(str)->_len; \
00822     const SQChar *sThis=_stringval(str); \
00823     SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
00824     for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \
00825     v->Push(SQString::Create(_ss(v),sNew,len)); \
00826     return 1; \
00827 }
00828 
00829 
00830 STRING_TOFUNCZ(tolower)
00831 STRING_TOFUNCZ(toupper)
00832 
00833 SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
00834     {_SC("len"),default_delegate_len,1, _SC("s")},
00835     {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},
00836     {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},
00837     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00838     {_SC("slice"),string_slice,-1, _SC(" s n  n")},
00839     {_SC("find"),string_find,-2, _SC("s s n ")},
00840     {_SC("tolower"),string_tolower,1, _SC("s")},
00841     {_SC("toupper"),string_toupper,1, _SC("s")},
00842     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00843     {0,0}
00844 };
00845 
00846 //INTEGER DEFAULT DELEGATE//////////////////////////
00847 SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
00848     {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
00849     {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
00850     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00851     {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
00852     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00853     {0,0}
00854 };
00855 
00856 //CLOSURE DEFAULT DELEGATE//////////////////////////
00857 static SQInteger closure_pcall(HSQUIRRELVM v)
00858 {
00859     return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;
00860 }
00861 
00862 static SQInteger closure_call(HSQUIRRELVM v)
00863 {
00864     return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
00865 }
00866 
00867 static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)
00868 {
00869     SQArray *aparams=_array(stack_get(v,2));
00870     SQInteger nparams=aparams->Size();
00871     v->Push(stack_get(v,1));
00872     for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
00873     return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;
00874 }
00875 
00876 static SQInteger closure_acall(HSQUIRRELVM v)
00877 {
00878     return _closure_acall(v,SQTrue);
00879 }
00880 
00881 static SQInteger closure_pacall(HSQUIRRELVM v)
00882 {
00883     return _closure_acall(v,SQFalse);
00884 }
00885 
00886 static SQInteger closure_bindenv(HSQUIRRELVM v)
00887 {
00888     if(SQ_FAILED(sq_bindenv(v,1)))
00889         return SQ_ERROR;
00890     return 1;
00891 }
00892 
00893 static SQInteger closure_getinfos(HSQUIRRELVM v) {
00894     SQObject o = stack_get(v,1);
00895     SQTable *res = SQTable::Create(_ss(v),4);
00896     if(type(o) == OT_CLOSURE) {
00897         SQFunctionProto *f = _closure(o)->_function;
00898         SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
00899         SQObjectPtr params = SQArray::Create(_ss(v),nparams);
00900     SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams);
00901         for(SQInteger n = 0; n<f->_nparameters; n++) {
00902             _array(params)->Set((SQInteger)n,f->_parameters[n]);
00903         }
00904     for(SQInteger j = 0; j<f->_ndefaultparams; j++) {
00905             _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]);
00906         }
00907         if(f->_varparams) {
00908             _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));
00909         }
00910         res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false);
00911         res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name);
00912         res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);
00913         res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);
00914         res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);
00915     res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams);
00916     }
00917     else { //OT_NATIVECLOSURE 
00918         SQNativeClosure *nc = _nativeclosure(o);
00919         res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);
00920         res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);
00921         res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
00922         SQObjectPtr typecheck;
00923         if(nc->_typecheck.size() > 0) {
00924             typecheck =
00925                 SQArray::Create(_ss(v), nc->_typecheck.size());
00926             for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
00927                     _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
00928             }
00929         }
00930         res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
00931     }
00932     v->Push(res);
00933     return 1;
00934 }
00935 
00936 
00937 
00938 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
00939     {_SC("call"),closure_call,-1, _SC("c")},
00940     {_SC("pcall"),closure_pcall,-1, _SC("c")},
00941     {_SC("acall"),closure_acall,2, _SC("ca")},
00942     {_SC("pacall"),closure_pacall,2, _SC("ca")},
00943     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00944     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00945     {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
00946     {_SC("getinfos"),closure_getinfos,1, _SC("c")},
00947     {0,0}
00948 };
00949 
00950 //GENERATOR DEFAULT DELEGATE
00951 static SQInteger generator_getstatus(HSQUIRRELVM v)
00952 {
00953     SQObject &o=stack_get(v,1);
00954     switch(_generator(o)->_state){
00955         case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;
00956         case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;
00957         case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;
00958     }
00959     return 1;
00960 }
00961 
00962 SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
00963     {_SC("getstatus"),generator_getstatus,1, _SC("g")},
00964     {_SC("weakref"),obj_delegate_weakref,1, NULL },
00965     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
00966     {0,0}
00967 };
00968 
00969 //THREAD DEFAULT DELEGATE
00970 static SQInteger thread_call(HSQUIRRELVM v)
00971 {
00972     SQObjectPtr o = stack_get(v,1);
00973     if(type(o) == OT_THREAD) {
00974         SQInteger nparams = sq_gettop(v);
00975         _thread(o)->Push(_thread(o)->_roottable);
00976         for(SQInteger i = 2; i<(nparams+1); i++)
00977             sq_move(_thread(o),v,i);
00978         if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) {
00979             sq_move(v,_thread(o),-1);
00980             sq_pop(_thread(o),1);
00981             return 1;
00982         }
00983         v->_lasterror = _thread(o)->_lasterror;
00984         return SQ_ERROR;
00985     }
00986     return sq_throwerror(v,_SC("wrong parameter"));
00987 }
00988 
00989 static SQInteger thread_wakeup(HSQUIRRELVM v)
00990 {
00991     SQObjectPtr o = stack_get(v,1);
00992     if(type(o) == OT_THREAD) {
00993         SQVM *thread = _thread(o);
00994         SQInteger state = sq_getvmstate(thread);
00995         if(state != SQ_VMSTATE_SUSPENDED) {
00996             switch(state) {
00997                 case SQ_VMSTATE_IDLE:
00998                     return sq_throwerror(v,_SC("cannot wakeup a idle thread"));
00999                 break;
01000                 case SQ_VMSTATE_RUNNING:
01001                     return sq_throwerror(v,_SC("cannot wakeup a running thread"));
01002                 break;
01003             }
01004         }
01005             
01006         SQInteger wakeupret = sq_gettop(v)>1?1:0;
01007         if(wakeupret) {
01008             sq_move(thread,v,2);
01009         }
01010         if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) {
01011             sq_move(v,thread,-1);
01012             sq_pop(thread,1); //pop retval
01013             if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
01014                 sq_settop(thread,1); //pop roottable
01015             }
01016             return 1;
01017         }
01018         sq_settop(thread,1);
01019         v->_lasterror = thread->_lasterror;
01020         return SQ_ERROR;
01021     }
01022     return sq_throwerror(v,_SC("wrong parameter"));
01023 }
01024 
01025 static SQInteger thread_getstatus(HSQUIRRELVM v)
01026 {
01027     SQObjectPtr &o = stack_get(v,1);
01028     switch(sq_getvmstate(_thread(o))) {
01029         case SQ_VMSTATE_IDLE:
01030             sq_pushstring(v,_SC("idle"),-1);
01031         break;
01032         case SQ_VMSTATE_RUNNING:
01033             sq_pushstring(v,_SC("running"),-1);
01034         break;
01035         case SQ_VMSTATE_SUSPENDED:
01036             sq_pushstring(v,_SC("suspended"),-1);
01037         break;
01038         default:
01039             return sq_throwerror(v,_SC("internal VM error"));
01040     }
01041     return 1;
01042 }
01043 
01044 static SQInteger thread_getstackinfos(HSQUIRRELVM v)
01045 {
01046     SQObjectPtr o = stack_get(v,1);
01047     if(type(o) == OT_THREAD) {
01048         SQVM *thread = _thread(o);
01049         SQInteger threadtop = sq_gettop(thread);
01050         SQInteger level;
01051         sq_getinteger(v,-1,&level);
01052         SQRESULT res = __getcallstackinfos(thread,level);
01053         if(SQ_FAILED(res))
01054         {
01055             sq_settop(thread,threadtop);
01056             if(type(thread->_lasterror) == OT_STRING) {
01057                 sq_throwerror(v,_stringval(thread->_lasterror));
01058             }
01059             else {
01060                 sq_throwerror(v,_SC("unknown error"));
01061             }
01062         }
01063         if(res > 0) {
01064             //some result
01065             sq_move(v,thread,-1);
01066             sq_settop(thread,threadtop);
01067             return 1;
01068         }
01069         //no result
01070         sq_settop(thread,threadtop);
01071         return 0;
01072         
01073     }
01074     return sq_throwerror(v,_SC("wrong parameter"));
01075 }
01076 
01077 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
01078     {_SC("call"), thread_call, -1, _SC("v")},
01079     {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
01080     {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
01081     {_SC("weakref"),obj_delegate_weakref,1, NULL },
01082     {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},
01083     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
01084     {0,0},
01085 };
01086 
01087 static SQInteger class_getattributes(HSQUIRRELVM v)
01088 {
01089     return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;
01090 }
01091 
01092 static SQInteger class_setattributes(HSQUIRRELVM v)
01093 {
01094     return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;
01095 }
01096 
01097 static SQInteger class_instance(HSQUIRRELVM v)
01098 {
01099     return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;
01100 }
01101 
01102 static SQInteger class_getbase(HSQUIRRELVM v)
01103 {
01104     return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;
01105 }
01106 
01107 static SQInteger class_newmember(HSQUIRRELVM v)
01108 {
01109     SQInteger top = sq_gettop(v);
01110     SQBool bstatic = SQFalse;
01111     if(top == 5)
01112     {
01113         sq_tobool(v,-1,&bstatic);
01114         sq_pop(v,1);
01115     }
01116 
01117     if(top < 4) {
01118         sq_pushnull(v);
01119     }
01120     return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR;
01121 }
01122 
01123 static SQInteger class_rawnewmember(HSQUIRRELVM v)
01124 {
01125     SQInteger top = sq_gettop(v);
01126     SQBool bstatic = SQFalse;
01127     if(top == 5)
01128     {
01129         sq_tobool(v,-1,&bstatic);
01130         sq_pop(v,1);
01131     }
01132 
01133     if(top < 4) {
01134         sq_pushnull(v);
01135     }
01136     return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR;
01137 }
01138 
01139 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
01140     {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
01141     {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
01142     {_SC("rawget"),container_rawget,2, _SC("y")},
01143     {_SC("rawset"),container_rawset,3, _SC("y")},
01144     {_SC("rawin"),container_rawexists,2, _SC("y")},
01145     {_SC("weakref"),obj_delegate_weakref,1, NULL },
01146     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
01147     {_SC("instance"),class_instance,1, _SC("y")},
01148     {_SC("getbase"),class_getbase,1, _SC("y")},
01149     {_SC("newmember"),class_newmember,-3, _SC("y")},
01150     {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},
01151     {0,0}
01152 };
01153 
01154 
01155 static SQInteger instance_getclass(HSQUIRRELVM v)
01156 {
01157     if(SQ_SUCCEEDED(sq_getclass(v,1)))
01158         return 1;
01159     return SQ_ERROR;
01160 }
01161 
01162 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
01163     {_SC("getclass"), instance_getclass, 1, _SC("x")},
01164     {_SC("rawget"),container_rawget,2, _SC("x")},
01165     {_SC("rawset"),container_rawset,3, _SC("x")},
01166     {_SC("rawin"),container_rawexists,2, _SC("x")},
01167     {_SC("weakref"),obj_delegate_weakref,1, NULL },
01168     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
01169     {0,0}
01170 };
01171 
01172 static SQInteger weakref_ref(HSQUIRRELVM v)
01173 {
01174     if(SQ_FAILED(sq_getweakrefval(v,1)))
01175         return SQ_ERROR;
01176     return 1;
01177 }
01178 
01179 SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
01180     {_SC("ref"),weakref_ref,1, _SC("r")},
01181     {_SC("weakref"),obj_delegate_weakref,1, NULL },
01182     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
01183     {0,0}
01184 };
01185