moved back to old acc
[vox.git] / src / core / vm.cpp
blobcdaf4e1a8049a867b08530b86c56221f58b38038
2 #include <math.h>
3 #include <stdlib.h>
5 #include "pcheader.hpp"
6 #include "opcodes.hpp"
7 #include "vm.hpp"
8 #include "funcproto.hpp"
9 #include "closure.hpp"
10 #include "string.hpp"
11 #include "table.hpp"
12 #include "userdata.hpp"
13 #include "class.hpp"
14 #include "names.hpp"
15 #include "compiler.hpp"
16 #include "debug.hpp"
18 #define TOP() (_stack.values()[_top-1])
20 #define arg0 (_i_._arg0)
21 #define sarg0 ((VXInteger)*((signed char *)&_i_._arg0))
22 #define arg1 (_i_._arg1)
23 #define sarg1 (*((VXInteger*)&_i_._arg1))
24 #define arg2 (_i_._arg2)
25 #define arg3 (_i_._arg3)
26 #define sarg3 ((VXInteger)*((signed char *)&_i_._arg3))
28 #define _ARITH_(op,trg,o1,o2) \
29 { \
30 VXInteger tmask = type(o1)|type(o2); \
31 switch(tmask) \
32 { \
33 case VX_OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
34 case (VX_OT_FLOAT|VX_OT_INTEGER): \
35 case (VX_OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
36 default: _GUARD(ARITH_OP(this, (#op)[0],trg,o1,o2)); break;\
37 } \
40 #define _ARITH_NOZERO(op,trg,o1,o2,err) \
41 { \
42 VXInteger tmask = type(o1)|type(o2); \
43 switch(tmask) { \
44 case VX_OT_INTEGER: \
45 { \
46 VXInteger i2 = _integer(o2); \
47 if(i2 == 0) \
48 { \
49 ThrowError(err); \
50 VX_THROW(); \
51 } \
52 trg = _integer(o1) op i2; \
53 } \
54 break;\
55 case (VX_OT_FLOAT|VX_OT_INTEGER): \
56 case (VX_OT_FLOAT): \
57 trg = tofloat(o1) op tofloat(o2); \
58 break;\
59 default: \
60 _GUARD(ARITH_OP(this, (#op)[0],trg,o1,o2)); \
61 break;\
62 } \
65 #define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
67 #define VX_THROW() { goto exception_trap; }
69 #define _GUARD(exp) { if(!exp) { VX_THROW();} }
71 #define _RET_SUCCEED(exp) { result = (exp); return true; }
73 #define FALLBACK_OK 0
74 #define FALLBACK_NO_MATCH 1
75 #define FALLBACK_ERROR 2
79 #undef _GETSAFE_OBJ
81 #define _GETSAFE_OBJ(v,idx,type,o) \
82 { \
83 if(VX_FAILED(v->GetTypedArg(v,idx,type,&o))) \
84 { \
85 return VX_ERROR; \
86 } \
90 #define _GETSAFE_OBJ_REF(v, idx, type, o) \
91 { \
92 if(VX_FAILED(v->GetTypedArg(idx, type, o))) \
93 { \
94 return VX_ERROR; \
95 } \
98 void vox_defaultprintfunc(VXState* v,const char *s,...)
100 (void)v;
101 va_list vl;
102 va_start(vl, s);
103 vfprintf(stdout, s, vl);
104 va_end(vl);
107 void vox_defaulterrorfunc(VXState* v,const char *s,...)
109 (void)v;
110 va_list vl;
111 va_start(vl, s);
112 vfprintf(stderr, s, vl);
113 va_end(vl);
118 template<typename Type, typename ClosureType>
119 Type WrongNumberOfArguments(VXState* vm,
120 Type retval,
121 bool isnative,
122 ClosureType func)
124 const char* funcname = _stringval(func->_name);
125 const char* prefix = isnative ? " native" : "";
126 if(func->_name.IsNull())
128 funcname = NAMES_ANONFUNC;
130 vm->ThrowError("wrong number of parameters to%s function '%s'", prefix, funcname);
131 return retval;
134 VXUnsignedInteger TranslateIndex(const VXObject &idx)
136 switch(type(idx))
138 case VX_OT_NULL:
139 return 0;
140 case VX_OT_INTEGER:
141 return (VXUnsignedInteger)_integer(idx);
142 default: vox_assert(0); break;
144 return 0;
147 const char *IdType2Name(VXOType type)
149 switch(VX_RAW_TYPE(type))
151 case VX_RT_NULL: return "null";
152 case VX_RT_INTEGER: return "integer";
153 case VX_RT_FLOAT: return "float";
154 case VX_RT_BOOL: return "bool";
155 case VX_RT_STRING: return "string";
156 case VX_RT_TABLE: return "table";
157 case VX_RT_ARRAY: return "array";
158 case VX_RT_GENERATOR: return "generator";
159 case VX_RT_CLOSURE:
160 case VX_RT_NATIVECLOSURE: return "function";
161 case VX_RT_USERDATA:
162 case VX_RT_USERPOINTER: return "userdata";
163 case VX_RT_THREAD: return "thread";
164 case VX_RT_FUNCPROTO: return "function";
165 case VX_RT_CLASS: return "class";
166 case VX_RT_INSTANCE: return "instance";
167 case VX_RT_WEAKREF: return "weakref";
168 case VX_RT_OUTER: return "outer";
169 default:
170 return "<unknown>";
174 const char *GetTypeName(const VXObject &obj1)
176 return IdType2Name(type(obj1));
180 VXInteger VXState::GetState()
182 if(this->_suspended)
184 return VX_VMSTATE_SUSPENDED;
186 if(this->_callsstacksize != 0)
188 return VX_VMSTATE_RUNNING;
190 return VX_VMSTATE_IDLE;
193 VXInteger VXState::WakeUp(bool wakeupret,bool retval,bool raiseerror,bool throwerror)
195 VXObject ret;
196 if(!this->_suspended)
198 return this->ThrowError("cannot resume a vm that is not running any code");
200 VXInteger target = this->_suspended_target;
201 if(wakeupret)
203 if(target != -1)
205 //retval
206 this->GetAt(this->_stackbase + this->_suspended_target) = this->GetUp(-1);
208 this->Pop();
210 else if(target != -1)
212 this->GetAt(this->_stackbase + this->_suspended_target).Null();
214 VXObject dummy;
215 VXState::ExecutionType extype;
216 extype = throwerror ? VXState::ET_RESUME_THROW_VM : VXState::ET_RESUME_VM;
217 if(!this->Execute(dummy, -1, -1, ret, raiseerror, extype))
219 return VX_ERROR;
221 if(retval)
223 this->Push(ret);
225 return VX_OK;
228 VXInteger VXState::SetDelegate(VXObject& self, const VXObject& mt)
230 VXOType type = self.Type();
231 switch(type)
233 case VX_OT_TABLE:
234 if(mt.Type() == VX_OT_TABLE)
236 if(!self.Table()->SetDelegate(_table(mt)))
238 return ThrowError("delegate cycle");
241 else if(mt.Type() == VX_OT_NULL)
243 self.Table()->SetDelegate(NULL);
245 else
247 return vox_aux_invalidtype(this, type);
249 break;
250 case VX_OT_USERDATA:
251 if(mt.Type() == VX_OT_TABLE)
253 _userdata(self)->SetDelegate(_table(mt));
255 else if(type(mt)==VX_OT_NULL)
257 _userdata(self)->SetDelegate(NULL);
259 else return vox_aux_invalidtype(this, type);
260 break;
261 default:
262 return vox_aux_invalidtype(this, type);
263 break;
265 return VX_OK;
268 bool SafeWrite(VXState* v,
269 VXWriteFunc write,
270 VXUserPointer up,
271 VXUserPointer dest,
272 VXInteger size)
274 if(write(up,dest,size) != size)
276 v->ThrowError("io error (write function failure)");
277 return false;
279 return true;
282 bool SafeRead(VXState* v,VXWriteFunc read,VXUserPointer up,VXUserPointer dest,VXInteger size)
284 if(size && read(up,dest,size) != size)
286 v->ThrowError("io error, read function failure, the origin stream could be corrupted/trucated");
287 return false;
289 return true;
292 bool WriteTag(VXState* v,VXWriteFunc write,VXUserPointer up,VXUnsignedInteger32 tag)
294 return SafeWrite(v,write,up,&tag,sizeof(tag));
297 bool CheckTag(VXState* v,VXWriteFunc read,VXUserPointer up,VXUnsignedInteger32 tag)
299 VXUnsignedInteger32 t;
300 _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
301 if(t != tag)
303 v->ThrowError("invalid or corrupted closure stream");
304 return false;
306 return true;
309 bool WriteObject(VXState* v,VXUserPointer up,VXWriteFunc write,VXObject &o)
311 VXUnsignedInteger32 _type = (VXUnsignedInteger32)type(o);
312 _CHECK_IO(SafeWrite(v, write, up, &_type,sizeof(_type)));
313 switch(type(o))
315 case VX_OT_STRING:
316 _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(VXInteger)));
317 _CHECK_IO(SafeWrite(v,
318 write, up,
319 VXUserPointer(o.String()->Value()), o.String()->Length()));
320 break;
321 case VX_OT_INTEGER:
322 _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(VXInteger)));break;
323 case VX_OT_FLOAT:
324 _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(VXFloat)));break;
325 case VX_OT_NULL:
326 break;
327 default:
328 v->ThrowError("cannot serialize a %s",GetTypeName(o));
329 return false;
331 return true;
334 bool ReadObject(VXState* v,VXUserPointer up,VXReadFunc read,VXObject &o)
336 VXUnsignedInteger32 _type;
337 _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
338 VXOType t = (VXOType)_type;
339 switch(t)
341 case VX_OT_STRING:
343 VXInteger len;
344 _CHECK_IO(SafeRead(v,read,up,&len,sizeof(VXInteger)));
345 _CHECK_IO(SafeRead(v,read,up,v->ScratchPad(len),len));
346 o = v->NewString(v->ScratchPad(-1), len);
348 break;
349 case VX_OT_INTEGER:
351 VXInteger i;
352 _CHECK_IO(SafeRead(v,read,up,&i,sizeof(VXInteger))); o = i; break;
354 case VX_OT_FLOAT:
356 VXFloat f;
357 _CHECK_IO(SafeRead(v,read,up,&f,sizeof(VXFloat))); o = f; break;
359 case VX_OT_NULL:
360 o.Null();
361 break;
362 default:
363 v->ThrowError("cannot serialize a %s",IdType2Name(t));
364 return false;
366 return true;
371 char* VXState::ScratchPad(VXInteger size)
373 return Shared()->GetScratchPad(size);
376 void VXState::SetReleaseHook(VXInteger idx, VXReleaseHook hook)
378 if(GetTop() >= 1)
380 VXObject& ud = StackGet(idx);
381 switch(type(ud))
383 case VX_OT_USERDATA:
384 _userdata(ud)->_hook = hook;
385 break;
386 case VX_OT_INSTANCE:
387 _instance(ud)->_hook = hook;
388 break;
389 case VX_OT_CLASS:
390 _class(ud)->_hook = hook;
391 break;
392 default:
393 break;
398 VXInteger VXState::SetTypeTag(VXObject& o, VXUserPointer typetag)
400 switch(o.Type())
402 case VX_OT_USERDATA:
403 _userdata(o)->_typetag = typetag;
404 break;
405 case VX_OT_CLASS:
406 _class(o)->_typetag = typetag;
407 break;
408 default:
409 return ThrowError("invalid object type");
411 return VX_OK;
414 VXInteger VXState::GetInstanceUp(VXInteger idx, VXUserPointer *p,
415 VXUserPointer typetag,
416 bool previously_checked_base)
418 (void)previously_checked_base;
419 VXObject& o = StackGet(idx);
420 if(o.Type() != VX_OT_INSTANCE)
422 return ThrowError("the object is not a class instance");
424 (*p) = _instance(o)->_userpointer;
425 if(typetag != 0)
427 VXClassObj *cl = _instance(o)->_class;
430 if(cl->_typetag == typetag)
432 return VX_OK;
434 cl = cl->_base;
435 } while(cl != NULL);
436 return this->ThrowError("invalid type tag");
438 return VX_OK;
442 VXInteger VXState::SetInstanceUp(VXInteger idx, VXUserPointer* p)
444 VXObject& o = StackGet(idx);
445 if(type(o) != VX_OT_INSTANCE)
447 return ThrowError("the object is not a class instance");
449 _instance(o)->_userpointer = (*p);
450 Push(o);
451 return VX_OK;
455 void VXState::PushString(const char* str, VXInteger len)
457 this->Push(this->NewString(str, len));
460 void VXState::PushInteger(VXInteger itm)
462 this->Push(VXObject(itm));
465 void VXState::PushFloat(VXFloat itm)
467 this->Push(VXObject(itm));
470 void VXState::SetTop(VXInteger newtop)
472 VXInteger top = this->GetTop();
473 if(top > newtop)
475 this->Pop(top - newtop);
477 else
479 while(top++ < newtop)
481 this->PushNull();
486 VXInteger VXState::GetTop()
488 return ((this->_top) - (this->_stackbase));
491 VXInteger VXState::WriteClosure(VXWriteFunc w, VXUserPointer up)
493 VXObject o;
494 _GETSAFE_OBJ_REF(this, -1, VX_OT_CLOSURE,o);
495 unsigned short tag = VX_BYTECODE_STREAM_TAG;
496 if(w(up, &tag, 2) != 2)
498 return this->ThrowError("io error");
500 if(!_closure(o)->Save(this, up, w))
502 return VX_ERROR;
504 return VX_OK;
508 VXInteger VXState::WriteClosureToFile(const char *filename)
510 FILE* file = fopen(filename, "wb+");
511 if(!file)
513 return ThrowError("Cannot open '%s' for writing: %s", filename, strerror(errno));
515 else
517 if(VX_SUCCEEDED(this->WriteClosure(file_write, file)))
519 fclose(file);
520 return VX_OK;
522 fclose(file);
524 return VX_ERROR; //forward the error
527 VXInteger VXState::BindEnv(VXObject& o, const VXObject& env, VXObject& ret)
529 VXWeakRefObj* weak;
530 VXForeignClosureObj* fclos;
531 VXNativeClosureObj* nclos;
532 if(!o.IsNativeClosure() && !o.IsClosure())
534 return this->ThrowError("the target is not a closure");
536 if(!env.IsTable() && !env.IsClass() && !env.IsInstance())
538 return this->ThrowError("invalid environment");
540 weak = env.RefCounted()->GetWeakRef(env.Type());
541 if(o.IsClosure())
543 fclos = o.Closure()->Clone();
544 __ObjRelease(fclos->_env);
545 fclos->_env = weak;
546 __ObjAddRef(fclos->_env);
547 if(_closure(o)->_base)
549 fclos->_base = o.Closure()->_base;
550 __ObjAddRef(fclos->_base);
552 ret = fclos;
554 else //then must be a native closure
556 nclos = o.NativeClosure()->Clone();
557 __ObjRelease(nclos->_env);
558 nclos->_env = weak;
559 __ObjAddRef(nclos->_env);
560 ret = nclos;
562 return VX_OK;
565 void VXState::SetCompilerErrorHandler(VXCompileError f)
567 Shared()->_compilererrorhandler = f;
570 void VXState::SetDebugHook(const VXObject& o)
572 if(o.IsClosure() || o.IsNativeClosure() || o.IsNull())
574 this->_debughook_closure = o;
575 this->_debughook_native = NULL;
576 this->_debughook = !o.IsNull();
580 void VXState::SetErrorHandler(const VXObject& o)
582 if(o.IsClosure() || o.IsNativeClosure() || o.IsNull())
584 this->_errorhandler = o;
589 void VXState::SetErrorHandlers()
591 this->SetCompilerErrorHandler(vox_aux_compiler_error);
592 VXObject fn = VXNativeClosureObj::Create(this->Shared(), vox_aux_printerror, 0);
593 if(fn.IsClosure() || fn.IsNativeClosure() || fn.IsNull())
595 this->_errorhandler = fn;
599 void VXState::EnableDebugInfo(bool enable)
601 _ss(this)->_debuginfo = enable;
604 void VXState::PushRoot()
606 this->Push(this->_roottable);
609 void VXState::PopRoot()
611 this->Pop(1);
614 VXInteger VXState::GetUserPointer(VXInteger idx, VXUserPointer *p)
616 VXObject o;
617 _GETSAFE_OBJ_REF(this, idx, VX_OT_USERPOINTER, o);
618 (*p) = _userpointerval(o);
619 return VX_OK;
622 VXInteger VXState::GetString(VXInteger idx, const char** destination, VXInteger* len_dest)
624 VXObject objptr;
625 _GETSAFE_OBJ_REF(this, idx, VX_OT_STRING, objptr);
626 *destination = _stringval(objptr);
627 if(len_dest != NULL)
629 *len_dest = _stringlen(objptr);
631 return VX_OK;
634 VXInteger VXState::GetInteger(VXInteger idx, VXInteger* dest)
636 VXObject& o = this->StackGet(idx);
637 if(o.IsNumeric())
639 *dest = o.Integer();
640 return VX_OK;
642 return VX_ERROR;
646 VXInteger VXState::GetFloat(VXInteger idx, VXFloat* dest)
648 VXObject& o = this->StackGet(idx);
649 if(o.IsNumeric())
651 *dest = o.Float();
652 return VX_OK;
654 return VX_ERROR;
657 VXInteger VXState::GetBool(VXInteger idx, bool* dest)
659 VXObject& o = this->StackGet(idx);
660 if(o.IsBool())
662 *dest = o.Integer();
663 return VX_OK;
665 return VX_ERROR;
668 VXInteger VXState::GetClosure(VXInteger idx, VXFuncProtoObj** fnproto)
670 VXRawObj o = this->StackGet(idx);
671 if(type(o) == VX_OT_CLOSURE)
673 (*fnproto) = _closure(o)->_function;
674 return VX_OK;
676 return VX_ERROR;
679 VXInteger VXState::GetTypedArg(VXInteger idx, VXOType expected_type, VXObject& dest)
681 dest = this->StackGet(idx);
682 if(type(dest) != expected_type)
684 VXObject oval = this->PrintObjVal(dest);
685 this->ThrowError(
686 "wrong argument type, expected '%s' got '%.50s'",
687 IdType2Name(expected_type),
688 _stringval(oval));
689 return VX_ERROR;
691 return VX_OK;
694 bool VXState::CollectGarbage()
696 return this->Shared()->CollectGarbage(this);
699 bool VXState::ResurrectUnreachable()
701 return this->Shared()->ResurrectUnreachable(this);
704 void VXState::AtExit(const VXObject& ob)//(VXFuncProtoObj* fn)
706 //VXForeignClosureObj* clos = VXForeignClosureObj::Create(Shared(), fn);
707 //VXObject pt(clos);
708 //this->_atexit_functions.push_back(pt);
709 //VXObject pt;
710 //VXInteger type = ob.Type();
711 //if(type == VX_RT_NATIVECLOSURE)
713 // pt = VXNativeClosureObj::Create(Shared(), ob.NativeClosure());
715 //pt = ob;
716 this->_atexit_functions.push_back(ob);
719 void VXState::Move(VXState* destination, VXState* source, const VXObject& o)
721 (void)source;
722 destination->Push(o);
725 void VXState::MoveIndex(VXState* destination, VXState* source, VXInteger idx)
727 VXState::Move(destination, source, source->StackGet(idx));
730 VXInteger DoCompile(VXState* v, VXLexReadFunc read,
731 VXUserPointer p, const char *sourcename,
732 bool raiseerror, VXObject* dest=NULL)
734 VXObject o;
735 #ifndef VOX_NO_COMPILER
736 if(Compile(v, read, p, sourcename, o, raiseerror, _ss(v)->_debuginfo))
738 VXForeignClosureObj* closure = VXForeignClosureObj::Create(_ss(v), _funcproto(o));
739 if(dest != NULL)
741 (*dest) = closure;
743 else
745 v->Push(closure);
747 return VX_OK;
749 return VX_ERROR;
750 #else
751 return v->ThrowError("this is a no compiler build");
752 #endif
756 VXInteger VXState::CompileBuffer(const char* source, VXInteger size,
757 const char* sourcename, bool raiseerror)
759 BufState buf;
760 buf.buf = source;
761 buf.size = size;
762 buf.ptr = 0;
763 return DoCompile(this, buf_lexfeed, &buf, sourcename, raiseerror);
766 VXInteger VXState::DoStringFmt(bool globaltable, bool returns,
767 bool raise_error, const char* str_format, ...)
769 VXInteger retvalue;
770 va_list arguments;
771 va_start(arguments, str_format);
772 char* buffptr;
773 size_t realsize;
774 size_t needed = 0;
775 size_t initial_bufsize = 1;
776 buffptr = new char[initial_bufsize+1];
777 needed = 1 + vsnprintf(buffptr, initial_bufsize, str_format, arguments);
778 va_end(arguments);
779 if(needed > initial_bufsize)
781 delete[] buffptr;
782 buffptr = new char[needed+1];
783 va_start(arguments, str_format);
784 realsize = vsnprintf(buffptr, needed, str_format, arguments);
785 va_end(arguments);
787 else
789 realsize = needed;
791 buffptr[realsize] = 0;
792 if(globaltable)
794 this->PushRoot();
796 retvalue = this->DoString(buffptr, realsize, "<buffer>", returns, raise_error);
797 if(globaltable)
799 this->Pop(1);
801 delete[] buffptr;
802 return retvalue;
806 VXInteger VXState::DoString(const char* str, VXInteger len,
807 const char* bufname, bool retval, bool printerror)
809 len = (len == -1) ? strlen(str) : len;
810 if(bufname == NULL)
812 bufname = "<buffer>";//DOSTRING_DEFAULTBUFFERNAME;
814 if(VX_FAILED(this->CompileBuffer(str, len, bufname, printerror)))
816 return VX_ERROR;
818 else
820 Repush(-2);
821 if(VX_FAILED(StackCall(1, retval, printerror)))
823 return VX_ERROR;
825 return VX_OK;
827 return ThrowError("call failed");
830 VXInteger VXState::ReadClosure(VXReadFunc r, VXUserPointer up, VXObject* dest)
832 VXObject closure;
833 unsigned short tag;
834 if(r(up, &tag, 2) != 2)
836 return ThrowError("io error");
838 if(tag != VX_BYTECODE_STREAM_TAG)
840 return ThrowError("invalid stream");
842 if(!VXForeignClosureObj::Load(this, up, r, closure))
844 return VX_ERROR;
846 if(dest)
848 (*dest) = closure;
850 else
852 this->Push(closure);
854 return VX_OK;
857 VXInteger VXState::LoadFile(const char* filename, bool printerror,
858 bool* failed_to_open, VXObject* dest)
861 FILE* file = fopen(filename, "rb");
862 VXInteger ret;
863 unsigned short us;
864 unsigned char uc;
865 VXLexReadFunc func = _io_file_lexfeed_PLAIN;
866 if(file)
868 if(failed_to_open != NULL)
870 (*failed_to_open) = false;
872 ret = fread(&us,1,2,file);
873 if(ret != 2)
875 //probably an empty file
876 us = 0;
878 //BYTECODE
879 if(us == VX_BYTECODE_STREAM_TAG)
881 VXInteger st;
882 fseek(file, 0, SEEK_SET);
883 if(VX_SUCCEEDED((st = this->ReadClosure(file_read, file, dest))))
885 fclose(file);
886 return st;
888 return st;
890 else //SCRIPT
892 switch(us)
894 //gotta swap the next 2 lines on BIG endian machines
895 //UTF-16 little endian
896 case 0xFFFE:
897 func = _io_file_lexfeed_UCS2_BE;
898 break;
900 // UTF-16 big endian
901 case 0xFEFF:
902 func = _io_file_lexfeed_UCS2_LE;
903 break;
905 // UTF-8
906 case 0xBBEF:
907 if(fread(&uc, 1, sizeof(uc), file) == 0)
909 fclose(file);
910 return ThrowError("io error");
912 if(uc != 0xBF)
914 fclose(file);
915 return ThrowError("Unrecognozed encoding");
917 func = _io_file_lexfeed_PLAIN;
918 break;
920 // ascii
921 default:
922 fseek(file, 0, SEEK_SET);
923 break;
925 if(VX_SUCCEEDED(DoCompile(this, func,file,filename,printerror, dest)))
927 fclose(file);
928 return VX_OK;
931 fclose(file);
932 return VX_ERROR;
934 if(failed_to_open != NULL)
936 (*failed_to_open) = true;
938 return ThrowError("Cannot open '%s' for reading: %s", filename, strerror(errno));
941 VXInteger VXState::CallStack(VXInteger idx, VXInteger params,bool retval,bool raiseerror)
943 return this->CallSimple(this->GetUp(idx), params, retval, raiseerror);
946 VXInteger VXState::CallStack(VXInteger params,bool retval,bool raiseerror)
948 return this->CallStack(-(params+1), params, retval, raiseerror);
951 VXInteger VXState::CallSimple(VXObject& closure, VXInteger params,bool retval,bool raiseerror)
953 VXObject res;
954 if(this->Call(closure, params, this->_top-params, res, raiseerror))
956 if(!this->_suspended)
958 //pop closure and args
959 this->Pop(params);
961 if(retval)
963 this->Push(res);
964 return VX_OK;
966 return VX_OK;
968 else
970 this->Pop(params);
971 return VX_ERROR;
973 if(!this->_suspended)
975 this->Pop(params);
977 return this->ThrowError("call failed");
981 VXInteger VXState::Repush(VXInteger idx)
983 this->Push(this->StackGet(idx));
984 return VX_OK;
987 VXInteger VXState::StackCall(VXInteger params, bool retval, bool raiseerror)
989 VXObject res;
990 if(this->Call(this->GetUp(-(params+1)), params, this->_top - params, res, raiseerror))
992 if(!this->_suspended)
994 //pop closure and args
995 this->Pop(params);
997 if(retval)
999 this->Push(res);
1000 return VX_OK;
1002 return VX_OK;
1004 else
1006 this->Pop(params);
1007 return VX_ERROR;
1009 if(!this->_suspended)
1011 this->Pop(params);
1013 return ThrowError("call failed");
1016 VXInteger VXState::DoFile(const char* filename, bool retval, bool printerror, bool* failed_to_open)
1018 if(VX_SUCCEEDED(this->LoadFile(filename, printerror, failed_to_open)))
1020 this->Repush(-2);
1021 if(VX_SUCCEEDED(this->StackCall(1, retval, printerror)))
1023 this->Remove(retval ? -2 : -1);
1024 return VX_OK;
1026 this->Pop(1);
1027 return VX_ERROR;
1029 return VX_ERROR;
1034 const char* VXState::GetLocal(VXUnsignedInteger level,VXUnsignedInteger idx, VXObject& dest)
1036 VXUnsignedInteger cstksize = this->_callsstacksize;
1037 VXUnsignedInteger lvl = (cstksize-level)-1;
1038 VXInteger stackbase = this->_stackbase;
1039 if(lvl < cstksize)
1041 for(VXUnsignedInteger i=0; i<level; i++)
1043 VXState::CallInfo &ci = this->_callsstack[(cstksize-i)-1];
1044 stackbase -= ci._prevstkbase;
1046 VXState::CallInfo &ci = this->_callsstack[lvl];
1047 if(type(ci._closure) != VX_OT_CLOSURE)
1048 return NULL;
1049 VXForeignClosureObj *c = _closure(ci._closure);
1050 VXFuncProtoObj *func = c->_function;
1051 if(func->_noutervalues > (VXInteger)idx)
1053 //v->Push(*_outer(c->_outervalues[idx])->_valptr);
1054 dest = *_outer(c->_outervalues[idx])->_valptr;
1055 return _stringval(func->_outervalues[idx]._name);
1057 idx -= func->_noutervalues;
1058 return func->GetLocal(this,
1059 stackbase, idx,
1060 (VXInteger)(ci._ip-func->_instructions)-1, dest);
1062 return NULL;
1067 void VXState::DefineGlobal(const char* name, const VXObject& sym)
1069 GetRootTable()->NewSlot(NewString(name), sym);
1072 void VXState::SetPrintFunc(VXPrintFunction printfunc,VXPrintFunction errfunc)
1074 this->Shared()->_printfunc = printfunc;
1075 this->Shared()->_errorfunc = errfunc;
1080 void VXState::PushLastError()
1082 this->Push(this->_lasterror);
1086 const char* VXState::LastError()
1088 const char* result;
1089 this->PushLastError();
1090 if(VX_FAILED(this->GetString(-1, &result, NULL)))
1092 result = "<unknown error>";
1094 return result;
1097 void VXState::Mark(VXCollectable **chain)
1099 START_MARK()
1100 VXSharedState::MarkObject(_lasterror,chain);
1101 VXSharedState::MarkObject(_errorhandler,chain);
1102 VXSharedState::MarkObject(_debughook_closure,chain);
1103 VXSharedState::MarkObject(_roottable, chain);
1104 VXSharedState::MarkObject(temp_reg, chain);
1105 for(VXUnsignedInteger i = 0; i < _stack.size(); i++)
1107 VXSharedState::MarkObject(_stack[i], chain);
1109 for(VXInteger k = 0; k < _callsstacksize; k++)
1111 VXSharedState::MarkObject(_callsstack[k]._closure, chain);
1113 END_MARK()
1116 void VXState::Release()
1118 vox_delete(this,VXState);
1121 VXOType VXState::GetType()
1123 return VX_OT_THREAD;
1126 void VXState::GrowCallStack()
1128 VXInteger newsize = _alloccallsstacksize*2;
1129 _callstackdata.resize(newsize);
1130 _callsstack = &_callstackdata[0];
1131 _alloccallsstacksize = newsize;
1134 VXObject& VXState::StackGet(VXInteger idx)
1136 //return ((idx>=0) ? (this->GetAt(idx + ((this->_stackbase)-1))) : (this->GetUp(idx)));
1137 if(idx >= 0)
1139 return this->GetAt(idx + ((this->_stackbase)-1));
1141 return this->GetUp(idx);
1144 VXInteger VXState::SetParamsCheck(VXObject& o, VXInteger nparams, const char *typemask)
1146 //VXObject o = stack_get(v, -1);
1147 if(!o.IsNativeClosure())
1149 return ThrowError("native closure expected");
1151 VXNativeClosureObj *nc = _nativeclosure(o);
1152 nc->_nparamscheck = nparams;
1153 if(typemask)
1155 VXIntVec res;
1156 if(!CompileTypemask(res, typemask))
1158 return ThrowError("invalid typemask");
1160 nc->_typecheck.copy(res);
1162 else
1164 nc->_typecheck.resize(0);
1166 if(nparams == VX_MATCHTYPEMASKSTRING)
1168 nc->_nparamscheck = nc->_typecheck.size();
1170 return VX_OK;
1174 void RegisterLib_IterReg(VXState* self, const VXRegFunction* funcs, VXTableObj* dest)
1176 VXInteger i;
1177 for(i=0; funcs[i].name; i++)
1179 VXRegFunction reg = funcs[i];
1180 VXObject name = self->NewString(reg.name);
1181 VXObject fn = self->NewClosure(reg.func);
1182 self->SetParamsCheck(fn, reg.nparamscheck, reg.typemask);
1183 dest->NewSlot(name, fn);
1187 VXTableObj* VXState::RegisterLib(const char* libname, const VXRegFunction* funcs,
1188 bool reg_global, VXTableObj* tb)
1191 if(reg_global && (libname == NULL))
1193 // in this case, each function of $funcs is supposed to be
1194 // a separate item in the root table
1195 RegisterLib_IterReg(this, funcs, GetRootTable());
1197 else
1199 // otherwise, a separate table with each function of $funcs will be
1200 // created and newslot'd to the root table
1201 if(tb == NULL)
1203 tb = this->NewTable();
1205 RegisterLib_IterReg(this, funcs, tb);
1206 if(reg_global)
1208 vox_assert(libname != NULL);
1209 GetRootTable()->NewSlot(NewString(libname), tb);
1212 return tb;
1215 VXClassObj* VXState::RegClass(const VXVector<VXRegFunction>& funcs,
1216 VXClassObj* base,
1217 VXUserPointer typetag)
1219 VXUnsignedInteger i;
1220 VXClassObj* cl;
1221 cl = this->NewClass(base);
1222 for(i=0; i<funcs.size(); i++)
1224 VXRegFunction f = funcs[i];
1225 VXObject fn = this->NewClosure(f.func);
1226 VXObject name = this->NewString(f.name);
1227 this->SetParamsCheck(fn, f.nparamscheck, f.typemask);
1228 cl->NewSlot(this->Shared(), name, fn, false);
1230 if(typetag != 0)
1232 cl->_typetag = typetag;
1234 return cl;
1238 VXClassObj* VXState::RegClass(const VXRegFunction* funcs,
1239 VXClassObj* base,
1240 VXUserPointer typetag)
1242 VXInteger i;
1243 VXVector<VXRegFunction> vecfuncs;
1244 for(i=0; funcs[i].name; i++)
1246 vecfuncs.push_back(funcs[i]);
1248 return this->RegClass(vecfuncs, base, typetag);
1252 VXClassObj* VXState::NewClass(VXClassObj* baseclass)
1254 VXClassObj* ret;
1255 ret = VXClassObj::Create(this->Shared(), baseclass);
1256 return ret;
1259 VXNativeClosureObj* VXState::NewClosure(VXFunction func, VXUnsignedInteger nfreevars)
1261 VXNativeClosureObj *nc = VXNativeClosureObj::Create(this->Shared(), func,nfreevars);
1262 nc->_nparamscheck = 0;
1263 for(VXUnsignedInteger i=0; i<nfreevars; i++)
1265 nc->_outervalues[i] = this->Top();
1266 this->Pop();
1268 return nc;
1271 VXStringObj* VXState::NewString(const char* str, VXInteger len)
1273 return VXStringObj::Create(_sharedstate, str, len);
1276 VXArrayObj* VXState::NewArray(VXInteger initial_size)
1278 return VXArrayObj::Create(_sharedstate, initial_size);
1281 VXTableObj* VXState::NewTable()
1283 return VXTableObj::Create(_sharedstate, 0);
1287 VXState* VXState::NewThread(VXState* friendvm, VXInteger initialstacksize)
1289 VXSharedState *ss;
1290 VXState *v;
1291 ss = _ss(friendvm);
1292 v = (VXState *)VX_MALLOC(sizeof(VXState));
1293 new (v) VXState(ss);
1295 if(v->Init(friendvm, initialstacksize))
1297 friendvm->Push(v);
1298 return v;
1300 else
1302 vox_delete(v, VXState);
1303 return NULL;
1307 VXArrayObj* VXState::GetSysArgv()
1309 return _system_argv;
1312 VXTableObj* VXState::GetRegistryTable()
1314 return Shared()->_registry.Table();
1317 VXTableObj* VXState::GetRootTable()
1319 return _roottable.Table();
1323 VXInteger VXState::ThrowError(const char *s, ...)
1325 va_list vl;
1326 va_start(vl, s);
1327 vsprintf(ScratchPad((VXInteger)strlen(s)+(NUMBER_MAX_CHAR*2)), s, vl);
1328 va_end(vl);
1329 this->_lasterror = VXStringObj::Create(_ss(this),ScratchPad(-1),-1);
1330 return VX_ERROR;
1333 VXInteger VXState::Irrecoverable_Error(const char* s, ...)
1335 va_list vl;
1336 va_start(vl, s);
1337 vsprintf(ScratchPad((VXInteger)strlen(s)+(NUMBER_MAX_CHAR*2)), s, vl);
1338 va_end(vl);
1339 fprintf(stderr, "Irrecoverable Error: %s\n", ScratchPad(-1));
1340 exit(-1);
1341 return VX_ERROR; // never reached
1345 VXStringObj* VXState::PrintObjVal(const VXObject &o)
1347 switch(type(o))
1349 case VX_OT_STRING:
1350 return _string(o);
1351 case VX_OT_INTEGER:
1352 sprintf(ScratchPad(NUMBER_MAX_CHAR+1), _PRINT_INT_FMT, _integer(o));
1353 return VXStringObj::Create(_ss(this), ScratchPad(-1));
1354 break;
1355 case VX_OT_FLOAT:
1356 sprintf(ScratchPad(NUMBER_MAX_CHAR+1), "%.14g", _float(o));
1357 return VXStringObj::Create(_ss(this), ScratchPad(-1));
1358 break;
1359 default:
1360 return VXStringObj::Create(_ss(this), GetTypeName(o));
1364 VXInteger VXState::Raise_IdxError(const VXObject &o,
1365 const VXObject& origin,
1366 bool is_index)
1368 VXInteger len;
1369 VXObject idx = PrintObjVal(o);
1370 if(origin.Type() == VX_OT_TABLE)
1372 return ThrowError("table key '%.50s' does not exist", _stringval(idx));
1374 if(((origin.Type() == VX_OT_CLASS || origin.Type() == VX_OT_INSTANCE) ||
1375 (origin.Type() & VX_OT_INSTANCE)) && !is_index)
1377 return ThrowError("class member '%.50s' does not exist", _stringval(idx));
1379 if(origin.Type() == VX_OT_STRING || origin.Type() == VX_OT_ARRAY)
1381 switch(origin.Type())
1383 case VX_OT_STRING:
1384 len = origin.String()->_len;
1385 break;
1386 case VX_OT_ARRAY:
1387 len = origin.Array()->Size();
1388 break;
1389 default:
1390 len = -1;
1392 return ThrowError("%s index '%.50s' out of range (%s size: %d)",
1393 origin.TypeString(), _stringval(idx), origin.TypeString(), len);
1395 return ThrowError("%s index '%.50s' does not exist",
1396 origin.TypeString(), _stringval(idx));
1399 VXInteger VXState::ThrowError(const VXObject &desc)
1401 _lasterror = desc;
1402 return VX_ERROR;
1406 VXInteger VXState::Raise_CompareError(const VXObject &o1, const VXObject &o2)
1408 VXObject oval1 = PrintObjVal(o1);
1409 VXObject oval2 = PrintObjVal(o2);
1410 ThrowError("comparison between '%s' and '%s'", o1.TypeString(), o2.TypeString());
1411 return VX_ERROR;
1414 VXInteger VXState::Raise_ParamTypeError(VXInteger nparam,VXInteger typemask,VXInteger type)
1416 VXObject exptypes = VXStringObj::Create(_ss(this), "", -1);
1417 VXInteger found = 0;
1418 for(VXInteger i=0; i<16; i++)
1420 VXInteger mask = 0x00000001 << i;
1421 if(typemask & (mask))
1423 if(found > 0)
1425 StringCat(exptypes,VXStringObj::Create(_ss(this), "|", -1), exptypes);
1427 found++;
1428 StringCat(exptypes,VXStringObj::Create(_ss(this),
1429 IdType2Name((VXOType)mask), -1), exptypes);
1432 return ThrowError("parameter %d has an invalid type '%s' ; expected: '%s'",
1433 nparam,
1434 IdType2Name((VXOType)type),
1435 _stringval(exptypes)
1440 VXSharedState* VXState::Shared()
1442 return _sharedstate;
1445 VXState* VXState::Create(VXInteger stacksize)
1447 VXSharedState *ss;
1448 VXState *v;
1449 vox_new(ss, VXSharedState);
1450 ss->Init();
1451 v = (VXState *)VX_MALLOC(sizeof(VXState));
1452 new (v) VXState(ss);
1453 ss->_root_vm = v;
1454 if(v->Init(NULL, stacksize) == true)
1456 v->_system_argv = v->NewArray();
1457 voxstd_register_system(v);
1458 voxstd_register_mathlib(v);
1459 voxstd_register_iolib(v);
1460 v->SetPrintFunc(vox_defaultprintfunc, vox_defaulterrorfunc);
1461 return v;
1463 else
1465 vox_delete(v, VXState);
1466 return NULL;
1468 return NULL;
1471 void VXState::Destroy(VXState* vm)
1473 VXUnsignedInteger i;
1474 VXSharedState* ss = _ss(vm);
1475 for(i=0; i<(vm->_atexit_functions.size()); i++)
1477 VXObject res;
1478 if(!vm->Call(vm->_atexit_functions[i], 1, vm->GetTop()-1, res, false))
1480 //fprintf(stderr, "Call() failed?\n");
1483 _thread(ss->_root_vm)->Finalize();
1484 vox_delete(ss, VXSharedState);
1488 VXState::VXState(VXSharedState *ss)
1490 _sharedstate=ss;
1491 _suspended = false;
1492 _suspended_target = -1;
1493 _suspended_root = false;
1494 _suspended_traps = -1;
1495 _foreignptr = NULL;
1496 _nnativecalls = 0;
1497 _nmetamethodscall = 0;
1498 _lasterror.Null();
1499 _errorhandler.Null();
1500 _debughook = false;
1501 _debughook_native = NULL;
1502 _debughook_closure.Null();
1503 _openouters = NULL;
1504 ci = NULL;
1505 INIT_CHAIN();
1506 ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
1509 void VXState::Finalize()
1511 if(_openouters)
1513 CloseOuters(this, &_stack.values()[0]);
1515 _roottable.Null();
1516 _lasterror.Null();
1517 _errorhandler.Null();
1518 _debughook = false;
1519 _debughook_native = NULL;
1520 _debughook_closure.Null();
1521 temp_reg.Null();
1522 _callstackdata.resize(0);
1523 VXInteger size=_stack.size();
1524 for(VXInteger i=0;i<size;i++)
1526 _stack[i].Null();
1530 VXState::~VXState()
1532 Finalize();
1533 REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
1539 bool VXState::ObjCmp(const VXObject &o1,
1540 const VXObject &o2,
1541 VXInteger &result)
1543 VXObject res;
1544 VXOType t1 = type(o1);
1545 VXOType t2 = type(o2);
1546 if(t1 == t2)
1548 if(_rawval(o1) == _rawval(o2))
1550 _RET_SUCCEED(0);
1552 switch(t1)
1554 case VX_OT_STRING:
1555 _RET_SUCCEED(strcmp(_stringval(o1), _stringval(o2)));
1556 case VX_OT_INTEGER:
1557 _RET_SUCCEED(_integer(o1)-_integer(o2));
1558 case VX_OT_FLOAT:
1559 _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
1560 case VX_OT_TABLE:
1561 case VX_OT_USERDATA:
1562 case VX_OT_INSTANCE:
1563 if(_delegable(o1)->_delegate)
1565 VXObject closure;
1566 if(_delegable(o1)->GetMetaMethod(this, VX_MT_CMP, closure))
1568 Push(o1);Push(o2);
1569 if(!CallMetaMethod(this, closure,VX_MT_CMP,2,res))
1571 return false;
1574 break;
1576 //continues through (no break needed)
1577 default:
1578 _RET_SUCCEED( _userpointerval(o1) < _userpointerval(o2)?-1:1 );
1580 if(type(res)!=VX_OT_INTEGER)
1582 Raise_CompareError(o1,o2);
1583 return false;
1585 _RET_SUCCEED(_integer(res));
1588 else
1590 if(o1.IsNumeric() && o2.IsNumeric())
1592 if((t1==VX_OT_INTEGER) && (t2==VX_OT_FLOAT))
1594 if(_integer(o1) == _float(o2) )
1596 _RET_SUCCEED(0);
1598 else if(_integer(o1)<_float(o2))
1600 _RET_SUCCEED(-1);
1602 _RET_SUCCEED(1);
1604 else
1606 if(_float(o1)==_integer(o2))
1608 _RET_SUCCEED(0);
1610 else if(_float(o1) < _integer(o2))
1612 _RET_SUCCEED(-1);
1614 _RET_SUCCEED(1);
1617 else if(t1==VX_OT_NULL)
1619 _RET_SUCCEED(-1);
1621 else if(t2==VX_OT_NULL)
1623 _RET_SUCCEED(1);
1625 else
1627 Raise_CompareError(o1,o2);
1628 return false;
1631 vox_assert(0);
1632 _RET_SUCCEED(0); //cannot happen
1636 bool VXState::ToString(const VXObject &o, VXObject &res)
1638 switch(type(o))
1640 case VX_OT_STRING:
1641 res = o;
1642 return true;
1643 case VX_OT_FLOAT:
1644 sprintf(ScratchPad(NUMBER_MAX_CHAR+1),"%g",_float(o));
1645 break;
1646 case VX_OT_INTEGER:
1647 sprintf(ScratchPad(NUMBER_MAX_CHAR+1),_PRINT_INT_FMT,_integer(o));
1648 break;
1649 case VX_OT_BOOL:
1650 sprintf(ScratchPad(6),_integer(o)?"true":"false");
1651 break;
1652 case VX_OT_TABLE:
1653 case VX_OT_USERDATA:
1654 case VX_OT_INSTANCE:
1655 if(_delegable(o)->_delegate)
1657 VXObject closure;
1658 if(_delegable(o)->GetMetaMethod(this, VX_MT_TOSTRING, closure))
1660 Push(o);
1661 if(CallMetaMethod(this, closure,VX_MT_TOSTRING,1,res))
1663 if(type(res) == VX_OT_STRING)
1665 return true;
1668 else
1670 return false;
1674 default:
1675 if(type(o) != VX_OT_NULL)
1677 sprintf(ScratchPad(sizeof(void*)+60),
1678 "<%s at %p>",
1679 GetTypeName(o),(void*)_rawval(o));
1681 else
1683 sprintf(ScratchPad(8), "<null>");
1686 //res = VXStringObj::Create(_ss(this), ScratchPad(-1));
1687 res = NewString(ScratchPad(-1));
1688 return true;
1692 bool VXState::StringCat(const VXObject &str,
1693 const VXObject &obj,
1694 VXObject &dest)
1696 VXObject a, b;
1697 if(!ToString(str, a))
1699 return false;
1701 if(!ToString(obj, b))
1703 return false;
1705 VXInteger l = _string(a)->_len , ol = _string(b)->_len;
1706 char *s = ScratchPad(l + ol + 1);
1707 memcpy(s, _stringval(a), l);
1708 memcpy(s + l, _stringval(b), ol);
1709 dest = VXStringObj::Create(_ss(this), ScratchPad(-1), l + ol);
1710 return true;
1713 bool VXState::TypeOf(const VXObject &obj1,
1714 VXObject &dest)
1716 if(is_delegable(obj1) && _delegable(obj1)->_delegate)
1718 VXObject closure;
1719 if(_delegable(obj1)->GetMetaMethod(this, VX_MT_TYPEOF, closure))
1721 Push(obj1);
1722 return CallMetaMethod(this, closure,VX_MT_TYPEOF,1,dest);
1725 dest = VXStringObj::Create(_ss(this),GetTypeName(obj1));
1726 return true;
1729 bool VXState::Init(VXState *friendvm, VXInteger stacksize)
1731 _stack.resize(stacksize);
1732 _alloccallsstacksize = 4;
1733 _callstackdata.resize(_alloccallsstacksize);
1734 _callsstacksize = 0;
1735 _callsstack = &_callstackdata[0];
1736 _stackbase = 0;
1737 _top = 0;
1738 if(!friendvm)
1740 _roottable = NewTable();
1742 else
1744 _roottable = friendvm->_roottable;
1745 _errorhandler = friendvm->_errorhandler;
1746 _debughook = friendvm->_debughook;
1747 _debughook_native = friendvm->_debughook_native;
1748 _debughook_closure = friendvm->_debughook_closure;
1750 return true;
1755 bool VXState::StartCall(VXForeignClosureObj *closure,
1756 VXInteger target,
1757 VXInteger args,
1758 VXInteger stackbase,
1759 bool tailcall)
1761 VXFuncProtoObj *func = closure->_function;
1763 VXInteger paramssize = func->_nparameters;
1764 const VXInteger newtop = stackbase + func->_stacksize;
1765 VXInteger nargs = args;
1766 const char* funcname = _stringval(func->_name);
1767 if(func->_name.IsNull())
1769 funcname = NAMES_ANONFUNC;
1771 if(func->_varparams)
1773 paramssize--;
1774 if(nargs < paramssize)
1776 return WrongNumberOfArguments(this, false, false, func);
1778 VXInteger nvargs = nargs - paramssize;
1779 VXArrayObj *arr = VXArrayObj::Create(_ss(this),nvargs);
1780 VXInteger pbase = stackbase+paramssize;
1781 for(VXInteger n = 0; n < nvargs; n++)
1783 arr->_values[n] = _stack.values()[pbase];
1784 _stack.values()[pbase].Null();
1785 pbase++;
1787 _stack.values()[stackbase+paramssize] = arr;
1789 else if (paramssize != nargs)
1791 VXInteger ndef = func->_ndefaultparams;
1792 VXInteger diff;
1793 if(ndef && (nargs < paramssize) && (diff = (paramssize - nargs)) <= ndef)
1795 for(VXInteger n = ndef - diff; n < ndef; n++)
1797 _stack.values()[stackbase + (nargs++)] = closure->_defaultparams[n];
1800 else
1802 return WrongNumberOfArguments(this, false, false, func);
1805 if(closure->_env)
1807 _stack.values()[stackbase] = closure->_env->_obj;
1809 if(!EnterFrame(stackbase, newtop, tailcall))
1811 return false;
1813 ci->_closure = closure;
1814 ci->_literals = func->_literals;
1815 ci->_ip = func->_instructions;
1816 ci->_target = (VXInt32)target;
1817 if (_debughook)
1819 CallDebugHook('c');
1821 if (closure->_function->_bgenerator)
1823 VXFuncProtoObj *f = closure->_function;
1824 VXGeneratorObj *gen = VXGeneratorObj::Create(_ss(this), closure);
1825 if(!gen->Yield(this,f->_stacksize))
1826 return false;
1827 VXObject temp;
1828 Return(this, 1, target, temp);
1829 STK(target) = gen;
1831 return true;
1836 VXInteger VXState::RawGetStack(VXInteger idx)
1838 VXObject& self = StackGet(idx);
1839 switch(type(self))
1841 case VX_OT_TABLE:
1842 if(_table(self)->Get(GetUp(-1), GetUp(-1)))
1843 return VX_OK;
1844 break;
1845 case VX_OT_CLASS:
1846 if(_class(self)->Get(GetUp(-1), GetUp(-1)))
1847 return VX_OK;
1848 break;
1849 case VX_OT_INSTANCE:
1850 if(_instance(self)->Get(GetUp(-1), GetUp(-1)))
1851 return VX_OK;
1852 break;
1853 case VX_OT_ARRAY:
1855 VXObject& key = GetUp(-1);
1856 if(key.IsNumeric())
1858 if(_array(self)->Get(tointeger(key), GetUp(-1)))
1860 return VX_OK;
1863 else
1865 Pop();
1866 return ThrowError("invalid index type for an array");
1869 break;
1870 default:
1871 Pop();
1872 return ThrowError("rawget works only on array/table/instance and class");
1874 Pop();
1875 return ThrowError("the index doesn't exist");
1878 VXInteger VXState::RawSetStack(VXInteger idx)
1880 VXObject &self = this->StackGet(idx);
1881 if(type(this->GetUp(-2)) == VX_OT_NULL)
1883 return this->ThrowError("null key");
1885 switch(type(self))
1887 case VX_OT_TABLE:
1888 _table(self)->NewSlot(GetUp(-2), GetUp(-1));
1889 Pop(2);
1890 return VX_OK;
1891 break;
1892 case VX_OT_CLASS:
1893 _class(self)->NewSlot(Shared(), GetUp(-2), GetUp(-1),false);
1894 Pop(2);
1895 return VX_OK;
1896 break;
1897 case VX_OT_INSTANCE:
1898 if(_instance(self)->Set(GetUp(-2), GetUp(-1)))
1900 Pop(2);
1901 return VX_OK;
1903 break;
1904 case VX_OT_ARRAY:
1905 if(Set(self, GetUp(-2), GetUp(-1),false))
1907 Pop(2);
1908 return VX_OK;
1910 break;
1911 default:
1912 Pop(2);
1913 return ThrowError("rawset works only on array/table/class and instance");
1915 return Raise_IdxError(GetUp(-2), self);
1918 VXInteger VXState::ToStringAt(VXInteger idx, VXObject& dest)
1920 VXObject &o = this->StackGet(idx);
1921 return this->ToString(o, dest);
1924 VXInteger VXState::Raise_InvalidType(VXOType type)
1926 return ThrowError("unexpected type %s", IdType2Name(type));
1930 VXInteger VXState::GetSize(const VXObject& o)
1932 VXOType type = type(o);
1933 switch(type)
1935 case VX_OT_STRING:
1936 return _string(o)->_len;
1937 case VX_OT_TABLE:
1938 return _table(o)->CountUsed();
1939 case VX_OT_ARRAY:
1940 return _array(o)->Size();
1941 case VX_OT_USERDATA:
1942 return _userdata(o)->_size;
1943 case VX_OT_INSTANCE:
1944 return _instance(o)->_class->_udsize;
1945 case VX_OT_CLASS:
1946 return _class(o)->_udsize;
1947 default:
1948 return this->Raise_InvalidType(type);
1952 VXInteger VXState::GetSizeAt(VXInteger idx)
1954 VXObject &o = StackGet(idx);
1955 return this->GetSize(o);
1958 VXInteger VXState::Clear(VXObject& o)
1960 switch(type(o))
1962 case VX_OT_TABLE:
1963 _table(o)->Clear();
1964 break;
1965 case VX_OT_ARRAY:
1966 _array(o)->Resize(0);
1967 break;
1968 default:
1969 return this->ThrowError("clear only works on table and array");
1970 break;
1972 return VX_OK;
1976 VXInteger VXState::ClearAt(VXInteger idx)
1978 return this->Clear(this->StackGet(idx));
1982 VXInteger VXState::StackInfos(VXInteger level, VXStackInfos* si)
1984 VXInteger cssize = this->_callsstacksize;
1985 if (cssize > level)
1987 memset(si, 0, sizeof(VXStackInfos));
1988 VXState::CallInfo &ci = this->_callsstack[cssize-level-1];
1989 switch(type(ci._closure))
1991 case VX_OT_CLOSURE:
1993 VXFuncProtoObj *func = _closure(ci._closure)->_function;
1994 si->native = false;
1995 if (type(func->_name) == VX_OT_STRING)
1997 si->funcname = _stringval(func->_name);
1999 if (type(func->_sourcename) == VX_OT_STRING)
2001 si->source = _stringval(func->_sourcename);
2003 si->line = func->GetLine(ci._ip);
2005 break;
2006 case VX_OT_NATIVECLOSURE:
2008 si->native = true;
2009 si->source = "<native>";
2010 si->funcname = "<closure>";
2011 if(type(_nativeclosure(ci._closure)->_name) == VX_OT_STRING)
2013 si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
2015 si->line = -1;
2017 break;
2018 default:
2019 break;
2021 return VX_OK;
2023 return VX_ERROR;
2026 VXPrintFunction VXState::GetErrorFunc()
2028 return Shared()->_errorfunc;
2031 VXInteger VXState::Suspend()
2033 if (_suspended)
2035 return this->ThrowError("cannot suspend an already suspended vm");
2037 if (_nnativecalls!=2)
2039 return this->ThrowError("cannot suspend through native calls/metamethods");
2041 return VX_SUSPEND_FLAG;
2048 bool VXState::IsEqual(const VXObject &o1,
2049 const VXObject &o2,
2050 bool &res)
2052 if(type(o1) == type(o2))
2054 res = (_rawval(o1) == _rawval(o2));
2056 else
2058 if(o1.IsNumeric() && o2.IsNumeric())
2060 res = (tofloat(o1) == tofloat(o2));
2062 else
2064 res = false;
2067 return true;
2070 bool VXState::IsFalse(VXObject &o)
2072 if(((type(o) & VXOBJECT_CANBEFALSE)
2073 && ( ((type(o) == VX_OT_FLOAT) && (_float(o) == VXFloat(0.0))) ))
2074 || (_integer(o) == 0) ) //VX_OT_NULL|OT_INTEGER|OT_BOOL
2076 return true;
2078 return false;
2081 bool VXState::Execute(VXObject &closure,
2082 VXInteger nargs,
2083 VXInteger stackbase,
2084 VXObject &outres,
2085 bool raiseerror,
2086 ExecutionType et)
2088 if ((_nnativecalls + 1) > MAX_NATIVE_CALLS)
2090 ThrowError("native stack overflow");
2091 return false;
2093 _nnativecalls++;
2094 AutoDec ad(&_nnativecalls);
2095 VXInteger traps = 0;
2096 CallInfo *prevci = ci;
2097 switch(et)
2099 case ET_CALL:
2101 temp_reg = closure;
2102 if(!StartCall(_closure(temp_reg),
2103 _top - nargs,
2104 nargs, stackbase, false))
2106 // call the handler if there are no calls in the
2107 // stack, if not relies on the previous node
2108 if(ci == NULL)
2110 CallErrorHandler(_lasterror);
2112 return false;
2114 if(ci == prevci)
2116 outres = STK(_top-nargs);
2117 return true;
2119 ci->_root = true;
2121 break;
2122 case ET_RESUME_GENERATOR:
2123 _generator(closure)->Resume(this, outres);
2124 ci->_root = true;
2125 traps += ci->_etraps;
2126 break;
2127 case ET_RESUME_VM:
2128 case ET_RESUME_THROW_VM:
2129 traps = _suspended_traps;
2130 ci->_root = _suspended_root;
2131 _suspended = false;
2132 if(et == ET_RESUME_THROW_VM)
2134 VX_THROW();
2136 break;
2139 exception_restore:
2142 for(;;)
2144 const VXInstruction &_i_ = *ci->_ip++;
2145 switch(_i_.op)
2147 case _OP_LINE:
2148 if (_debughook)
2150 CallDebugHook('l',arg1);
2152 continue;
2154 case _OP_LOAD:
2155 TARGET = ci->_literals[arg1];
2156 continue;
2158 case _OP_LOADINT:
2159 TARGET = (VXInteger)arg1;
2160 continue;
2162 case _OP_LOADFLOAT:
2163 TARGET = *((VXFloat *)&arg1);
2164 continue;
2166 case _OP_DLOAD:
2167 TARGET = ci->_literals[arg1];
2168 STK(arg2) = ci->_literals[arg3];
2169 continue;
2171 case _OP_TAILCALL:
2173 VXInteger i;
2174 VXObject &t = STK(arg1);
2175 if (type(t) == VX_OT_CLOSURE
2176 && (!_closure(t)->_function->_bgenerator))
2178 VXObject clo = t;
2179 if(_openouters)
2181 CloseOuters(this, &(_stack.values()[_stackbase]));
2183 for(i=0; i<arg3; i++)
2185 STK(i) = STK(arg2 + i);
2187 _GUARD(StartCall(_closure(clo),
2188 ci->_target, arg3, _stackbase, true));
2189 continue;
2193 case _OP_CALL:
2195 VXObject clo = STK(arg1);
2196 switch (type(clo))
2198 case VX_OT_CLOSURE:
2199 _GUARD(StartCall(_closure(clo),
2200 sarg0, arg3,
2201 _stackbase+arg2, false));
2202 continue;
2203 case VX_OT_NATIVECLOSURE:
2205 bool suspend;
2206 _GUARD(CallNative(
2207 _nativeclosure(clo),
2208 arg3, _stackbase+arg2,
2209 clo,suspend));
2210 if(suspend)
2212 _suspended = true;
2213 _suspended_target = sarg0;
2214 _suspended_root = ci->_root;
2215 _suspended_traps = traps;
2216 outres = clo;
2217 return true;
2219 if(sarg0 != -1)
2221 STK(arg0) = clo;
2224 continue;
2225 case VX_OT_CLASS:
2227 VXInteger stkbase;
2228 VXObject inst;
2229 _GUARD(CreateClassInstance(
2230 _class(clo),inst,clo));
2231 if(sarg0 != -1)
2233 STK(arg0) = inst;
2235 switch(type(clo))
2237 case VX_OT_CLOSURE:
2238 stkbase = _stackbase+arg2;
2239 _stack.values()[stkbase] = inst;
2240 _GUARD(StartCall(
2241 _closure(clo), -1, arg3,
2242 stkbase, false));
2243 break;
2244 case VX_OT_NATIVECLOSURE:
2245 bool suspend;
2246 stkbase = _stackbase+arg2;
2247 _stack.values()[stkbase] = inst;
2249 _GUARD(CallNative(
2250 _nativeclosure(clo), arg3,
2251 stkbase, clo, suspend));
2254 break;
2255 default:
2256 break; //shutup GCC 4.x
2262 break;
2263 case VX_OT_TABLE:
2264 case VX_OT_USERDATA:
2265 case VX_OT_INSTANCE:
2267 VXObject closure;
2268 if(_delegable(clo)->_delegate &&
2269 _delegable(clo)->GetMetaMethod(this,VX_MT_CALL,closure))
2271 Push(clo);
2272 for (VXInteger i=0; i<arg3; i++)
2274 Push(STK(arg2 + i));
2276 if(!CallMetaMethod(this, closure, VX_MT_CALL, arg3+1, clo))
2278 VX_THROW();
2280 if(sarg0 != -1)
2282 STK(arg0) = clo;
2284 break;
2287 default:
2288 ThrowError("attempt to call '%s'",
2289 GetTypeName(clo));
2290 VX_THROW();
2293 continue;
2295 case _OP_PREPCALL:
2296 case _OP_PREPCALLK:
2298 VXObject &key =
2299 (_i_.op == _OP_PREPCALLK) ?
2300 (ci->_literals)[arg1] : STK(arg1);
2301 VXObject &o = STK(arg2);
2302 if (!Get(o, key, temp_reg,false,arg2))
2304 VX_THROW();
2306 STK(arg3) = o;
2307 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
2309 continue;
2311 case _OP_GETK:
2312 if (!Get(STK(arg2), ci->_literals[arg1],
2313 temp_reg, false,arg2))
2315 VX_THROW();
2317 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
2318 continue;
2320 case _OP_MOVE:
2321 TARGET = STK(arg1);
2322 continue;
2324 case _OP_NEWSLOT:
2325 _GUARD(NewSlot(STK(arg1), STK(arg2),
2326 STK(arg3),false));
2327 if(arg0 != 0xFF)
2329 TARGET = STK(arg3);
2331 continue;
2333 case _OP_DELETE:
2334 _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET));
2335 continue;
2337 case _OP_SET:
2338 if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1))
2340 VX_THROW();
2342 if (arg0 != 0xFF)
2344 TARGET = STK(arg3);
2346 continue;
2348 case _OP_GET:
2349 if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1))
2351 VX_THROW();
2353 _Swap(TARGET,temp_reg);//TARGET = temp_reg;
2354 continue;
2356 case _OP_EQ:
2358 bool res;
2359 if(!IsEqual(STK(arg2),COND_LITERAL,res))
2361 VX_THROW();
2363 TARGET = res ? true : false;
2365 continue;
2367 case _OP_NE:
2369 bool res;
2370 if(!IsEqual(STK(arg2),COND_LITERAL,res))
2372 VX_THROW();
2374 TARGET = (!res) ? true : false;
2376 continue;
2378 case _OP_ADD:
2379 _ARITH_(+,TARGET,STK(arg2),STK(arg1));
2380 continue;
2382 case _OP_SUB:
2383 _ARITH_(-,TARGET,STK(arg2),STK(arg1));
2384 continue;
2386 case _OP_MUL:
2387 _ARITH_(*,TARGET,STK(arg2),STK(arg1));
2388 continue;
2390 case _OP_DIV:
2391 _ARITH_NOZERO(/,TARGET,STK(arg2),
2392 STK(arg1), "division by zero");
2393 continue;
2395 case _OP_MOD:
2396 ARITH_OP(this, '%',TARGET,STK(arg2),STK(arg1));
2397 continue;
2399 case _OP_BITW:
2400 _GUARD(BW_OP(this, arg3,TARGET,STK(arg2),STK(arg1)));
2401 continue;
2403 case _OP_RETURN:
2404 if((ci)->_generator)
2406 (ci)->_generator->Kill();
2408 if(Return(this, arg0, arg1, temp_reg))
2410 vox_assert(traps == 0);
2411 //outres = temp_reg;
2412 _Swap(outres,temp_reg);
2413 return true;
2415 continue;
2417 case _OP_LOADNULLS:
2419 for(VXInt32 n=0; n < arg1; n++)
2421 STK(arg0+n).Null();
2424 continue;
2426 case _OP_LOADROOT:
2427 TARGET = _roottable;
2428 continue;
2430 case _OP_LOADBOOL:
2431 TARGET = arg1?true:false;
2432 continue;
2434 case _OP_DMOVE:
2435 STK(arg0) = STK(arg1);
2436 STK(arg2) = STK(arg3);
2437 continue;
2439 case _OP_JMP:
2440 ci->_ip += (sarg1);
2441 continue;
2443 case _OP_JCMP:
2444 _GUARD(CMP_OP(this, (CmpOP)arg3,STK(arg2),
2445 STK(arg0),temp_reg));
2446 if(IsFalse(temp_reg))
2448 ci->_ip+=(sarg1);
2450 continue;
2452 case _OP_JZ:
2453 if(IsFalse(STK(arg0)))
2455 ci->_ip+=(sarg1);
2457 continue;
2459 case _OP_GETOUTER:
2461 VXForeignClosureObj *cur_cls = _closure(ci->_closure);
2462 VXOuterObj *otr = _outer(cur_cls->_outervalues[arg1]);
2463 TARGET = *(otr->_valptr);
2465 continue;
2467 case _OP_SETOUTER:
2469 VXForeignClosureObj *cur_cls = _closure(ci->_closure);
2470 VXOuterObj *otr = _outer(cur_cls->_outervalues[arg1]);
2471 *(otr->_valptr) = STK(arg2);
2472 if(arg0 != 0xFF)
2474 TARGET = STK(arg2);
2477 continue;
2479 case _OP_NEWOBJ:
2480 switch(arg3)
2482 case NVX_OT_TABLE:
2483 TARGET = VXTableObj::Create(_ss(this), arg1);
2484 continue;
2485 case NVX_OT_ARRAY:
2486 TARGET = VXArrayObj::Create(_ss(this), 0);
2487 _array(TARGET)->Reserve(arg1);
2488 continue;
2490 case NVX_OT_CLASS:
2491 _GUARD(CLASS_OP(this, TARGET,arg1,arg2));
2492 continue;
2494 default:
2495 vox_assert(0);
2496 continue;
2498 case _OP_APPENDARRAY:
2500 VXRawObj val;
2501 val._unVal.raw = 0;
2502 switch(arg2)
2504 case AAT_STACK:
2505 val = STK(arg1);
2506 break;
2507 case AAT_LITERAL:
2508 val = ci->_literals[arg1];
2509 break;
2510 case AAT_INT:
2511 val._type = VX_OT_INTEGER;
2512 val._unVal.nInteger = (VXInteger)arg1;
2513 break;
2514 case AAT_FLOAT:
2515 val._type = VX_OT_FLOAT;
2516 val._unVal.fFloat = *((VXFloat *)&arg1);
2517 break;
2518 case AAT_BOOL:
2519 val._type = VX_OT_BOOL;
2520 val._unVal.nInteger = arg1;
2521 break;
2522 default:
2523 vox_assert(0);
2524 break;
2527 _array(STK(arg0))->Append(val);
2528 continue;
2531 case _OP_COMPARITH:
2533 VXInteger selfidx =
2534 (((VXUnsignedInteger)arg1&0xFFFF0000)>>16);
2535 _GUARD(DerefInc(this, arg3, TARGET,
2536 STK(selfidx), STK(arg2),
2537 STK(arg1&0x0000FFFF), false, selfidx));
2539 continue;
2541 case _OP_INC:
2543 VXObject o(sarg3);
2544 _GUARD(DerefInc(this, '+',TARGET, STK(arg1),
2545 STK(arg2), o, false, arg1));
2547 continue;
2549 case _OP_INCL:
2551 VXObject &a = STK(arg1);
2552 if(type(a) == VX_OT_INTEGER)
2554 a._unVal.nInteger = _integer(a) + sarg3;
2556 else
2558 VXObject o(sarg3);
2559 _ARITH_(+,a,a,o);
2562 continue;
2564 case _OP_PINC:
2566 VXObject o(sarg3);
2567 _GUARD(DerefInc(this, '+',TARGET,
2568 STK(arg1), STK(arg2), o, true, arg1));
2570 continue;
2572 case _OP_PINCL:
2574 VXObject &a = STK(arg1);
2575 if(type(a) == VX_OT_INTEGER)
2577 TARGET = a;
2578 a._unVal.nInteger = _integer(a) + sarg3;
2580 else
2582 VXObject o(sarg3);
2583 _GUARD(PLOCAL_INC(this, '+',TARGET, STK(arg1), o));
2586 continue;
2588 case _OP_CMP:
2589 _GUARD(CMP_OP(this, (CmpOP)arg3,
2590 STK(arg2),STK(arg1),TARGET));
2591 continue;
2593 case _OP_EXISTS:
2594 TARGET =
2595 Get(STK(arg1), STK(arg2),
2596 temp_reg, true, DONT_FALL_BACK)
2597 ? true : false;
2598 continue;
2600 case _OP_INSTANCEOF:
2601 if(type(STK(arg1)) != VX_OT_CLASS)
2603 ThrowError(
2604 "cannot apply instanceof between a %s and a %s",
2605 GetTypeName(STK(arg1)),
2606 GetTypeName(STK(arg2)));
2607 VX_THROW();
2609 TARGET =
2610 (type(STK(arg2)) == VX_OT_INSTANCE) ?
2611 (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))
2612 ? true : false) : false;
2613 continue;
2615 case _OP_AND:
2616 if(IsFalse(STK(arg2)))
2618 TARGET = STK(arg2);
2619 ci->_ip += (sarg1);
2621 continue;
2623 case _OP_OR:
2624 if(!IsFalse(STK(arg2)))
2626 TARGET = STK(arg2);
2627 ci->_ip += (sarg1);
2629 continue;
2631 case _OP_NEG:
2632 _GUARD(NEG_OP(this, TARGET,STK(arg1)));
2633 continue;
2635 case _OP_NOT:
2636 TARGET = IsFalse(STK(arg1));
2637 continue;
2639 case _OP_BWNOT:
2640 if(type(STK(arg1)) == VX_OT_INTEGER)
2642 VXInteger t = _integer(STK(arg1));
2643 TARGET = VXInteger(~t);
2644 continue;
2646 ThrowError(
2647 "attempt to perform a bitwise op on a %s",
2648 GetTypeName(STK(arg1)));
2649 VX_THROW();
2651 case _OP_CLOSURE:
2653 VXForeignClosureObj *c = ci->_closure._unVal.pClosure;
2654 VXFuncProtoObj *fp = c->_function;
2655 if(!CLOSURE_OP(this, TARGET,
2656 fp->_functions[arg1]._unVal.pFunctionProto))
2658 VX_THROW();
2660 continue;
2662 case _OP_YIELD:
2664 if(ci->_generator)
2666 if(sarg1 != MAX_FUNC_STACKSIZE)
2667 temp_reg = STK(arg1);
2668 _GUARD(ci->_generator->Yield(this,arg2));
2669 traps -= ci->_etraps;
2670 if(sarg1 != MAX_FUNC_STACKSIZE)
2671 _Swap(STK(arg1),temp_reg);
2673 else
2675 ThrowError(
2676 "trying to yield a '%s',"
2677 "only genenerator can be yielded",
2678 GetTypeName(ci->_generator));
2679 VX_THROW();
2681 if(Return(this, arg0, arg1, temp_reg))
2683 vox_assert(traps == 0);
2684 outres = temp_reg;
2685 return true;
2689 continue;
2691 case _OP_RESUME:
2692 if(type(STK(arg1)) != VX_OT_GENERATOR)
2694 ThrowError(
2695 "trying to resume a '%s',"
2696 " only a genenerator can be resumed",
2697 GetTypeName(STK(arg1)));
2698 VX_THROW();
2700 _GUARD(_generator(STK(arg1))->Resume(this, TARGET));
2701 traps += ci->_etraps;
2702 continue;
2704 case _OP_FOREACH:
2706 int tojump;
2707 _GUARD(FOREACH_OP(this, STK(arg0),STK(arg2),
2708 STK(arg2+1),STK(arg2+2),arg2,
2709 sarg1,tojump));
2710 ci->_ip += tojump;
2712 continue;
2714 case _OP_POSTFOREACH:
2715 vox_assert(type(STK(arg0)) == VX_OT_GENERATOR);
2716 if(_generator(STK(arg0))->_state == VXGeneratorObj::eDead)
2717 ci->_ip += (sarg1 - 1);
2718 continue;
2720 case _OP_CLONE:
2721 _GUARD(Clone(STK(arg1), TARGET));
2722 continue;
2724 case _OP_TYPEOF:
2725 _GUARD(TypeOf(STK(arg1), TARGET));
2726 continue;
2728 case _OP_PUSHTRAP:
2730 VXInstruction *_iv =
2731 _closure(ci->_closure)->_function->_instructions;
2732 _etraps.push_back(VXExceptionTrap(
2733 _top,_stackbase,
2734 &_iv[(ci->_ip-_iv)+arg1], arg0));
2735 traps++;
2736 ci->_etraps++;
2738 continue;
2740 case _OP_POPTRAP:
2742 for(VXInteger i=0; i<arg0; i++)
2744 _etraps.pop_back(); traps--;
2745 ci->_etraps--;
2748 continue;
2750 case _OP_THROW:
2751 ThrowError(TARGET);
2752 VX_THROW();
2753 continue;
2755 case _OP_NEWSLOTA:
2757 bool bstatic =
2758 (arg0&NEW_SLVX_OT_STATIC_FLAG)?true:false;
2759 if(type(STK(arg1)) == VX_OT_CLASS)
2761 if(type(_class(STK(arg1))->
2762 _metamethods[VX_MT_NEWMEMBER]) != VX_OT_NULL)
2764 Push(STK(arg1));
2765 Push(STK(arg2));
2766 Push(STK(arg3));
2767 Push((arg0&NEW_SLVX_OT_ATTRIBUTES_FLAG)?
2768 STK(arg2-1) : VXObject());
2769 Push(bstatic);
2770 int nparams = 5;
2771 if(Call(_class(STK(arg1))->
2772 _metamethods[VX_MT_NEWMEMBER],
2773 nparams, _top - nparams,
2774 temp_reg,false))
2776 Pop(nparams);
2777 continue;
2779 else
2781 VX_THROW();
2785 _GUARD(NewSlot(STK(arg1), STK(arg2),
2786 STK(arg3),bstatic));
2787 if((arg0&NEW_SLVX_OT_ATTRIBUTES_FLAG))
2789 _class(STK(arg1))->SetAttributes(
2790 STK(arg2), STK(arg2-1));
2793 continue;
2795 case _OP_GETBASE:
2797 VXForeignClosureObj *clo = _closure(ci->_closure);
2798 if(clo->_base)
2800 TARGET = clo->_base;
2802 else
2804 TARGET.Null();
2806 continue;
2809 case _OP_CLOSE:
2810 if(_openouters)
2812 CloseOuters(this, &(STK(arg1)));
2814 continue;
2819 exception_trap:
2821 VXObject currerror = _lasterror;
2822 VXInteger last_top = _top;
2823 if(_ss(this)->_notifyallexceptions || (!traps && raiseerror))
2825 CallErrorHandler(currerror);
2827 while(ci)
2829 if(ci->_etraps > 0)
2831 VXExceptionTrap &et = _etraps.top();
2832 ci->_ip = et._ip;
2833 _top = et._stacksize;
2834 _stackbase = et._stackbase;
2835 _stack.values()[_stackbase + et._extarget] = currerror;
2836 _etraps.pop_back(); traps--; ci->_etraps--;
2837 while(last_top >= _top)
2839 _stack.values()[last_top--].Null();
2841 goto exception_restore;
2843 else if (_debughook)
2845 //notify debugger of a "return"
2846 //even if it really an exception unwinding the stack
2847 for(VXInteger i=0; i<(ci->_ncalls); i++)
2849 CallDebugHook('r');
2852 if(ci->_generator)
2854 ci->_generator->Kill();
2856 bool mustbreak = ci && ci->_root;
2857 LeaveFrame();
2858 if(mustbreak)
2860 break;
2863 _lasterror = currerror;
2864 return false;
2866 vox_assert(0);
2869 bool VXState::CreateClassInstance(VXClassObj *theclass,
2870 VXObject &inst,
2871 VXObject &constructor)
2873 inst = theclass->CreateInstance();
2874 if(!theclass->GetConstructor(constructor))
2876 constructor.Null();
2878 return true;
2881 void VXState::CallErrorHandler(VXObject &error)
2883 if(type(_errorhandler) != VX_OT_NULL)
2885 VXObject out;
2886 if(_errorhandler.Type() == VX_OT_NATIVECLOSURE)
2888 _errorhandler.NativeClosure()->_nparamscheck = 2;
2890 Push(_roottable);
2891 Push(error);
2892 if(!Call(_errorhandler, 2, _top-2, out, false))
2894 // the irony is killing me!
2895 Irrecoverable_Error("failed to call errorhandler!");
2897 Pop(2);
2902 void VXState::CallDebugHook(VXInteger type,
2903 VXInteger forcedline)
2905 VXFuncProtoObj* func;
2906 VXInteger line;
2907 const char* src;
2908 const char* fname;
2909 _debughook = false;
2910 func =_closure(ci->_closure)->_function;
2911 if(_debughook_native)
2913 src = type(func->_sourcename) == VX_OT_STRING ?
2914 _stringval(func->_sourcename) : NULL;
2915 fname = type(func->_name) == VX_OT_STRING ?
2916 _stringval(func->_name) : NULL;
2917 line = forcedline ? forcedline : func->GetLine(ci->_ip);
2918 _debughook_native(this,type,src,line,fname);
2920 else
2922 VXObject temp_reg;
2923 VXInteger nparams=5;
2924 Push(_roottable);
2925 Push(VXInteger(type));
2926 Push(func->_sourcename);
2927 Push(VXInteger(forcedline?forcedline:func->GetLine(ci->_ip)));
2928 Push(func->_name);
2929 Call(_debughook_closure,nparams,_top-nparams,temp_reg,false);
2930 Pop(nparams);
2932 _debughook = true;
2935 bool VXState::CallNative(VXNativeClosureObj *nclosure,
2936 VXInteger nargs,
2937 VXInteger newbase,
2938 VXObject &retval,
2939 bool &suspend)
2941 VXInteger nparamscheck = nclosure->_nparamscheck;
2942 VXInteger newtop = newbase + nargs + nclosure->_noutervalues;
2943 if(_nnativecalls + 1 > MAX_NATIVE_CALLS)
2945 ThrowError("native stack overflow");
2946 return false;
2948 if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
2949 ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
2951 return WrongNumberOfArguments(this, false, true, nclosure);
2953 VXInteger tcs;
2954 VXIntVec &tc = nclosure->_typecheck;
2955 if((tcs = tc.size()))
2957 for(VXInteger i = 0; i < nargs && i < tcs; i++)
2959 if((tc.values()[i] != -1) && !(type(_stack.values()[newbase+i]) & tc.values()[i]))
2961 Raise_ParamTypeError(i,tc.values()[i],type(_stack.values()[newbase+i]));
2962 return false;
2966 if(!EnterFrame(newbase, newtop, false))
2968 return false;
2970 ci->_closure = nclosure;
2971 VXInteger outers = nclosure->_noutervalues;
2972 for (VXInteger i = 0; i < outers; i++)
2974 _stack.values()[newbase+nargs+i] = nclosure->_outervalues[i];
2976 if(nclosure->_env)
2978 _stack.values()[newbase] = nclosure->_env->_obj;
2980 _nnativecalls++;
2981 VXInteger ret = (nclosure->_function)(this);
2982 _nnativecalls--;
2983 suspend = false;
2984 if (ret == VX_SUSPEND_FLAG)
2986 suspend = true;
2988 else if (ret < 0)
2990 LeaveFrame();
2991 ThrowError(_lasterror);
2992 return false;
2994 if(ret)
2996 retval = _stack.values()[_top-1];
2998 else
3000 retval.Null();
3002 //retval = ret ? _stack.values()[_top-1] : _null_;
3003 LeaveFrame();
3004 return true;
3009 bool VXState::Get(const VXObject &self,
3010 const VXObject &key,
3011 VXObject &dest,
3012 bool raw,
3013 VXInteger selfidx)
3015 switch(type(self))
3017 case VX_OT_TABLE:
3018 if(_table(self)->Get(key,dest))
3020 return true;
3022 break;
3023 case VX_OT_ARRAY:
3024 if(key.IsNumeric())
3026 if(_array(self)->Get(tointeger(key),dest))
3028 return true;
3030 Raise_IdxError(key, self, true);
3031 return false;
3033 break;
3034 case VX_OT_INSTANCE:
3035 if(_instance(self)->Get(key,dest))
3037 return true;
3039 break;
3040 case VX_OT_CLASS:
3041 if(_class(self)->Get(key,dest))
3043 return true;
3045 break;
3046 case VX_OT_STRING:
3047 if(key.IsNumeric())
3049 VXInteger n = tointeger(key);
3050 if(abs((int)n) < _string(self)->_len)
3052 if(n < 0)
3054 n = ((_string(self)->_len) - n);
3056 dest = VXInteger(_stringval(self)[n]);
3057 return true;
3059 Raise_IdxError(key, self, true);
3060 return false;
3062 break;
3063 default:
3064 break; //shut up compiler
3066 if(!raw)
3068 switch(FallBackGet(self,key,dest))
3070 case FALLBACK_OK:
3071 return true; //okie
3072 case FALLBACK_NO_MATCH:
3073 break; //keep falling back
3074 case FALLBACK_ERROR:
3075 return false; // the metamethod failed
3077 if(InvokeDefaultDelegate(self,key,dest))
3079 return true;
3082 if(selfidx == 0)
3084 if(_table(_roottable)->Get(key,dest))
3086 return true;
3089 Raise_IdxError(key, self);
3090 return false;
3093 bool VXState::InvokeDefaultDelegate(const VXObject &self,
3094 const VXObject &key,
3095 VXObject &dest)
3097 VXTableObj *ddel = NULL;
3098 switch(type(self))
3100 case VX_OT_CLASS:
3101 ddel = _class_ddel;
3102 break;
3103 case VX_OT_TABLE:
3104 ddel = _table_ddel;
3105 break;
3106 case VX_OT_ARRAY:
3107 ddel = _array_ddel;
3108 break;
3109 case VX_OT_STRING:
3110 ddel = _string_ddel;
3111 break;
3112 case VX_OT_INSTANCE:
3113 ddel = _instance_ddel;
3114 break;
3115 case VX_OT_INTEGER:
3116 case VX_OT_FLOAT:
3117 case VX_OT_BOOL:
3118 ddel = _number_ddel;
3119 break;
3120 case VX_OT_GENERATOR:
3121 ddel = _generator_ddel;
3122 break;
3123 case VX_OT_CLOSURE:
3124 case VX_OT_NATIVECLOSURE:
3125 ddel = _closure_ddel;
3126 break;
3127 case VX_OT_THREAD:
3128 ddel = _thread_ddel;
3129 break;
3130 case VX_OT_WEAKREF:
3131 ddel = _weakref_ddel;
3132 break;
3133 default:
3134 return false;
3136 return ddel->Get(key,dest);
3140 VXInteger VXState::FallBackGet(const VXObject &self,
3141 const VXObject &key,
3142 VXObject &dest)
3144 switch(type(self))
3146 case VX_OT_TABLE:
3147 case VX_OT_USERDATA:
3148 //delegation
3149 if(_delegable(self)->_delegate)
3151 if(Get(VXObject(_delegable(self)->_delegate),
3152 key,dest,false,DONT_FALL_BACK))
3154 return FALLBACK_OK;
3157 else
3159 return FALLBACK_NO_MATCH;
3161 //go through
3162 case VX_OT_INSTANCE:
3164 VXObject closure;
3165 if(_delegable(self)->GetMetaMethod(this, VX_MT_GET, closure))
3167 Push(self);
3168 Push(key);
3169 _nmetamethodscall++;
3170 AutoDec ad(&_nmetamethodscall);
3171 if(Call(closure, 2, _top - 2, dest, false))
3173 Pop(2);
3174 return FALLBACK_OK;
3176 else
3178 //NULL means "clean failure" (not found)
3179 if(type(_lasterror) != VX_OT_NULL)
3181 //error
3182 Pop(2);
3183 return FALLBACK_ERROR;
3188 break;
3189 default:
3190 break;//shutup GCC 4.x
3192 // no metamethod or no fallback type
3193 return FALLBACK_NO_MATCH;
3196 bool VXState::Set(const VXObject &self,
3197 const VXObject &key,
3198 const VXObject &val,
3199 VXInteger selfidx)
3201 switch(type(self))
3203 case VX_OT_TABLE:
3204 if(_table(self)->Set(key,val))
3206 return true;
3208 break;
3209 case VX_OT_INSTANCE:
3210 if(_instance(self)->Set(key,val))
3212 return true;
3214 break;
3215 case VX_OT_ARRAY:
3216 if(!key.IsNumeric())
3218 ThrowError("cannot index %s with type %s",
3219 GetTypeName(self), GetTypeName(key));
3220 return false;
3222 if(!_array(self)->Set(tointeger(key), val))
3224 Raise_IdxError(key, self);
3225 return false;
3227 return true;
3228 default:
3229 ThrowError("type '%s' does not support index assignment", GetTypeName(self));
3230 return false;
3232 switch(FallBackSet(self,key,val))
3234 case FALLBACK_OK:
3235 return true; //okie
3236 case FALLBACK_NO_MATCH:
3237 break; //keep falling back
3238 case FALLBACK_ERROR:
3239 return false; // the metamethod failed
3241 if(selfidx == 0)
3243 if(_table(_roottable)->Set(key,val))
3245 return true;
3248 Raise_IdxError(key, self);
3249 return false;
3252 VXInteger VXState::FallBackSet(const VXObject &self,
3253 const VXObject &key,
3254 const VXObject &val)
3256 switch(type(self))
3258 case VX_OT_TABLE:
3259 if(_table(self)->_delegate)
3261 if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK))
3263 return FALLBACK_OK;
3266 //keps on going
3267 case VX_OT_INSTANCE:
3268 case VX_OT_USERDATA:
3270 VXObject closure;
3271 VXObject t;
3272 if(_delegable(self)->GetMetaMethod(this, VX_MT_SET, closure))
3274 Push(self);
3275 Push(key);
3276 Push(val);
3277 _nmetamethodscall++;
3278 AutoDec ad(&_nmetamethodscall);
3279 if(Call(closure, 3, _top - 3, t, false))
3281 Pop(3);
3282 return FALLBACK_OK;
3284 else
3286 //NULL means "clean failure" (not found)
3287 if(type(_lasterror) != VX_OT_NULL)
3289 //error
3290 Pop(3);
3291 return FALLBACK_ERROR;
3296 break;
3297 default:
3298 break;//shutup GCC 4.x
3300 // no metamethod or no fallback type
3301 return FALLBACK_NO_MATCH;
3304 bool VXState::Clone(const VXObject& self,
3305 VXObject &target)
3307 VXObject temp_reg;
3308 VXObject newobj;
3309 switch(type(self))
3311 case VX_OT_TABLE:
3312 newobj = _table(self)->Clone();
3313 goto cloned_mt;
3314 case VX_OT_INSTANCE:
3316 newobj = _instance(self)->Clone(_ss(this));
3317 cloned_mt:
3318 VXObject closure;
3319 if(_delegable(newobj)->_delegate &&
3320 _delegable(newobj)->GetMetaMethod(this,VX_MT_CLONED,closure))
3322 Push(newobj);
3323 Push(self);
3324 if(!CallMetaMethod(this, closure,VX_MT_CLONED,2,temp_reg))
3326 return false;
3330 target = newobj;
3331 return true;
3332 case VX_OT_ARRAY:
3333 target = _array(self)->Clone();
3334 return true;
3335 default:
3336 ThrowError("cannot clone a '%s'", GetTypeName(self));
3337 return false;
3341 bool VXState::NewSlot(const VXObject &self,
3342 const VXObject &key,
3343 const VXObject &val,
3344 bool bstatic)
3346 if(type(key) == VX_OT_NULL)
3348 ThrowError("null cannot be used as index");
3349 return false;
3351 switch(type(self))
3353 case VX_OT_TABLE:
3355 bool rawcall = true;
3356 if(_table(self)->_delegate)
3358 VXObject res;
3359 if(!_table(self)->Get(key,res))
3361 VXObject closure;
3362 if(_delegable(self)->_delegate &&
3363 _delegable(self)->GetMetaMethod(this,VX_MT_NEWSLOT,closure))
3365 Push(self);
3366 Push(key);
3367 Push(val);
3368 if(!CallMetaMethod(this, closure,VX_MT_NEWSLOT,3,res))
3370 return false;
3372 rawcall = false;
3374 else
3376 rawcall = true;
3380 if(rawcall)
3382 _table(self)->NewSlot(key,val); //cannot fail
3384 break;
3386 case VX_OT_INSTANCE:
3388 VXObject res;
3389 VXObject closure;
3390 if(_delegable(self)->_delegate &&
3391 _delegable(self)->GetMetaMethod(this, VX_MT_NEWSLOT, closure))
3393 Push(self);
3394 Push(key);
3395 Push(val);
3396 if(!CallMetaMethod(this, closure, VX_MT_NEWSLOT, 3,res))
3398 return false;
3400 break;
3402 //ThrowError("class instances do not support the new slot operator");
3403 ThrowError("cannot create slots in class instances; use 'local' instead!");
3404 return false;
3405 break;
3407 case VX_OT_CLASS:
3408 if(!_class(self)->NewSlot(Shared(), key, val, bstatic))
3410 if(_class(self)->_locked)
3412 ThrowError("trying to modify a class that has already been instantiated");
3413 return false;
3415 else
3417 VXObject oval = PrintObjVal(key);
3418 ThrowError("property '%s' already exists",_stringval(oval));
3419 return false;
3422 break;
3423 default:
3424 ThrowError("indexing %s with %s", GetTypeName(self),GetTypeName(key));
3425 return false;
3426 break;
3428 return true;
3433 bool VXState::DeleteSlot(const VXObject &self,
3434 const VXObject &key,
3435 VXObject &res)
3437 switch(type(self))
3439 case VX_OT_TABLE:
3440 case VX_OT_INSTANCE:
3441 case VX_OT_USERDATA:
3443 VXObject t;
3444 //bool handled = false;
3445 VXObject closure;
3446 if(_delegable(self)->_delegate &&
3447 _delegable(self)->GetMetaMethod(this,VX_MT_DELSLOT,closure))
3449 Push(self);
3450 Push(key);
3451 return CallMetaMethod(this, closure,VX_MT_DELSLOT,2,res);
3453 else
3455 if(type(self) == VX_OT_TABLE)
3457 if(_table(self)->Get(key,t))
3459 _table(self)->Remove(key);
3461 else
3463 Raise_IdxError((VXRawObj &)key, self);
3464 return false;
3467 else
3469 ThrowError("cannot delete a slot from %s",GetTypeName(self));
3470 return false;
3473 res = t;
3475 break;
3476 default:
3477 ThrowError("attempt to delete a slot from a %s",GetTypeName(self));
3478 return false;
3480 return true;
3483 bool VXState::Call(VXObject &closure,
3484 VXInteger nparams,
3485 VXInteger stackbase,
3486 VXObject &outres,
3487 bool raiseerror)
3489 switch(type(closure))
3491 case VX_OT_CLOSURE:
3492 return Execute(closure, nparams, stackbase, outres, raiseerror);
3493 break;
3494 case VX_OT_NATIVECLOSURE:
3496 bool suspend;
3497 return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
3499 break;
3500 case VX_OT_CLASS:
3502 VXObject constr;
3503 VXObject temp;
3504 CreateClassInstance(_class(closure),outres,constr);
3505 if(type(constr) != VX_OT_NULL)
3507 _stack[stackbase] = outres;
3508 return Call(constr,nparams,stackbase,temp,raiseerror);
3510 return true;
3512 break;
3513 default:
3514 // populate LastError() with a meaningful message
3515 ThrowError("Call(): not a closure (type: %s)", closure.TypeString());
3516 return false;
3518 return true;
3522 bool VXState::EnterFrame(VXInteger newbase, VXInteger newtop, bool tailcall)
3524 if( !tailcall )
3526 if( _callsstacksize == _alloccallsstacksize )
3528 GrowCallStack();
3530 ci = &_callsstack[_callsstacksize++];
3531 ci->_prevstkbase = (VXInt32)(newbase - _stackbase);
3532 ci->_prevtop = (VXInt32)(_top - _stackbase);
3533 ci->_etraps = 0;
3534 ci->_ncalls = 1;
3535 ci->_generator = NULL;
3536 ci->_root = false;
3538 else
3540 ci->_ncalls++;
3542 _stackbase = newbase;
3543 _top = newtop;
3544 if(newtop + MIN_STACK_OVERHEAD > (VXInteger)_stack.size())
3546 if(_nmetamethodscall)
3548 ThrowError("stack overflow, cannot resize stack while in a metamethod");
3549 return false;
3551 _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2));
3552 RelocateOuters(this);
3554 return true;
3557 void VXState::LeaveFrame()
3559 VXInteger last_top = _top;
3560 VXInteger last_stackbase = _stackbase;
3561 VXInteger css = --_callsstacksize;
3562 /* First clean out the call stack frame */
3563 ci->_closure.Null();
3564 _stackbase -= ci->_prevstkbase;
3565 _top = _stackbase + ci->_prevtop;
3566 ci = (css) ? &_callsstack[css-1] : NULL;
3567 if(_openouters)
3569 CloseOuters(this, &(_stack.values()[last_stackbase]));
3571 while (last_top >= _top)
3573 _stack.values()[last_top--].Null();
3577 void VXState::Remove(VXInteger n)
3579 n = (n >= 0)?n + _stackbase - 1:_top + n;
3580 for(VXInteger i = n; i < _top; i++)
3582 _stack[i] = _stack[i+1];
3584 _stack[_top].Null();
3585 _top--;
3588 void VXState::Pop()
3590 _stack[--_top].Null();
3593 void VXState::Pop(VXInteger n)
3595 for(VXInteger i = 0; i < n; i++)
3597 _stack[--_top].Null();
3601 void VXState::PushNull()
3603 _stack[_top++].Null();
3606 void VXState::Push(const VXObject &o)
3608 _stack[_top++] = o;
3611 VXObject& VXState::Top()
3613 return _stack[_top-1];
3616 VXObject& VXState::PopGet()
3618 return _stack[--_top];
3621 VXObject& VXState::GetUp(VXInteger n)
3623 return _stack[_top+n];
3626 VXObject& VXState::GetAt(VXInteger n)
3628 return _stack[n];