Back to home page

Enduro/X

 
 

    


0001 /*

0002     see copyright notice in pscript.h

0003 */
0004 #include "pspcheader.h"
0005 #include "psvm.h"
0006 #include "psstring.h"
0007 #include "pstable.h"
0008 #include "psarray.h"
0009 #include "psfuncproto.h"
0010 #include "psclosure.h"
0011 #include "psclass.h"
0012 #include <stdlib.h>
0013 #include <stdarg.h>
0014 #include <ctype.h>
0015 
0016 static bool str2num(const PSChar *s,PSObjectPtr &res,PSInteger base)
0017 {
0018     PSChar *end;
0019     const PSChar *e = s;
0020     bool iseintbase = base > 13; //to fix error converting hexadecimals with e like 56f0791e

0021     bool isfloat = false;
0022     PSChar c;
0023     while((c = *e) != _SC('\0'))
0024     {
0025         if (c == _SC('.') || (!iseintbase && (c == _SC('E') || c == _SC('e')))) { //e and E is for scientific notation

0026             isfloat = true;
0027             break;
0028         }
0029         e++;
0030     }
0031     if(isfloat){
0032         PSFloat r = PSFloat(scstrtod(s,&end));
0033         if(s == end) return false;
0034         res = r;
0035     }
0036     else{
0037         PSInteger r = PSInteger(scstrtol(s,&end,(int)base));
0038         if(s == end) return false;
0039         res = r;
0040     }
0041     return true;
0042 }
0043 
0044 static PSInteger base_dummy(HPSCRIPTVM PS_UNUSED_ARG(v))
0045 {
0046     return 0;
0047 }
0048 
0049 #ifndef NO_GARBAGE_COLLECTOR
0050 static PSInteger base_collectgarbage(HPSCRIPTVM v)
0051 {
0052     ps_pushinteger(v, ps_collectgarbage(v));
0053     return 1;
0054 }
0055 static PSInteger base_resurectureachable(HPSCRIPTVM v)
0056 {
0057     ps_resurrectunreachable(v);
0058     return 1;
0059 }
0060 #endif
0061 
0062 static PSInteger base_getroottable(HPSCRIPTVM v)
0063 {
0064     v->Push(v->_roottable);
0065     return 1;
0066 }
0067 
0068 static PSInteger base_getconsttable(HPSCRIPTVM v)
0069 {
0070     v->Push(_ss(v)->_consts);
0071     return 1;
0072 }
0073 
0074 
0075 static PSInteger base_setroottable(HPSCRIPTVM v)
0076 {
0077     PSObjectPtr o = v->_roottable;
0078     if(PS_FAILED(ps_setroottable(v))) return PS_ERROR;
0079     v->Push(o);
0080     return 1;
0081 }
0082 
0083 static PSInteger base_setconsttable(HPSCRIPTVM v)
0084 {
0085     PSObjectPtr o = _ss(v)->_consts;
0086     if(PS_FAILED(ps_setconsttable(v))) return PS_ERROR;
0087     v->Push(o);
0088     return 1;
0089 }
0090 
0091 static PSInteger base_seterrorhandler(HPSCRIPTVM v)
0092 {
0093     ps_seterrorhandler(v);
0094     return 0;
0095 }
0096 
0097 static PSInteger base_setdebughook(HPSCRIPTVM v)
0098 {
0099     ps_setdebughook(v);
0100     return 0;
0101 }
0102 
0103 static PSInteger base_enabledebuginfo(HPSCRIPTVM v)
0104 {
0105     PSObjectPtr &o=stack_get(v,2);
0106 
0107     ps_enabledebuginfo(v,PSVM::IsFalse(o)?PSFalse:PSTrue);
0108     return 0;
0109 }
0110 
0111 static PSInteger __getcallstackinfos(HPSCRIPTVM v,PSInteger level)
0112 {
0113     PSStackInfos si;
0114     PSInteger seq = 0;
0115     const PSChar *name = NULL;
0116 
0117     if (PS_SUCCEEDED(ps_stackinfos(v, level, &si)))
0118     {
0119         const PSChar *fn = _SC("unknown");
0120         const PSChar *src = _SC("unknown");
0121         if(si.funcname)fn = si.funcname;
0122         if(si.source)src = si.source;
0123         ps_newtable(v);
0124         ps_pushstring(v, _SC("func"), -1);
0125         ps_pushstring(v, fn, -1);
0126         ps_newslot(v, -3, PSFalse);
0127         ps_pushstring(v, _SC("src"), -1);
0128         ps_pushstring(v, src, -1);
0129         ps_newslot(v, -3, PSFalse);
0130         ps_pushstring(v, _SC("line"), -1);
0131         ps_pushinteger(v, si.line);
0132         ps_newslot(v, -3, PSFalse);
0133         ps_pushstring(v, _SC("locals"), -1);
0134         ps_newtable(v);
0135         seq=0;
0136         while ((name = ps_getlocal(v, level, seq))) {
0137             ps_pushstring(v, name, -1);
0138             ps_push(v, -2);
0139             ps_newslot(v, -4, PSFalse);
0140             ps_pop(v, 1);
0141             seq++;
0142         }
0143         ps_newslot(v, -3, PSFalse);
0144         return 1;
0145     }
0146 
0147     return 0;
0148 }
0149 static PSInteger base_getstackinfos(HPSCRIPTVM v)
0150 {
0151     PSInteger level;
0152     ps_getinteger(v, -1, &level);
0153     return __getcallstackinfos(v,level);
0154 }
0155 
0156 static PSInteger base_assert(HPSCRIPTVM v)
0157 {
0158     if(PSVM::IsFalse(stack_get(v,2))){
0159         return ps_throwerror(v,_SC("assertion failed"));
0160     }
0161     return 0;
0162 }
0163 
0164 static PSInteger get_slice_params(HPSCRIPTVM v,PSInteger &sidx,PSInteger &eidx,PSObjectPtr &o)
0165 {
0166     PSInteger top = ps_gettop(v);
0167     sidx=0;
0168     eidx=0;
0169     o=stack_get(v,1);
0170     if(top>1){
0171         PSObjectPtr &start=stack_get(v,2);
0172         if(type(start)!=OT_NULL && ps_isnumeric(start)){
0173             sidx=tointeger(start);
0174         }
0175     }
0176     if(top>2){
0177         PSObjectPtr &end=stack_get(v,3);
0178         if(ps_isnumeric(end)){
0179             eidx=tointeger(end);
0180         }
0181     }
0182     else {
0183         eidx = ps_getsize(v,1);
0184     }
0185     return 1;
0186 }
0187 
0188 static PSInteger base_print(HPSCRIPTVM v)
0189 {
0190     const PSChar *str;
0191     if(PS_SUCCEEDED(ps_tostring(v,2)))
0192     {
0193         if(PS_SUCCEEDED(ps_getstring(v,-1,&str))) {
0194             if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
0195             return 0;
0196         }
0197     }
0198     return PS_ERROR;
0199 }
0200 
0201 static PSInteger base_error(HPSCRIPTVM v)
0202 {
0203     const PSChar *str;
0204     if(PS_SUCCEEDED(ps_tostring(v,2)))
0205     {
0206         if(PS_SUCCEEDED(ps_getstring(v,-1,&str))) {
0207             if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);
0208             return 0;
0209         }
0210     }
0211     return PS_ERROR;
0212 }
0213 
0214 static PSInteger base_compilestring(HPSCRIPTVM v)
0215 {
0216     PSInteger nargs=ps_gettop(v);
0217     const PSChar *src=NULL,*name=_SC("unnamedbuffer");
0218     PSInteger size;
0219     ps_getstring(v,2,&src);
0220     size=ps_getsize(v,2);
0221     if(nargs>2){
0222         ps_getstring(v,3,&name);
0223     }
0224     if(PS_SUCCEEDED(ps_compilebuffer(v,src,size,name,PSFalse)))
0225         return 1;
0226     else
0227         return PS_ERROR;
0228 }
0229 
0230 static PSInteger base_newthread(HPSCRIPTVM v)
0231 {
0232     PSObjectPtr &func = stack_get(v,2);
0233     PSInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;
0234     HPSCRIPTVM newv = ps_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
0235     ps_move(newv,v,-2);
0236     return 1;
0237 }
0238 
0239 static PSInteger base_suspend(HPSCRIPTVM v)
0240 {
0241     return ps_suspendvm(v);
0242 }
0243 
0244 static PSInteger base_array(HPSCRIPTVM v)
0245 {
0246     PSArray *a;
0247     PSObject &size = stack_get(v,2);
0248     if(ps_gettop(v) > 2) {
0249         a = PSArray::Create(_ss(v),0);
0250         a->Resize(tointeger(size),stack_get(v,3));
0251     }
0252     else {
0253         a = PSArray::Create(_ss(v),tointeger(size));
0254     }
0255     v->Push(a);
0256     return 1;
0257 }
0258 
0259 static PSInteger base_type(HPSCRIPTVM v)
0260 {
0261     PSObjectPtr &o = stack_get(v,2);
0262     v->Push(PSString::Create(_ss(v),GetTypeName(o),-1));
0263     return 1;
0264 }
0265 
0266 static PSInteger base_callee(HPSCRIPTVM v)
0267 {
0268     if(v->_callsstacksize > 1)
0269     {
0270         v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
0271         return 1;
0272     }
0273     return ps_throwerror(v,_SC("no closure in the calls stack"));
0274 }
0275 
0276 static const PSRegFunction base_funcs[]={
0277     //generic

0278     {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
0279     {_SC("setdebughook"),base_setdebughook,2, NULL},
0280     {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
0281     {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
0282     {_SC("getroottable"),base_getroottable,1, NULL},
0283     {_SC("setroottable"),base_setroottable,2, NULL},
0284     {_SC("getconsttable"),base_getconsttable,1, NULL},
0285     {_SC("setconsttable"),base_setconsttable,2, NULL},
0286     {_SC("assert"),base_assert,2, NULL},
0287     {_SC("print"),base_print,2, NULL},
0288     {_SC("error"),base_error,2, NULL},
0289     {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
0290     {_SC("newthread"),base_newthread,2, _SC(".c")},
0291     {_SC("suspend"),base_suspend,-1, NULL},
0292     {_SC("array"),base_array,-2, _SC(".n")},
0293     {_SC("type"),base_type,2, NULL},
0294     {_SC("callee"),base_callee,0,NULL},
0295     {_SC("dummy"),base_dummy,0,NULL},
0296 #ifndef NO_GARBAGE_COLLECTOR
0297     {_SC("collectgarbage"),base_collectgarbage,0, NULL},
0298     {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},
0299 #endif
0300     {NULL,(PSFUNCTION)0,0,NULL}
0301 };
0302 
0303 void ps_base_register(HPSCRIPTVM v)
0304 {
0305     PSInteger i=0;
0306     ps_pushroottable(v);
0307     while(base_funcs[i].name!=0) {
0308         ps_pushstring(v,base_funcs[i].name,-1);
0309         ps_newclosure(v,base_funcs[i].f,0);
0310         ps_setnativeclosurename(v,-1,base_funcs[i].name);
0311         ps_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
0312         ps_newslot(v,-3, PSFalse);
0313         i++;
0314     }
0315 
0316     ps_pushstring(v,_SC("_versionnumber_"),-1);
0317     ps_pushinteger(v,PSCRIPT_VERSION_NUMBER);
0318     ps_newslot(v,-3, PSFalse);
0319     ps_pushstring(v,_SC("_version_"),-1);
0320     ps_pushstring(v,PSCRIPT_VERSION,-1);
0321     ps_newslot(v,-3, PSFalse);
0322     ps_pushstring(v,_SC("_charsize_"),-1);
0323     ps_pushinteger(v,sizeof(PSChar));
0324     ps_newslot(v,-3, PSFalse);
0325     ps_pushstring(v,_SC("_intsize_"),-1);
0326     ps_pushinteger(v,sizeof(PSInteger));
0327     ps_newslot(v,-3, PSFalse);
0328     ps_pushstring(v,_SC("_floatsize_"),-1);
0329     ps_pushinteger(v,sizeof(PSFloat));
0330     ps_newslot(v,-3, PSFalse);
0331     ps_pop(v,1);
0332 }
0333 
0334 static PSInteger default_delegate_len(HPSCRIPTVM v)
0335 {
0336     v->Push(PSInteger(ps_getsize(v,1)));
0337     return 1;
0338 }
0339 
0340 static PSInteger default_delegate_tofloat(HPSCRIPTVM v)
0341 {
0342     PSObjectPtr &o=stack_get(v,1);
0343     switch(type(o)){
0344     case OT_STRING:{
0345         PSObjectPtr res;
0346         if(str2num(_stringval(o),res,10)){
0347             v->Push(PSObjectPtr(tofloat(res)));
0348             break;
0349         }}
0350         return ps_throwerror(v, _SC("cannot convert the string"));
0351         break;
0352     case OT_INTEGER:case OT_FLOAT:
0353         v->Push(PSObjectPtr(tofloat(o)));
0354         break;
0355     case OT_BOOL:
0356         v->Push(PSObjectPtr((PSFloat)(_integer(o)?1:0)));
0357         break;
0358     default:
0359         v->PushNull();
0360         break;
0361     }
0362     return 1;
0363 }
0364 
0365 static PSInteger default_delegate_tointeger(HPSCRIPTVM v)
0366 {
0367     PSObjectPtr &o=stack_get(v,1);
0368     PSInteger base = 10;
0369     if(ps_gettop(v) > 1) {
0370         ps_getinteger(v,2,&base);
0371     }
0372     switch(type(o)){
0373     case OT_STRING:{
0374         PSObjectPtr res;
0375         if(str2num(_stringval(o),res,base)){
0376             v->Push(PSObjectPtr(tointeger(res)));
0377             break;
0378         }}
0379         return ps_throwerror(v, _SC("cannot convert the string"));
0380         break;
0381     case OT_INTEGER:case OT_FLOAT:
0382         v->Push(PSObjectPtr(tointeger(o)));
0383         break;
0384     case OT_BOOL:
0385         v->Push(PSObjectPtr(_integer(o)?(PSInteger)1:(PSInteger)0));
0386         break;
0387     default:
0388         v->PushNull();
0389         break;
0390     }
0391     return 1;
0392 }
0393 
0394 static PSInteger default_delegate_tostring(HPSCRIPTVM v)
0395 {
0396     if(PS_FAILED(ps_tostring(v,1)))
0397         return PS_ERROR;
0398     return 1;
0399 }
0400 
0401 static PSInteger obj_delegate_weakref(HPSCRIPTVM v)
0402 {
0403     ps_weakref(v,1);
0404     return 1;
0405 }
0406 
0407 static PSInteger obj_clear(HPSCRIPTVM v)
0408 {
0409     return ps_clear(v,-1);
0410 }
0411 
0412 
0413 static PSInteger number_delegate_tochar(HPSCRIPTVM v)
0414 {
0415     PSObject &o=stack_get(v,1);
0416     PSChar c = (PSChar)tointeger(o);
0417     v->Push(PSString::Create(_ss(v),(const PSChar *)&c,1));
0418     return 1;
0419 }
0420 
0421 
0422 
0423 /////////////////////////////////////////////////////////////////

0424 //TABLE DEFAULT DELEGATE

0425 
0426 static PSInteger table_rawdelete(HPSCRIPTVM v)
0427 {
0428     if(PS_FAILED(ps_rawdeleteslot(v,1,PSTrue)))
0429         return PS_ERROR;
0430     return 1;
0431 }
0432 
0433 
0434 static PSInteger container_rawexists(HPSCRIPTVM v)
0435 {
0436     if(PS_SUCCEEDED(ps_rawget(v,-2))) {
0437         ps_pushbool(v,PSTrue);
0438         return 1;
0439     }
0440     ps_pushbool(v,PSFalse);
0441     return 1;
0442 }
0443 
0444 static PSInteger container_rawset(HPSCRIPTVM v)
0445 {
0446     return ps_rawset(v,-3);
0447 }
0448 
0449 
0450 static PSInteger container_rawget(HPSCRIPTVM v)
0451 {
0452     return PS_SUCCEEDED(ps_rawget(v,-2))?1:PS_ERROR;
0453 }
0454 
0455 static PSInteger table_setdelegate(HPSCRIPTVM v)
0456 {
0457     if(PS_FAILED(ps_setdelegate(v,-2)))
0458         return PS_ERROR;
0459     ps_push(v,-1); // -1 because ps_setdelegate pops 1

0460     return 1;
0461 }
0462 
0463 static PSInteger table_getdelegate(HPSCRIPTVM v)
0464 {
0465     return PS_SUCCEEDED(ps_getdelegate(v,-1))?1:PS_ERROR;
0466 }
0467 
0468 const PSRegFunction PSSharedState::_table_default_delegate_funcz[]={
0469     {_SC("len"),default_delegate_len,1, _SC("t")},
0470     {_SC("rawget"),container_rawget,2, _SC("t")},
0471     {_SC("rawset"),container_rawset,3, _SC("t")},
0472     {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
0473     {_SC("rawin"),container_rawexists,2, _SC("t")},
0474     {_SC("weakref"),obj_delegate_weakref,1, NULL },
0475     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
0476     {_SC("clear"),obj_clear,1, _SC(".")},
0477     {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
0478     {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
0479     {NULL,(PSFUNCTION)0,0,NULL}
0480 };
0481 
0482 //ARRAY DEFAULT DELEGATE///////////////////////////////////////

0483 
0484 static PSInteger array_append(HPSCRIPTVM v)
0485 {
0486     return ps_arrayappend(v,-2);
0487 }
0488 
0489 static PSInteger array_extend(HPSCRIPTVM v)
0490 {
0491     _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
0492     return 0;
0493 }
0494 
0495 static PSInteger array_reverse(HPSCRIPTVM v)
0496 {
0497     return ps_arrayreverse(v,-1);
0498 }
0499 
0500 static PSInteger array_pop(HPSCRIPTVM v)
0501 {
0502     return PS_SUCCEEDED(ps_arraypop(v,1,PSTrue))?1:PS_ERROR;
0503 }
0504 
0505 static PSInteger array_top(HPSCRIPTVM v)
0506 {
0507     PSObject &o=stack_get(v,1);
0508     if(_array(o)->Size()>0){
0509         v->Push(_array(o)->Top());
0510         return 1;
0511     }
0512     else return ps_throwerror(v,_SC("top() on a empty array"));
0513 }
0514 
0515 static PSInteger array_insert(HPSCRIPTVM v)
0516 {
0517     PSObject &o=stack_get(v,1);
0518     PSObject &idx=stack_get(v,2);
0519     PSObject &val=stack_get(v,3);
0520     if(!_array(o)->Insert(tointeger(idx),val))
0521         return ps_throwerror(v,_SC("index out of range"));
0522     return 0;
0523 }
0524 
0525 static PSInteger array_remove(HPSCRIPTVM v)
0526 {
0527     PSObject &o = stack_get(v, 1);
0528     PSObject &idx = stack_get(v, 2);
0529     if(!ps_isnumeric(idx)) return ps_throwerror(v, _SC("wrong type"));
0530     PSObjectPtr val;
0531     if(_array(o)->Get(tointeger(idx), val)) {
0532         _array(o)->Remove(tointeger(idx));
0533         v->Push(val);
0534         return 1;
0535     }
0536     return ps_throwerror(v, _SC("idx out of range"));
0537 }
0538 
0539 static PSInteger array_resize(HPSCRIPTVM v)
0540 {
0541     PSObject &o = stack_get(v, 1);
0542     PSObject &nsize = stack_get(v, 2);
0543     PSObjectPtr fill;
0544     if(ps_isnumeric(nsize)) {
0545         if(ps_gettop(v) > 2)
0546             fill = stack_get(v, 3);
0547         _array(o)->Resize(tointeger(nsize),fill);
0548         return 0;
0549     }
0550     return ps_throwerror(v, _SC("size must be a number"));
0551 }
0552 
0553 static PSInteger __map_array(PSArray *dest,PSArray *src,HPSCRIPTVM v) {
0554     PSObjectPtr temp;
0555     PSInteger size = src->Size();
0556     for(PSInteger n = 0; n < size; n++) {
0557         src->Get(n,temp);
0558         v->Push(src);
0559         v->Push(temp);
0560         if(PS_FAILED(ps_call(v,2,PSTrue,PSFalse))) {
0561             return PS_ERROR;
0562         }
0563         dest->Set(n,v->GetUp(-1));
0564         v->Pop();
0565     }
0566     return 0;
0567 }
0568 
0569 static PSInteger array_map(HPSCRIPTVM v)
0570 {
0571     PSObject &o = stack_get(v,1);
0572     PSInteger size = _array(o)->Size();
0573     PSObjectPtr ret = PSArray::Create(_ss(v),size);
0574     if(PS_FAILED(__map_array(_array(ret),_array(o),v)))
0575         return PS_ERROR;
0576     v->Push(ret);
0577     return 1;
0578 }
0579 
0580 static PSInteger array_apply(HPSCRIPTVM v)
0581 {
0582     PSObject &o = stack_get(v,1);
0583     if(PS_FAILED(__map_array(_array(o),_array(o),v)))
0584         return PS_ERROR;
0585     return 0;
0586 }
0587 
0588 static PSInteger array_reduce(HPSCRIPTVM v)
0589 {
0590     PSObject &o = stack_get(v,1);
0591     PSArray *a = _array(o);
0592     PSInteger size = a->Size();
0593     if(size == 0) {
0594         return 0;
0595     }
0596     PSObjectPtr res;
0597     a->Get(0,res);
0598     if(size > 1) {
0599         PSObjectPtr other;
0600         for(PSInteger n = 1; n < size; n++) {
0601             a->Get(n,other);
0602             v->Push(o);
0603             v->Push(res);
0604             v->Push(other);
0605             if(PS_FAILED(ps_call(v,3,PSTrue,PSFalse))) {
0606                 return PS_ERROR;
0607             }
0608             res = v->GetUp(-1);
0609             v->Pop();
0610         }
0611     }
0612     v->Push(res);
0613     return 1;
0614 }
0615 
0616 static PSInteger array_filter(HPSCRIPTVM v)
0617 {
0618     PSObject &o = stack_get(v,1);
0619     PSArray *a = _array(o);
0620     PSObjectPtr ret = PSArray::Create(_ss(v),0);
0621     PSInteger size = a->Size();
0622     PSObjectPtr val;
0623     for(PSInteger n = 0; n < size; n++) {
0624         a->Get(n,val);
0625         v->Push(o);
0626         v->Push(n);
0627         v->Push(val);
0628         if(PS_FAILED(ps_call(v,3,PSTrue,PSFalse))) {
0629             return PS_ERROR;
0630         }
0631         if(!PSVM::IsFalse(v->GetUp(-1))) {
0632             _array(ret)->Append(val);
0633         }
0634         v->Pop();
0635     }
0636     v->Push(ret);
0637     return 1;
0638 }
0639 
0640 static PSInteger array_find(HPSCRIPTVM v)
0641 {
0642     PSObject &o = stack_get(v,1);
0643     PSObjectPtr &val = stack_get(v,2);
0644     PSArray *a = _array(o);
0645     PSInteger size = a->Size();
0646     PSObjectPtr temp;
0647     for(PSInteger n = 0; n < size; n++) {
0648         bool res = false;
0649         a->Get(n,temp);
0650         if(PSVM::IsEqual(temp,val,res) && res) {
0651             v->Push(n);
0652             return 1;
0653         }
0654     }
0655     return 0;
0656 }
0657 
0658 
0659 static bool _sort_compare(HPSCRIPTVM v,PSObjectPtr &a,PSObjectPtr &b,PSInteger func,PSInteger &ret)
0660 {
0661     if(func < 0) {
0662         if(!v->ObjCmp(a,b,ret)) return false;
0663     }
0664     else {
0665         PSInteger top = ps_gettop(v);
0666         ps_push(v, func);
0667         ps_pushroottable(v);
0668         v->Push(a);
0669         v->Push(b);
0670         if(PS_FAILED(ps_call(v, 3, PSTrue, PSFalse))) {
0671             if(!ps_isstring( v->_lasterror))
0672                 v->Raise_Error(_SC("compare func failed"));
0673             return false;
0674         }
0675         if(PS_FAILED(ps_getinteger(v, -1, &ret))) {
0676             v->Raise_Error(_SC("numeric value expected as return value of the compare function"));
0677             return false;
0678         }
0679         ps_settop(v, top);
0680         return true;
0681     }
0682     return true;
0683 }
0684 
0685 static bool _hsort_sift_down(HPSCRIPTVM v,PSArray *arr, PSInteger root, PSInteger bottom, PSInteger func)
0686 {
0687     PSInteger maxChild;
0688     PSInteger done = 0;
0689     PSInteger ret;
0690     PSInteger root2;
0691     while (((root2 = root * 2) <= bottom) && (!done))
0692     {
0693         if (root2 == bottom) {
0694             maxChild = root2;
0695         }
0696         else {
0697             if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
0698                 return false;
0699             if (ret > 0) {
0700                 maxChild = root2;
0701             }
0702             else {
0703                 maxChild = root2 + 1;
0704             }
0705         }
0706 
0707         if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
0708             return false;
0709         if (ret < 0) {
0710             if (root == maxChild) {
0711                 v->Raise_Error(_SC("inconsistent compare function"));
0712                 return false; // We'd be swapping ourselve. The compare function is incorrect

0713             }
0714 
0715             _Swap(arr->_values[root],arr->_values[maxChild]);
0716             root = maxChild;
0717         }
0718         else {
0719             done = 1;
0720         }
0721     }
0722     return true;
0723 }
0724 
0725 static bool _hsort(HPSCRIPTVM v,PSObjectPtr &arr, PSInteger PS_UNUSED_ARG(l), PSInteger PS_UNUSED_ARG(r),PSInteger func)
0726 {
0727     PSArray *a = _array(arr);
0728     PSInteger i;
0729     PSInteger array_size = a->Size();
0730     for (i = (array_size / 2); i >= 0; i--) {
0731         if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
0732     }
0733 
0734     for (i = array_size-1; i >= 1; i--)
0735     {
0736         _Swap(a->_values[0],a->_values[i]);
0737         if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
0738     }
0739     return true;
0740 }
0741 
0742 static PSInteger array_sort(HPSCRIPTVM v)
0743 {
0744     PSInteger func = -1;
0745     PSObjectPtr &o = stack_get(v,1);
0746     if(_array(o)->Size() > 1) {
0747         if(ps_gettop(v) == 2) func = 2;
0748         if(!_hsort(v, o, 0, _array(o)->Size()-1, func))
0749             return PS_ERROR;
0750 
0751     }
0752     return 0;
0753 }
0754 
0755 static PSInteger array_slice(HPSCRIPTVM v)
0756 {
0757     PSInteger sidx,eidx;
0758     PSObjectPtr o;
0759     if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
0760     PSInteger alen = _array(o)->Size();
0761     if(sidx < 0)sidx = alen + sidx;
0762     if(eidx < 0)eidx = alen + eidx;
0763     if(eidx < sidx)return ps_throwerror(v,_SC("wrong indexes"));
0764     if(eidx > alen || sidx < 0)return ps_throwerror(v, _SC("slice out of range"));
0765     PSArray *arr=PSArray::Create(_ss(v),eidx-sidx);
0766     PSObjectPtr t;
0767     PSInteger count=0;
0768     for(PSInteger i=sidx;i<eidx;i++){
0769         _array(o)->Get(i,t);
0770         arr->Set(count++,t);
0771     }
0772     v->Push(arr);
0773     return 1;
0774 
0775 }
0776 
0777 const PSRegFunction PSSharedState::_array_default_delegate_funcz[]={
0778     {_SC("len"),default_delegate_len,1, _SC("a")},
0779     {_SC("append"),array_append,2, _SC("a")},
0780     {_SC("extend"),array_extend,2, _SC("aa")},
0781     {_SC("push"),array_append,2, _SC("a")},
0782     {_SC("pop"),array_pop,1, _SC("a")},
0783     {_SC("top"),array_top,1, _SC("a")},
0784     {_SC("insert"),array_insert,3, _SC("an")},
0785     {_SC("remove"),array_remove,2, _SC("an")},
0786     {_SC("resize"),array_resize,-2, _SC("an")},
0787     {_SC("reverse"),array_reverse,1, _SC("a")},
0788     {_SC("sort"),array_sort,-1, _SC("ac")},
0789     {_SC("slice"),array_slice,-1, _SC("ann")},
0790     {_SC("weakref"),obj_delegate_weakref,1, NULL },
0791     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
0792     {_SC("clear"),obj_clear,1, _SC(".")},
0793     {_SC("map"),array_map,2, _SC("ac")},
0794     {_SC("apply"),array_apply,2, _SC("ac")},
0795     {_SC("reduce"),array_reduce,2, _SC("ac")},
0796     {_SC("filter"),array_filter,2, _SC("ac")},
0797     {_SC("find"),array_find,2, _SC("a.")},
0798     {NULL,(PSFUNCTION)0,0,NULL}
0799 };
0800 
0801 //STRING DEFAULT DELEGATE//////////////////////////

0802 static PSInteger string_slice(HPSCRIPTVM v)
0803 {
0804     PSInteger sidx,eidx;
0805     PSObjectPtr o;
0806     if(PS_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
0807     PSInteger slen = _string(o)->_len;
0808     if(sidx < 0)sidx = slen + sidx;
0809     if(eidx < 0)eidx = slen + eidx;
0810     if(eidx < sidx) return ps_throwerror(v,_SC("wrong indexes"));
0811     if(eidx > slen || sidx < 0) return ps_throwerror(v, _SC("slice out of range"));
0812     v->Push(PSString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
0813     return 1;
0814 }
0815 
0816 static PSInteger string_find(HPSCRIPTVM v)
0817 {
0818     PSInteger top,start_idx=0;
0819     const PSChar *str,*substr,*ret;
0820     if(((top=ps_gettop(v))>1) && PS_SUCCEEDED(ps_getstring(v,1,&str)) && PS_SUCCEEDED(ps_getstring(v,2,&substr))){
0821         if(top>2)ps_getinteger(v,3,&start_idx);
0822         if((ps_getsize(v,1)>start_idx) && (start_idx>=0)){
0823             ret=scstrstr(&str[start_idx],substr);
0824             if(ret){
0825                 ps_pushinteger(v,(PSInteger)(ret-str));
0826                 return 1;
0827             }
0828         }
0829         return 0;
0830     }
0831     return ps_throwerror(v,_SC("invalid param"));
0832 }
0833 
0834 #define STRING_TOFUNCZ(func) static PSInteger string_##func(HPSCRIPTVM v) \
0835 {\
0836     PSInteger sidx,eidx; \
0837     PSObjectPtr str; \
0838     if(PS_FAILED(get_slice_params(v,sidx,eidx,str)))return -1; \
0839     PSInteger slen = _string(str)->_len; \
0840     if(sidx < 0)sidx = slen + sidx; \
0841     if(eidx < 0)eidx = slen + eidx; \
0842     if(eidx < sidx) return ps_throwerror(v,_SC("wrong indexes")); \
0843     if(eidx > slen || sidx < 0) return ps_throwerror(v,_SC("slice out of range")); \
0844     PSInteger len=_string(str)->_len; \
0845     const PSChar *sthis=_stringval(str); \
0846     PSChar *snew=(_ss(v)->GetScratchPad(ps_rsl(len))); \
0847     memcpy(snew,sthis,ps_rsl(len));\
0848     for(PSInteger i=sidx;i<eidx;i++) snew[i] = func(sthis[i]); \
0849     v->Push(PSString::Create(_ss(v),snew,len)); \
0850     return 1; \
0851 }
0852 
0853 
0854 STRING_TOFUNCZ(tolower)
0855 STRING_TOFUNCZ(toupper)
0856 
0857 const PSRegFunction PSSharedState::_string_default_delegate_funcz[]={
0858     {_SC("len"),default_delegate_len,1, _SC("s")},
0859     {_SC("tointeger"),default_delegate_tointeger,-1, _SC("sn")},
0860     {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},
0861     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
0862     {_SC("slice"),string_slice,-1, _SC("s n  n")},
0863     {_SC("find"),string_find,-2, _SC("s s n")},
0864     {_SC("tolower"),string_tolower,-1, _SC("s n n")},
0865     {_SC("toupper"),string_toupper,-1, _SC("s n n")},
0866     {_SC("weakref"),obj_delegate_weakref,1, NULL },
0867     {NULL,(PSFUNCTION)0,0,NULL}
0868 };
0869 
0870 //INTEGER DEFAULT DELEGATE//////////////////////////

0871 const PSRegFunction PSSharedState::_number_default_delegate_funcz[]={
0872     {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
0873     {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
0874     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
0875     {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
0876     {_SC("weakref"),obj_delegate_weakref,1, NULL },
0877     {NULL,(PSFUNCTION)0,0,NULL}
0878 };
0879 
0880 //CLOSURE DEFAULT DELEGATE//////////////////////////

0881 static PSInteger closure_pcall(HPSCRIPTVM v)
0882 {
0883     return PS_SUCCEEDED(ps_call(v,ps_gettop(v)-1,PSTrue,PSFalse))?1:PS_ERROR;
0884 }
0885 
0886 static PSInteger closure_call(HPSCRIPTVM v)
0887 {
0888     return PS_SUCCEEDED(ps_call(v,ps_gettop(v)-1,PSTrue,PSTrue))?1:PS_ERROR;
0889 }
0890 
0891 static PSInteger _closure_acall(HPSCRIPTVM v,PSBool raiseerror)
0892 {
0893     PSArray *aparams=_array(stack_get(v,2));
0894     PSInteger nparams=aparams->Size();
0895     v->Push(stack_get(v,1));
0896     for(PSInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
0897     return PS_SUCCEEDED(ps_call(v,nparams,PSTrue,raiseerror))?1:PS_ERROR;
0898 }
0899 
0900 static PSInteger closure_acall(HPSCRIPTVM v)
0901 {
0902     return _closure_acall(v,PSTrue);
0903 }
0904 
0905 static PSInteger closure_pacall(HPSCRIPTVM v)
0906 {
0907     return _closure_acall(v,PSFalse);
0908 }
0909 
0910 static PSInteger closure_bindenv(HPSCRIPTVM v)
0911 {
0912     if(PS_FAILED(ps_bindenv(v,1)))
0913         return PS_ERROR;
0914     return 1;
0915 }
0916 
0917 static PSInteger closure_getroot(HPSCRIPTVM v)
0918 {
0919     if(PS_FAILED(ps_getclosureroot(v,-1)))
0920         return PS_ERROR;
0921     return 1;
0922 }
0923 
0924 static PSInteger closure_setroot(HPSCRIPTVM v)
0925 {
0926     if(PS_FAILED(ps_setclosureroot(v,-2)))
0927         return PS_ERROR;
0928     return 1;
0929 }
0930 
0931 static PSInteger closure_getinfos(HPSCRIPTVM v) {
0932     PSObject o = stack_get(v,1);
0933     PSTable *res = PSTable::Create(_ss(v),4);
0934     if(type(o) == OT_CLOSURE) {
0935         PSFunctionProto *f = _closure(o)->_function;
0936         PSInteger nparams = f->_nparameters + (f->_varparams?1:0);
0937         PSObjectPtr params = PSArray::Create(_ss(v),nparams);
0938     PSObjectPtr defparams = PSArray::Create(_ss(v),f->_ndefaultparams);
0939         for(PSInteger n = 0; n<f->_nparameters; n++) {
0940             _array(params)->Set((PSInteger)n,f->_parameters[n]);
0941         }
0942     for(PSInteger j = 0; j<f->_ndefaultparams; j++) {
0943             _array(defparams)->Set((PSInteger)j,_closure(o)->_defaultparams[j]);
0944         }
0945         if(f->_varparams) {
0946             _array(params)->Set(nparams-1,PSString::Create(_ss(v),_SC("..."),-1));
0947         }
0948         res->NewSlot(PSString::Create(_ss(v),_SC("native"),-1),false);
0949         res->NewSlot(PSString::Create(_ss(v),_SC("name"),-1),f->_name);
0950         res->NewSlot(PSString::Create(_ss(v),_SC("src"),-1),f->_sourcename);
0951         res->NewSlot(PSString::Create(_ss(v),_SC("parameters"),-1),params);
0952         res->NewSlot(PSString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);
0953     res->NewSlot(PSString::Create(_ss(v),_SC("defparams"),-1),defparams);
0954     }
0955     else { //OT_NATIVECLOSURE

0956         PSNativeClosure *nc = _nativeclosure(o);
0957         res->NewSlot(PSString::Create(_ss(v),_SC("native"),-1),true);
0958         res->NewSlot(PSString::Create(_ss(v),_SC("name"),-1),nc->_name);
0959         res->NewSlot(PSString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
0960         PSObjectPtr typecheck;
0961         if(nc->_typecheck.size() > 0) {
0962             typecheck =
0963                 PSArray::Create(_ss(v), nc->_typecheck.size());
0964             for(PSUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
0965                     _array(typecheck)->Set((PSInteger)n,nc->_typecheck[n]);
0966             }
0967         }
0968         res->NewSlot(PSString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
0969     }
0970     v->Push(res);
0971     return 1;
0972 }
0973 
0974 
0975 
0976 const PSRegFunction PSSharedState::_closure_default_delegate_funcz[]={
0977     {_SC("call"),closure_call,-1, _SC("c")},
0978     {_SC("pcall"),closure_pcall,-1, _SC("c")},
0979     {_SC("acall"),closure_acall,2, _SC("ca")},
0980     {_SC("pacall"),closure_pacall,2, _SC("ca")},
0981     {_SC("weakref"),obj_delegate_weakref,1, NULL },
0982     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
0983     {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
0984     {_SC("getinfos"),closure_getinfos,1, _SC("c")},
0985     {_SC("getroot"),closure_getroot,1, _SC("c")},
0986     {_SC("setroot"),closure_setroot,2, _SC("ct")},
0987     {NULL,(PSFUNCTION)0,0,NULL}
0988 };
0989 
0990 //GENERATOR DEFAULT DELEGATE

0991 static PSInteger generator_getstatus(HPSCRIPTVM v)
0992 {
0993     PSObject &o=stack_get(v,1);
0994     switch(_generator(o)->_state){
0995         case PSGenerator::eSuspended:v->Push(PSString::Create(_ss(v),_SC("suspended")));break;
0996         case PSGenerator::eRunning:v->Push(PSString::Create(_ss(v),_SC("running")));break;
0997         case PSGenerator::eDead:v->Push(PSString::Create(_ss(v),_SC("dead")));break;
0998     }
0999     return 1;
1000 }
1001 
1002 const PSRegFunction PSSharedState::_generator_default_delegate_funcz[]={
1003     {_SC("getstatus"),generator_getstatus,1, _SC("g")},
1004     {_SC("weakref"),obj_delegate_weakref,1, NULL },
1005     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
1006     {NULL,(PSFUNCTION)0,0,NULL}
1007 };
1008 
1009 //THREAD DEFAULT DELEGATE

1010 static PSInteger thread_call(HPSCRIPTVM v)
1011 {
1012     PSObjectPtr o = stack_get(v,1);
1013     if(type(o) == OT_THREAD) {
1014         PSInteger nparams = ps_gettop(v);
1015         _thread(o)->Push(_thread(o)->_roottable);
1016         for(PSInteger i = 2; i<(nparams+1); i++)
1017             ps_move(_thread(o),v,i);
1018         if(PS_SUCCEEDED(ps_call(_thread(o),nparams,PSTrue,PSTrue))) {
1019             ps_move(v,_thread(o),-1);
1020             ps_pop(_thread(o),1);
1021             return 1;
1022         }
1023         v->_lasterror = _thread(o)->_lasterror;
1024         return PS_ERROR;
1025     }
1026     return ps_throwerror(v,_SC("wrong parameter"));
1027 }
1028 
1029 static PSInteger thread_wakeup(HPSCRIPTVM v)
1030 {
1031     PSObjectPtr o = stack_get(v,1);
1032     if(type(o) == OT_THREAD) {
1033         PSVM *thread = _thread(o);
1034         PSInteger state = ps_getvmstate(thread);
1035         if(state != PS_VMSTATE_SUSPENDED) {
1036             switch(state) {
1037                 case PS_VMSTATE_IDLE:
1038                     return ps_throwerror(v,_SC("cannot wakeup a idle thread"));
1039                 break;
1040                 case PS_VMSTATE_RUNNING:
1041                     return ps_throwerror(v,_SC("cannot wakeup a running thread"));
1042                 break;
1043             }
1044         }
1045 
1046         PSInteger wakeupret = ps_gettop(v)>1?PSTrue:PSFalse;
1047         if(wakeupret) {
1048             ps_move(thread,v,2);
1049         }
1050         if(PS_SUCCEEDED(ps_wakeupvm(thread,wakeupret,PSTrue,PSTrue,PSFalse))) {
1051             ps_move(v,thread,-1);
1052             ps_pop(thread,1); //pop retval

1053             if(ps_getvmstate(thread) == PS_VMSTATE_IDLE) {
1054                 ps_settop(thread,1); //pop roottable

1055             }
1056             return 1;
1057         }
1058         ps_settop(thread,1);
1059         v->_lasterror = thread->_lasterror;
1060         return PS_ERROR;
1061     }
1062     return ps_throwerror(v,_SC("wrong parameter"));
1063 }
1064 
1065 static PSInteger thread_wakeupthrow(HPSCRIPTVM v)
1066 {
1067     PSObjectPtr o = stack_get(v,1);
1068     if(type(o) == OT_THREAD) {
1069         PSVM *thread = _thread(o);
1070         PSInteger state = ps_getvmstate(thread);
1071         if(state != PS_VMSTATE_SUSPENDED) {
1072             switch(state) {
1073                 case PS_VMSTATE_IDLE:
1074                     return ps_throwerror(v,_SC("cannot wakeup a idle thread"));
1075                 break;
1076                 case PS_VMSTATE_RUNNING:
1077                     return ps_throwerror(v,_SC("cannot wakeup a running thread"));
1078                 break;
1079             }
1080         }
1081 
1082         ps_move(thread,v,2);
1083         ps_throwobject(thread);
1084         PSBool rethrow_error = PSTrue;
1085         if(ps_gettop(v) > 2) {
1086             ps_getbool(v,3,&rethrow_error);
1087         }
1088         if(PS_SUCCEEDED(ps_wakeupvm(thread,PSFalse,PSTrue,PSTrue,PSTrue))) {
1089             ps_move(v,thread,-1);
1090             ps_pop(thread,1); //pop retval

1091             if(ps_getvmstate(thread) == PS_VMSTATE_IDLE) {
1092                 ps_settop(thread,1); //pop roottable

1093             }
1094             return 1;
1095         }
1096         ps_settop(thread,1);
1097         if(rethrow_error) {
1098             v->_lasterror = thread->_lasterror;
1099             return PS_ERROR;
1100         }
1101         return PS_OK;
1102     }
1103     return ps_throwerror(v,_SC("wrong parameter"));
1104 }
1105 
1106 static PSInteger thread_getstatus(HPSCRIPTVM v)
1107 {
1108     PSObjectPtr &o = stack_get(v,1);
1109     switch(ps_getvmstate(_thread(o))) {
1110         case PS_VMSTATE_IDLE:
1111             ps_pushstring(v,_SC("idle"),-1);
1112         break;
1113         case PS_VMSTATE_RUNNING:
1114             ps_pushstring(v,_SC("running"),-1);
1115         break;
1116         case PS_VMSTATE_SUSPENDED:
1117             ps_pushstring(v,_SC("suspended"),-1);
1118         break;
1119         default:
1120             return ps_throwerror(v,_SC("internal VM error"));
1121     }
1122     return 1;
1123 }
1124 
1125 static PSInteger thread_getstackinfos(HPSCRIPTVM v)
1126 {
1127     PSObjectPtr o = stack_get(v,1);
1128     if(type(o) == OT_THREAD) {
1129         PSVM *thread = _thread(o);
1130         PSInteger threadtop = ps_gettop(thread);
1131         PSInteger level;
1132         ps_getinteger(v,-1,&level);
1133         PSRESULT res = __getcallstackinfos(thread,level);
1134         if(PS_FAILED(res))
1135         {
1136             ps_settop(thread,threadtop);
1137             if(type(thread->_lasterror) == OT_STRING) {
1138                 ps_throwerror(v,_stringval(thread->_lasterror));
1139             }
1140             else {
1141                 ps_throwerror(v,_SC("unknown error"));
1142             }
1143         }
1144         if(res > 0) {
1145             //some result

1146             ps_move(v,thread,-1);
1147             ps_settop(thread,threadtop);
1148             return 1;
1149         }
1150         //no result

1151         ps_settop(thread,threadtop);
1152         return 0;
1153 
1154     }
1155     return ps_throwerror(v,_SC("wrong parameter"));
1156 }
1157 
1158 const PSRegFunction PSSharedState::_thread_default_delegate_funcz[] = {
1159     {_SC("call"), thread_call, -1, _SC("v")},
1160     {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
1161     {_SC("wakeupthrow"), thread_wakeupthrow, -2, _SC("v.b")},
1162     {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
1163     {_SC("weakref"),obj_delegate_weakref,1, NULL },
1164     {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},
1165     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
1166     {NULL,(PSFUNCTION)0,0,NULL}
1167 };
1168 
1169 static PSInteger class_getattributes(HPSCRIPTVM v)
1170 {
1171     return PS_SUCCEEDED(ps_getattributes(v,-2))?1:PS_ERROR;
1172 }
1173 
1174 static PSInteger class_setattributes(HPSCRIPTVM v)
1175 {
1176     return PS_SUCCEEDED(ps_setattributes(v,-3))?1:PS_ERROR;
1177 }
1178 
1179 static PSInteger class_instance(HPSCRIPTVM v)
1180 {
1181     return PS_SUCCEEDED(ps_createinstance(v,-1))?1:PS_ERROR;
1182 }
1183 
1184 static PSInteger class_getbase(HPSCRIPTVM v)
1185 {
1186     return PS_SUCCEEDED(ps_getbase(v,-1))?1:PS_ERROR;
1187 }
1188 
1189 static PSInteger class_newmember(HPSCRIPTVM v)
1190 {
1191     PSInteger top = ps_gettop(v);
1192     PSBool bstatic = PSFalse;
1193     if(top == 5)
1194     {
1195         ps_tobool(v,-1,&bstatic);
1196         ps_pop(v,1);
1197     }
1198 
1199     if(top < 4) {
1200         ps_pushnull(v);
1201     }
1202     return PS_SUCCEEDED(ps_newmember(v,-4,bstatic))?1:PS_ERROR;
1203 }
1204 
1205 static PSInteger class_rawnewmember(HPSCRIPTVM v)
1206 {
1207     PSInteger top = ps_gettop(v);
1208     PSBool bstatic = PSFalse;
1209     if(top == 5)
1210     {
1211         ps_tobool(v,-1,&bstatic);
1212         ps_pop(v,1);
1213     }
1214 
1215     if(top < 4) {
1216         ps_pushnull(v);
1217     }
1218     return PS_SUCCEEDED(ps_rawnewmember(v,-4,bstatic))?1:PS_ERROR;
1219 }
1220 
1221 const PSRegFunction PSSharedState::_class_default_delegate_funcz[] = {
1222     {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
1223     {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
1224     {_SC("rawget"),container_rawget,2, _SC("y")},
1225     {_SC("rawset"),container_rawset,3, _SC("y")},
1226     {_SC("rawin"),container_rawexists,2, _SC("y")},
1227     {_SC("weakref"),obj_delegate_weakref,1, NULL },
1228     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
1229     {_SC("instance"),class_instance,1, _SC("y")},
1230     {_SC("getbase"),class_getbase,1, _SC("y")},
1231     {_SC("newmember"),class_newmember,-3, _SC("y")},
1232     {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},
1233     {NULL,(PSFUNCTION)0,0,NULL}
1234 };
1235 
1236 
1237 static PSInteger instance_getclass(HPSCRIPTVM v)
1238 {
1239     if(PS_SUCCEEDED(ps_getclass(v,1)))
1240         return 1;
1241     return PS_ERROR;
1242 }
1243 
1244 const PSRegFunction PSSharedState::_instance_default_delegate_funcz[] = {
1245     {_SC("getclass"), instance_getclass, 1, _SC("x")},
1246     {_SC("rawget"),container_rawget,2, _SC("x")},
1247     {_SC("rawset"),container_rawset,3, _SC("x")},
1248     {_SC("rawin"),container_rawexists,2, _SC("x")},
1249     {_SC("weakref"),obj_delegate_weakref,1, NULL },
1250     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
1251     {NULL,(PSFUNCTION)0,0,NULL}
1252 };
1253 
1254 static PSInteger weakref_ref(HPSCRIPTVM v)
1255 {
1256     if(PS_FAILED(ps_getweakrefval(v,1)))
1257         return PS_ERROR;
1258     return 1;
1259 }
1260 
1261 const PSRegFunction PSSharedState::_weakref_default_delegate_funcz[] = {
1262     {_SC("ref"),weakref_ref,1, _SC("r")},
1263     {_SC("weakref"),obj_delegate_weakref,1, NULL },
1264     {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
1265     {NULL,(PSFUNCTION)0,0,NULL}
1266 };