5 #include "pcheader.hpp"
8 #include "funcproto.hpp"
12 #include "userdata.hpp"
15 #include "compiler.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) \
30 VXInteger tmask = type(o1)|type(o2); \
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;\
40 #define _ARITH_NOZERO(op,trg,o1,o2,err) \
42 VXInteger tmask = type(o1)|type(o2); \
46 VXInteger i2 = _integer(o2); \
52 trg = _integer(o1) op i2; \
55 case (VX_OT_FLOAT|VX_OT_INTEGER): \
57 trg = tofloat(o1) op tofloat(o2); \
60 _GUARD(ARITH_OP(this, (#op)[0],trg,o1,o2)); \
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; }
74 #define FALLBACK_NO_MATCH 1
75 #define FALLBACK_ERROR 2
81 #define _GETSAFE_OBJ(v,idx,type,o) \
83 if(VX_FAILED(v->GetTypedArg(v,idx,type,&o))) \
90 #define _GETSAFE_OBJ_REF(v, idx, type, o) \
92 if(VX_FAILED(v->GetTypedArg(idx, type, o))) \
98 void vox_defaultprintfunc(VXState
* v
,const char *s
,...)
103 vfprintf(stdout
, s
, vl
);
107 void vox_defaulterrorfunc(VXState
* v
,const char *s
,...)
112 vfprintf(stderr
, s
, vl
);
118 template<typename Type
, typename ClosureType
>
119 Type
WrongNumberOfArguments(VXState
* vm
,
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
);
134 VXUnsignedInteger
TranslateIndex(const VXObject
&idx
)
141 return (VXUnsignedInteger
)_integer(idx
);
142 default: vox_assert(0); break;
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";
160 case VX_RT_NATIVECLOSURE
: return "function";
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";
174 const char *GetTypeName(const VXObject
&obj1
)
176 return IdType2Name(type(obj1
));
180 VXInteger
VXState::GetState()
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
)
196 if(!this->_suspended
)
198 return this->ThrowError("cannot resume a vm that is not running any code");
200 VXInteger target
= this->_suspended_target
;
206 this->GetAt(this->_stackbase
+ this->_suspended_target
) = this->GetUp(-1);
210 else if(target
!= -1)
212 this->GetAt(this->_stackbase
+ this->_suspended_target
).Null();
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
))
228 VXInteger
VXState::SetDelegate(VXObject
& self
, const VXObject
& mt
)
230 VXOType type
= self
.Type();
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
);
247 return vox_aux_invalidtype(this, type
);
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
);
262 return vox_aux_invalidtype(this, type
);
268 bool SafeWrite(VXState
* v
,
274 if(write(up
,dest
,size
) != size
)
276 v
->ThrowError("io error (write function failure)");
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");
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
)));
303 v
->ThrowError("invalid or corrupted closure stream");
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
)));
316 _CHECK_IO(SafeWrite(v
,write
,up
,&_string(o
)->_len
,sizeof(VXInteger
)));
317 _CHECK_IO(SafeWrite(v
,
319 VXUserPointer(o
.String()->Value()), o
.String()->Length()));
322 _CHECK_IO(SafeWrite(v
,write
,up
,&_integer(o
),sizeof(VXInteger
)));break;
324 _CHECK_IO(SafeWrite(v
,write
,up
,&_float(o
),sizeof(VXFloat
)));break;
328 v
->ThrowError("cannot serialize a %s",GetTypeName(o
));
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
;
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
);
352 _CHECK_IO(SafeRead(v
,read
,up
,&i
,sizeof(VXInteger
))); o
= i
; break;
357 _CHECK_IO(SafeRead(v
,read
,up
,&f
,sizeof(VXFloat
))); o
= f
; break;
363 v
->ThrowError("cannot serialize a %s",IdType2Name(t
));
371 char* VXState::ScratchPad(VXInteger size
)
373 return Shared()->GetScratchPad(size
);
376 void VXState::SetReleaseHook(VXInteger idx
, VXReleaseHook hook
)
380 VXObject
& ud
= StackGet(idx
);
384 _userdata(ud
)->_hook
= hook
;
387 _instance(ud
)->_hook
= hook
;
390 _class(ud
)->_hook
= hook
;
398 VXInteger
VXState::SetTypeTag(VXObject
& o
, VXUserPointer typetag
)
403 _userdata(o
)->_typetag
= typetag
;
406 _class(o
)->_typetag
= typetag
;
409 return ThrowError("invalid object type");
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
;
427 VXClassObj
*cl
= _instance(o
)->_class
;
430 if(cl
->_typetag
== typetag
)
436 return this->ThrowError("invalid type tag");
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
);
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();
475 this->Pop(top
- newtop
);
479 while(top
++ < newtop
)
486 VXInteger
VXState::GetTop()
488 return ((this->_top
) - (this->_stackbase
));
491 VXInteger
VXState::WriteClosure(VXWriteFunc w
, VXUserPointer up
)
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
))
508 VXInteger
VXState::WriteClosureToFile(const char *filename
)
510 FILE* file
= fopen(filename
, "wb+");
513 return ThrowError("Cannot open '%s' for writing: %s", filename
, strerror(errno
));
517 if(VX_SUCCEEDED(this->WriteClosure(file_write
, file
)))
524 return VX_ERROR
; //forward the error
527 VXInteger
VXState::BindEnv(VXObject
& o
, const VXObject
& env
, VXObject
& ret
)
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());
543 fclos
= o
.Closure()->Clone();
544 __ObjRelease(fclos
->_env
);
546 __ObjAddRef(fclos
->_env
);
547 if(_closure(o
)->_base
)
549 fclos
->_base
= o
.Closure()->_base
;
550 __ObjAddRef(fclos
->_base
);
554 else //then must be a native closure
556 nclos
= o
.NativeClosure()->Clone();
557 __ObjRelease(nclos
->_env
);
559 __ObjAddRef(nclos
->_env
);
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()
614 VXInteger
VXState::GetUserPointer(VXInteger idx
, VXUserPointer
*p
)
617 _GETSAFE_OBJ_REF(this, idx
, VX_OT_USERPOINTER
, o
);
618 (*p
) = _userpointerval(o
);
622 VXInteger
VXState::GetString(VXInteger idx
, const char** destination
, VXInteger
* len_dest
)
625 _GETSAFE_OBJ_REF(this, idx
, VX_OT_STRING
, objptr
);
626 *destination
= _stringval(objptr
);
629 *len_dest
= _stringlen(objptr
);
634 VXInteger
VXState::GetInteger(VXInteger idx
, VXInteger
* dest
)
636 VXObject
& o
= this->StackGet(idx
);
646 VXInteger
VXState::GetFloat(VXInteger idx
, VXFloat
* dest
)
648 VXObject
& o
= this->StackGet(idx
);
657 VXInteger
VXState::GetBool(VXInteger idx
, bool* dest
)
659 VXObject
& o
= this->StackGet(idx
);
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
;
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
);
686 "wrong argument type, expected '%s' got '%.50s'",
687 IdType2Name(expected_type
),
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);
708 //this->_atexit_functions.push_back(pt);
710 //VXInteger type = ob.Type();
711 //if(type == VX_RT_NATIVECLOSURE)
713 // pt = VXNativeClosureObj::Create(Shared(), ob.NativeClosure());
716 this->_atexit_functions
.push_back(ob
);
719 void VXState::Move(VXState
* destination
, VXState
* source
, const VXObject
& o
)
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
)
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
));
751 return v
->ThrowError("this is a no compiler build");
756 VXInteger
VXState::CompileBuffer(const char* source
, VXInteger size
,
757 const char* sourcename
, bool raiseerror
)
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
, ...)
771 va_start(arguments
, str_format
);
775 size_t initial_bufsize
= 1;
776 buffptr
= new char[initial_bufsize
+1];
777 needed
= 1 + vsnprintf(buffptr
, initial_bufsize
, str_format
, arguments
);
779 if(needed
> initial_bufsize
)
782 buffptr
= new char[needed
+1];
783 va_start(arguments
, str_format
);
784 realsize
= vsnprintf(buffptr
, needed
, str_format
, arguments
);
791 buffptr
[realsize
] = 0;
796 retvalue
= this->DoString(buffptr
, realsize
, "<buffer>", returns
, raise_error
);
806 VXInteger
VXState::DoString(const char* str
, VXInteger len
,
807 const char* bufname
, bool retval
, bool printerror
)
809 len
= (len
== -1) ? strlen(str
) : len
;
812 bufname
= "<buffer>";//DOSTRING_DEFAULTBUFFERNAME;
814 if(VX_FAILED(this->CompileBuffer(str
, len
, bufname
, printerror
)))
821 if(VX_FAILED(StackCall(1, retval
, printerror
)))
827 return ThrowError("call failed");
830 VXInteger
VXState::ReadClosure(VXReadFunc r
, VXUserPointer up
, VXObject
* dest
)
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
))
857 VXInteger
VXState::LoadFile(const char* filename
, bool printerror
,
858 bool* failed_to_open
, VXObject
* dest
)
861 FILE* file
= fopen(filename
, "rb");
865 VXLexReadFunc func
= _io_file_lexfeed_PLAIN
;
868 if(failed_to_open
!= NULL
)
870 (*failed_to_open
) = false;
872 ret
= fread(&us
,1,2,file
);
875 //probably an empty file
879 if(us
== VX_BYTECODE_STREAM_TAG
)
882 fseek(file
, 0, SEEK_SET
);
883 if(VX_SUCCEEDED((st
= this->ReadClosure(file_read
, file
, dest
))))
894 //gotta swap the next 2 lines on BIG endian machines
895 //UTF-16 little endian
897 func
= _io_file_lexfeed_UCS2_BE
;
902 func
= _io_file_lexfeed_UCS2_LE
;
907 if(fread(&uc
, 1, sizeof(uc
), file
) == 0)
910 return ThrowError("io error");
915 return ThrowError("Unrecognozed encoding");
917 func
= _io_file_lexfeed_PLAIN
;
922 fseek(file
, 0, SEEK_SET
);
925 if(VX_SUCCEEDED(DoCompile(this, func
,file
,filename
,printerror
, dest
)))
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
)
954 if(this->Call(closure
, params
, this->_top
-params
, res
, raiseerror
))
956 if(!this->_suspended
)
958 //pop closure and args
973 if(!this->_suspended
)
977 return this->ThrowError("call failed");
981 VXInteger
VXState::Repush(VXInteger idx
)
983 this->Push(this->StackGet(idx
));
987 VXInteger
VXState::StackCall(VXInteger params
, bool retval
, bool raiseerror
)
990 if(this->Call(this->GetUp(-(params
+1)), params
, this->_top
- params
, res
, raiseerror
))
992 if(!this->_suspended
)
994 //pop closure and args
1009 if(!this->_suspended
)
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
)))
1021 if(VX_SUCCEEDED(this->StackCall(1, retval
, printerror
)))
1023 this->Remove(retval
? -2 : -1);
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
;
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
)
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,
1060 (VXInteger
)(ci
._ip
-func
->_instructions
)-1, dest
);
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()
1089 this->PushLastError();
1090 if(VX_FAILED(this->GetString(-1, &result
, NULL
)))
1092 result
= "<unknown error>";
1097 void VXState::Mark(VXCollectable
**chain
)
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
);
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)));
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
;
1156 if(!CompileTypemask(res
, typemask
))
1158 return ThrowError("invalid typemask");
1160 nc
->_typecheck
.copy(res
);
1164 nc
->_typecheck
.resize(0);
1166 if(nparams
== VX_MATCHTYPEMASKSTRING
)
1168 nc
->_nparamscheck
= nc
->_typecheck
.size();
1174 void RegisterLib_IterReg(VXState
* self
, const VXRegFunction
* funcs
, VXTableObj
* dest
)
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());
1199 // otherwise, a separate table with each function of $funcs will be
1200 // created and newslot'd to the root table
1203 tb
= this->NewTable();
1205 RegisterLib_IterReg(this, funcs
, tb
);
1208 vox_assert(libname
!= NULL
);
1209 GetRootTable()->NewSlot(NewString(libname
), tb
);
1215 VXClassObj
* VXState::RegClass(const VXVector
<VXRegFunction
>& funcs
,
1217 VXUserPointer typetag
)
1219 VXUnsignedInteger i
;
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);
1232 cl
->_typetag
= typetag
;
1238 VXClassObj
* VXState::RegClass(const VXRegFunction
* funcs
,
1240 VXUserPointer typetag
)
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
)
1255 ret
= VXClassObj::Create(this->Shared(), baseclass
);
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();
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
)
1292 v
= (VXState
*)VX_MALLOC(sizeof(VXState
));
1293 new (v
) VXState(ss
);
1295 if(v
->Init(friendvm
, initialstacksize
))
1302 vox_delete(v
, VXState
);
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
, ...)
1327 vsprintf(ScratchPad((VXInteger
)strlen(s
)+(NUMBER_MAX_CHAR
*2)), s
, vl
);
1329 this->_lasterror
= VXStringObj::Create(_ss(this),ScratchPad(-1),-1);
1333 VXInteger
VXState::Irrecoverable_Error(const char* s
, ...)
1337 vsprintf(ScratchPad((VXInteger
)strlen(s
)+(NUMBER_MAX_CHAR
*2)), s
, vl
);
1339 fprintf(stderr
, "Irrecoverable Error: %s\n", ScratchPad(-1));
1341 return VX_ERROR
; // never reached
1345 VXStringObj
* VXState::PrintObjVal(const VXObject
&o
)
1352 sprintf(ScratchPad(NUMBER_MAX_CHAR
+1), _PRINT_INT_FMT
, _integer(o
));
1353 return VXStringObj::Create(_ss(this), ScratchPad(-1));
1356 sprintf(ScratchPad(NUMBER_MAX_CHAR
+1), "%.14g", _float(o
));
1357 return VXStringObj::Create(_ss(this), ScratchPad(-1));
1360 return VXStringObj::Create(_ss(this), GetTypeName(o
));
1364 VXInteger
VXState::Raise_IdxError(const VXObject
&o
,
1365 const VXObject
& origin
,
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())
1384 len
= origin
.String()->_len
;
1387 len
= origin
.Array()->Size();
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
)
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());
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
))
1425 StringCat(exptypes
,VXStringObj::Create(_ss(this), "|", -1), exptypes
);
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'",
1434 IdType2Name((VXOType
)type
),
1435 _stringval(exptypes
)
1440 VXSharedState
* VXState::Shared()
1442 return _sharedstate
;
1445 VXState
* VXState::Create(VXInteger stacksize
)
1449 vox_new(ss
, VXSharedState
);
1451 v
= (VXState
*)VX_MALLOC(sizeof(VXState
));
1452 new (v
) VXState(ss
);
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
);
1465 vox_delete(v
, VXState
);
1471 void VXState::Destroy(VXState
* vm
)
1473 VXUnsignedInteger i
;
1474 VXSharedState
* ss
= _ss(vm
);
1475 for(i
=0; i
<(vm
->_atexit_functions
.size()); i
++)
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
)
1492 _suspended_target
= -1;
1493 _suspended_root
= false;
1494 _suspended_traps
= -1;
1497 _nmetamethodscall
= 0;
1499 _errorhandler
.Null();
1501 _debughook_native
= NULL
;
1502 _debughook_closure
.Null();
1506 ADD_TO_CHAIN(&_ss(this)->_gc_chain
,this);
1509 void VXState::Finalize()
1513 CloseOuters(this, &_stack
.values()[0]);
1517 _errorhandler
.Null();
1519 _debughook_native
= NULL
;
1520 _debughook_closure
.Null();
1522 _callstackdata
.resize(0);
1523 VXInteger size
=_stack
.size();
1524 for(VXInteger i
=0;i
<size
;i
++)
1533 REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain
,this);
1539 bool VXState::ObjCmp(const VXObject
&o1
,
1544 VXOType t1
= type(o1
);
1545 VXOType t2
= type(o2
);
1548 if(_rawval(o1
) == _rawval(o2
))
1555 _RET_SUCCEED(strcmp(_stringval(o1
), _stringval(o2
)));
1557 _RET_SUCCEED(_integer(o1
)-_integer(o2
));
1559 _RET_SUCCEED((_float(o1
)<_float(o2
))?-1:1);
1561 case VX_OT_USERDATA
:
1562 case VX_OT_INSTANCE
:
1563 if(_delegable(o1
)->_delegate
)
1566 if(_delegable(o1
)->GetMetaMethod(this, VX_MT_CMP
, closure
))
1569 if(!CallMetaMethod(this, closure
,VX_MT_CMP
,2,res
))
1576 //continues through (no break needed)
1578 _RET_SUCCEED( _userpointerval(o1
) < _userpointerval(o2
)?-1:1 );
1580 if(type(res
)!=VX_OT_INTEGER
)
1582 Raise_CompareError(o1
,o2
);
1585 _RET_SUCCEED(_integer(res
));
1590 if(o1
.IsNumeric() && o2
.IsNumeric())
1592 if((t1
==VX_OT_INTEGER
) && (t2
==VX_OT_FLOAT
))
1594 if(_integer(o1
) == _float(o2
) )
1598 else if(_integer(o1
)<_float(o2
))
1606 if(_float(o1
)==_integer(o2
))
1610 else if(_float(o1
) < _integer(o2
))
1617 else if(t1
==VX_OT_NULL
)
1621 else if(t2
==VX_OT_NULL
)
1627 Raise_CompareError(o1
,o2
);
1632 _RET_SUCCEED(0); //cannot happen
1636 bool VXState::ToString(const VXObject
&o
, VXObject
&res
)
1644 sprintf(ScratchPad(NUMBER_MAX_CHAR
+1),"%g",_float(o
));
1647 sprintf(ScratchPad(NUMBER_MAX_CHAR
+1),_PRINT_INT_FMT
,_integer(o
));
1650 sprintf(ScratchPad(6),_integer(o
)?"true":"false");
1653 case VX_OT_USERDATA
:
1654 case VX_OT_INSTANCE
:
1655 if(_delegable(o
)->_delegate
)
1658 if(_delegable(o
)->GetMetaMethod(this, VX_MT_TOSTRING
, closure
))
1661 if(CallMetaMethod(this, closure
,VX_MT_TOSTRING
,1,res
))
1663 if(type(res
) == VX_OT_STRING
)
1675 if(type(o
) != VX_OT_NULL
)
1677 sprintf(ScratchPad(sizeof(void*)+60),
1679 GetTypeName(o
),(void*)_rawval(o
));
1683 sprintf(ScratchPad(8), "<null>");
1686 //res = VXStringObj::Create(_ss(this), ScratchPad(-1));
1687 res
= NewString(ScratchPad(-1));
1692 bool VXState::StringCat(const VXObject
&str
,
1693 const VXObject
&obj
,
1697 if(!ToString(str
, a
))
1701 if(!ToString(obj
, b
))
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
);
1713 bool VXState::TypeOf(const VXObject
&obj1
,
1716 if(is_delegable(obj1
) && _delegable(obj1
)->_delegate
)
1719 if(_delegable(obj1
)->GetMetaMethod(this, VX_MT_TYPEOF
, closure
))
1722 return CallMetaMethod(this, closure
,VX_MT_TYPEOF
,1,dest
);
1725 dest
= VXStringObj::Create(_ss(this),GetTypeName(obj1
));
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];
1740 _roottable
= NewTable();
1744 _roottable
= friendvm
->_roottable
;
1745 _errorhandler
= friendvm
->_errorhandler
;
1746 _debughook
= friendvm
->_debughook
;
1747 _debughook_native
= friendvm
->_debughook_native
;
1748 _debughook_closure
= friendvm
->_debughook_closure
;
1755 bool VXState::StartCall(VXForeignClosureObj
*closure
,
1758 VXInteger stackbase
,
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
)
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();
1787 _stack
.values()[stackbase
+paramssize
] = arr
;
1789 else if (paramssize
!= nargs
)
1791 VXInteger ndef
= func
->_ndefaultparams
;
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
];
1802 return WrongNumberOfArguments(this, false, false, func
);
1807 _stack
.values()[stackbase
] = closure
->_env
->_obj
;
1809 if(!EnterFrame(stackbase
, newtop
, tailcall
))
1813 ci
->_closure
= closure
;
1814 ci
->_literals
= func
->_literals
;
1815 ci
->_ip
= func
->_instructions
;
1816 ci
->_target
= (VXInt32
)target
;
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
))
1828 Return(this, 1, target
, temp
);
1836 VXInteger
VXState::RawGetStack(VXInteger idx
)
1838 VXObject
& self
= StackGet(idx
);
1842 if(_table(self
)->Get(GetUp(-1), GetUp(-1)))
1846 if(_class(self
)->Get(GetUp(-1), GetUp(-1)))
1849 case VX_OT_INSTANCE
:
1850 if(_instance(self
)->Get(GetUp(-1), GetUp(-1)))
1855 VXObject
& key
= GetUp(-1);
1858 if(_array(self
)->Get(tointeger(key
), GetUp(-1)))
1866 return ThrowError("invalid index type for an array");
1872 return ThrowError("rawget works only on array/table/instance and class");
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");
1888 _table(self
)->NewSlot(GetUp(-2), GetUp(-1));
1893 _class(self
)->NewSlot(Shared(), GetUp(-2), GetUp(-1),false);
1897 case VX_OT_INSTANCE
:
1898 if(_instance(self
)->Set(GetUp(-2), GetUp(-1)))
1905 if(Set(self
, GetUp(-2), GetUp(-1),false))
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
);
1936 return _string(o
)->_len
;
1938 return _table(o
)->CountUsed();
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
;
1946 return _class(o
)->_udsize
;
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
)
1966 _array(o
)->Resize(0);
1969 return this->ThrowError("clear only works on table and array");
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
;
1987 memset(si
, 0, sizeof(VXStackInfos
));
1988 VXState::CallInfo
&ci
= this->_callsstack
[cssize
-level
-1];
1989 switch(type(ci
._closure
))
1993 VXFuncProtoObj
*func
= _closure(ci
._closure
)->_function
;
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
);
2006 case VX_OT_NATIVECLOSURE
:
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
);
2026 VXPrintFunction
VXState::GetErrorFunc()
2028 return Shared()->_errorfunc
;
2031 VXInteger
VXState::Suspend()
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
,
2052 if(type(o1
) == type(o2
))
2054 res
= (_rawval(o1
) == _rawval(o2
));
2058 if(o1
.IsNumeric() && o2
.IsNumeric())
2060 res
= (tofloat(o1
) == tofloat(o2
));
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
2081 bool VXState::Execute(VXObject
&closure
,
2083 VXInteger stackbase
,
2088 if ((_nnativecalls
+ 1) > MAX_NATIVE_CALLS
)
2090 ThrowError("native stack overflow");
2094 AutoDec
ad(&_nnativecalls
);
2095 VXInteger traps
= 0;
2096 CallInfo
*prevci
= ci
;
2102 if(!StartCall(_closure(temp_reg
),
2104 nargs
, stackbase
, false))
2106 // call the handler if there are no calls in the
2107 // stack, if not relies on the previous node
2110 CallErrorHandler(_lasterror
);
2116 outres
= STK(_top
-nargs
);
2122 case ET_RESUME_GENERATOR
:
2123 _generator(closure
)->Resume(this, outres
);
2125 traps
+= ci
->_etraps
;
2128 case ET_RESUME_THROW_VM
:
2129 traps
= _suspended_traps
;
2130 ci
->_root
= _suspended_root
;
2132 if(et
== ET_RESUME_THROW_VM
)
2144 const VXInstruction
&_i_
= *ci
->_ip
++;
2150 CallDebugHook('l',arg1
);
2155 TARGET
= ci
->_literals
[arg1
];
2159 TARGET
= (VXInteger
)arg1
;
2163 TARGET
= *((VXFloat
*)&arg1
);
2167 TARGET
= ci
->_literals
[arg1
];
2168 STK(arg2
) = ci
->_literals
[arg3
];
2174 VXObject
&t
= STK(arg1
);
2175 if (type(t
) == VX_OT_CLOSURE
2176 && (!_closure(t
)->_function
->_bgenerator
))
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));
2195 VXObject clo
= STK(arg1
);
2199 _GUARD(StartCall(_closure(clo
),
2201 _stackbase
+arg2
, false));
2203 case VX_OT_NATIVECLOSURE
:
2207 _nativeclosure(clo
),
2208 arg3
, _stackbase
+arg2
,
2213 _suspended_target
= sarg0
;
2214 _suspended_root
= ci
->_root
;
2215 _suspended_traps
= traps
;
2229 _GUARD(CreateClassInstance(
2230 _class(clo
),inst
,clo
));
2238 stkbase
= _stackbase
+arg2
;
2239 _stack
.values()[stkbase
] = inst
;
2241 _closure(clo
), -1, arg3
,
2244 case VX_OT_NATIVECLOSURE
:
2246 stkbase
= _stackbase
+arg2
;
2247 _stack
.values()[stkbase
] = inst
;
2250 _nativeclosure(clo
), arg3
,
2251 stkbase
, clo
, suspend
));
2256 break; //shutup GCC 4.x
2264 case VX_OT_USERDATA
:
2265 case VX_OT_INSTANCE
:
2268 if(_delegable(clo
)->_delegate
&&
2269 _delegable(clo
)->GetMetaMethod(this,VX_MT_CALL
,closure
))
2272 for (VXInteger i
=0; i
<arg3
; i
++)
2274 Push(STK(arg2
+ i
));
2276 if(!CallMetaMethod(this, closure
, VX_MT_CALL
, arg3
+1, clo
))
2288 ThrowError("attempt to call '%s'",
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
))
2307 _Swap(TARGET
,temp_reg
);//TARGET = temp_reg;
2312 if (!Get(STK(arg2
), ci
->_literals
[arg1
],
2313 temp_reg
, false,arg2
))
2317 _Swap(TARGET
,temp_reg
);//TARGET = temp_reg;
2325 _GUARD(NewSlot(STK(arg1
), STK(arg2
),
2334 _GUARD(DeleteSlot(STK(arg1
), STK(arg2
), TARGET
));
2338 if (!Set(STK(arg1
), STK(arg2
), STK(arg3
),arg1
))
2349 if (!Get(STK(arg1
), STK(arg2
), temp_reg
, false,arg1
))
2353 _Swap(TARGET
,temp_reg
);//TARGET = temp_reg;
2359 if(!IsEqual(STK(arg2
),COND_LITERAL
,res
))
2363 TARGET
= res
? true : false;
2370 if(!IsEqual(STK(arg2
),COND_LITERAL
,res
))
2374 TARGET
= (!res
) ? true : false;
2379 _ARITH_(+,TARGET
,STK(arg2
),STK(arg1
));
2383 _ARITH_(-,TARGET
,STK(arg2
),STK(arg1
));
2387 _ARITH_(*,TARGET
,STK(arg2
),STK(arg1
));
2391 _ARITH_NOZERO(/,TARGET
,STK(arg2
),
2392 STK(arg1
), "division by zero");
2396 ARITH_OP(this, '%',TARGET
,STK(arg2
),STK(arg1
));
2400 _GUARD(BW_OP(this, arg3
,TARGET
,STK(arg2
),STK(arg1
)));
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
);
2419 for(VXInt32 n
=0; n
< arg1
; n
++)
2427 TARGET
= _roottable
;
2431 TARGET
= arg1
?true:false;
2435 STK(arg0
) = STK(arg1
);
2436 STK(arg2
) = STK(arg3
);
2444 _GUARD(CMP_OP(this, (CmpOP
)arg3
,STK(arg2
),
2445 STK(arg0
),temp_reg
));
2446 if(IsFalse(temp_reg
))
2453 if(IsFalse(STK(arg0
)))
2461 VXForeignClosureObj
*cur_cls
= _closure(ci
->_closure
);
2462 VXOuterObj
*otr
= _outer(cur_cls
->_outervalues
[arg1
]);
2463 TARGET
= *(otr
->_valptr
);
2469 VXForeignClosureObj
*cur_cls
= _closure(ci
->_closure
);
2470 VXOuterObj
*otr
= _outer(cur_cls
->_outervalues
[arg1
]);
2471 *(otr
->_valptr
) = STK(arg2
);
2483 TARGET
= VXTableObj::Create(_ss(this), arg1
);
2486 TARGET
= VXArrayObj::Create(_ss(this), 0);
2487 _array(TARGET
)->Reserve(arg1
);
2491 _GUARD(CLASS_OP(this, TARGET
,arg1
,arg2
));
2498 case _OP_APPENDARRAY
:
2508 val
= ci
->_literals
[arg1
];
2511 val
._type
= VX_OT_INTEGER
;
2512 val
._unVal
.nInteger
= (VXInteger
)arg1
;
2515 val
._type
= VX_OT_FLOAT
;
2516 val
._unVal
.fFloat
= *((VXFloat
*)&arg1
);
2519 val
._type
= VX_OT_BOOL
;
2520 val
._unVal
.nInteger
= arg1
;
2527 _array(STK(arg0
))->Append(val
);
2534 (((VXUnsignedInteger
)arg1
&0xFFFF0000)>>16);
2535 _GUARD(DerefInc(this, arg3
, TARGET
,
2536 STK(selfidx
), STK(arg2
),
2537 STK(arg1
&0x0000FFFF), false, selfidx
));
2544 _GUARD(DerefInc(this, '+',TARGET
, STK(arg1
),
2545 STK(arg2
), o
, false, arg1
));
2551 VXObject
&a
= STK(arg1
);
2552 if(type(a
) == VX_OT_INTEGER
)
2554 a
._unVal
.nInteger
= _integer(a
) + sarg3
;
2567 _GUARD(DerefInc(this, '+',TARGET
,
2568 STK(arg1
), STK(arg2
), o
, true, arg1
));
2574 VXObject
&a
= STK(arg1
);
2575 if(type(a
) == VX_OT_INTEGER
)
2578 a
._unVal
.nInteger
= _integer(a
) + sarg3
;
2583 _GUARD(PLOCAL_INC(this, '+',TARGET
, STK(arg1
), o
));
2589 _GUARD(CMP_OP(this, (CmpOP
)arg3
,
2590 STK(arg2
),STK(arg1
),TARGET
));
2595 Get(STK(arg1
), STK(arg2
),
2596 temp_reg
, true, DONT_FALL_BACK
)
2600 case _OP_INSTANCEOF
:
2601 if(type(STK(arg1
)) != VX_OT_CLASS
)
2604 "cannot apply instanceof between a %s and a %s",
2605 GetTypeName(STK(arg1
)),
2606 GetTypeName(STK(arg2
)));
2610 (type(STK(arg2
)) == VX_OT_INSTANCE
) ?
2611 (_instance(STK(arg2
))->InstanceOf(_class(STK(arg1
)))
2612 ? true : false) : false;
2616 if(IsFalse(STK(arg2
)))
2624 if(!IsFalse(STK(arg2
)))
2632 _GUARD(NEG_OP(this, TARGET
,STK(arg1
)));
2636 TARGET
= IsFalse(STK(arg1
));
2640 if(type(STK(arg1
)) == VX_OT_INTEGER
)
2642 VXInteger t
= _integer(STK(arg1
));
2643 TARGET
= VXInteger(~t
);
2647 "attempt to perform a bitwise op on a %s",
2648 GetTypeName(STK(arg1
)));
2653 VXForeignClosureObj
*c
= ci
->_closure
._unVal
.pClosure
;
2654 VXFuncProtoObj
*fp
= c
->_function
;
2655 if(!CLOSURE_OP(this, TARGET
,
2656 fp
->_functions
[arg1
]._unVal
.pFunctionProto
))
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
);
2676 "trying to yield a '%s',"
2677 "only genenerator can be yielded",
2678 GetTypeName(ci
->_generator
));
2681 if(Return(this, arg0
, arg1
, temp_reg
))
2683 vox_assert(traps
== 0);
2692 if(type(STK(arg1
)) != VX_OT_GENERATOR
)
2695 "trying to resume a '%s',"
2696 " only a genenerator can be resumed",
2697 GetTypeName(STK(arg1
)));
2700 _GUARD(_generator(STK(arg1
))->Resume(this, TARGET
));
2701 traps
+= ci
->_etraps
;
2707 _GUARD(FOREACH_OP(this, STK(arg0
),STK(arg2
),
2708 STK(arg2
+1),STK(arg2
+2),arg2
,
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);
2721 _GUARD(Clone(STK(arg1
), TARGET
));
2725 _GUARD(TypeOf(STK(arg1
), TARGET
));
2730 VXInstruction
*_iv
=
2731 _closure(ci
->_closure
)->_function
->_instructions
;
2732 _etraps
.push_back(VXExceptionTrap(
2734 &_iv
[(ci
->_ip
-_iv
)+arg1
], arg0
));
2742 for(VXInteger i
=0; i
<arg0
; i
++)
2744 _etraps
.pop_back(); traps
--;
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
)
2767 Push((arg0
&NEW_SLVX_OT_ATTRIBUTES_FLAG
)?
2768 STK(arg2
-1) : VXObject());
2771 if(Call(_class(STK(arg1
))->
2772 _metamethods
[VX_MT_NEWMEMBER
],
2773 nparams
, _top
- nparams
,
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));
2797 VXForeignClosureObj
*clo
= _closure(ci
->_closure
);
2800 TARGET
= clo
->_base
;
2812 CloseOuters(this, &(STK(arg1
)));
2821 VXObject currerror
= _lasterror
;
2822 VXInteger last_top
= _top
;
2823 if(_ss(this)->_notifyallexceptions
|| (!traps
&& raiseerror
))
2825 CallErrorHandler(currerror
);
2831 VXExceptionTrap
&et
= _etraps
.top();
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
++)
2854 ci
->_generator
->Kill();
2856 bool mustbreak
= ci
&& ci
->_root
;
2863 _lasterror
= currerror
;
2869 bool VXState::CreateClassInstance(VXClassObj
*theclass
,
2871 VXObject
&constructor
)
2873 inst
= theclass
->CreateInstance();
2874 if(!theclass
->GetConstructor(constructor
))
2881 void VXState::CallErrorHandler(VXObject
&error
)
2883 if(type(_errorhandler
) != VX_OT_NULL
)
2886 if(_errorhandler
.Type() == VX_OT_NATIVECLOSURE
)
2888 _errorhandler
.NativeClosure()->_nparamscheck
= 2;
2892 if(!Call(_errorhandler
, 2, _top
-2, out
, false))
2894 // the irony is killing me!
2895 Irrecoverable_Error("failed to call errorhandler!");
2902 void VXState::CallDebugHook(VXInteger type
,
2903 VXInteger forcedline
)
2905 VXFuncProtoObj
* func
;
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
);
2923 VXInteger nparams
=5;
2925 Push(VXInteger(type
));
2926 Push(func
->_sourcename
);
2927 Push(VXInteger(forcedline
?forcedline
:func
->GetLine(ci
->_ip
)));
2929 Call(_debughook_closure
,nparams
,_top
-nparams
,temp_reg
,false);
2935 bool VXState::CallNative(VXNativeClosureObj
*nclosure
,
2941 VXInteger nparamscheck
= nclosure
->_nparamscheck
;
2942 VXInteger newtop
= newbase
+ nargs
+ nclosure
->_noutervalues
;
2943 if(_nnativecalls
+ 1 > MAX_NATIVE_CALLS
)
2945 ThrowError("native stack overflow");
2948 if(nparamscheck
&& (((nparamscheck
> 0) && (nparamscheck
!= nargs
)) ||
2949 ((nparamscheck
< 0) && (nargs
< (-nparamscheck
)))))
2951 return WrongNumberOfArguments(this, false, true, nclosure
);
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
]));
2966 if(!EnterFrame(newbase
, newtop
, 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
];
2978 _stack
.values()[newbase
] = nclosure
->_env
->_obj
;
2981 VXInteger ret
= (nclosure
->_function
)(this);
2984 if (ret
== VX_SUSPEND_FLAG
)
2991 ThrowError(_lasterror
);
2996 retval
= _stack
.values()[_top
-1];
3002 //retval = ret ? _stack.values()[_top-1] : _null_;
3009 bool VXState::Get(const VXObject
&self
,
3010 const VXObject
&key
,
3018 if(_table(self
)->Get(key
,dest
))
3026 if(_array(self
)->Get(tointeger(key
),dest
))
3030 Raise_IdxError(key
, self
, true);
3034 case VX_OT_INSTANCE
:
3035 if(_instance(self
)->Get(key
,dest
))
3041 if(_class(self
)->Get(key
,dest
))
3049 VXInteger n
= tointeger(key
);
3050 if(abs((int)n
) < _string(self
)->_len
)
3054 n
= ((_string(self
)->_len
) - n
);
3056 dest
= VXInteger(_stringval(self
)[n
]);
3059 Raise_IdxError(key
, self
, true);
3064 break; //shut up compiler
3068 switch(FallBackGet(self
,key
,dest
))
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
))
3084 if(_table(_roottable
)->Get(key
,dest
))
3089 Raise_IdxError(key
, self
);
3093 bool VXState::InvokeDefaultDelegate(const VXObject
&self
,
3094 const VXObject
&key
,
3097 VXTableObj
*ddel
= NULL
;
3110 ddel
= _string_ddel
;
3112 case VX_OT_INSTANCE
:
3113 ddel
= _instance_ddel
;
3118 ddel
= _number_ddel
;
3120 case VX_OT_GENERATOR
:
3121 ddel
= _generator_ddel
;
3124 case VX_OT_NATIVECLOSURE
:
3125 ddel
= _closure_ddel
;
3128 ddel
= _thread_ddel
;
3131 ddel
= _weakref_ddel
;
3136 return ddel
->Get(key
,dest
);
3140 VXInteger
VXState::FallBackGet(const VXObject
&self
,
3141 const VXObject
&key
,
3147 case VX_OT_USERDATA
:
3149 if(_delegable(self
)->_delegate
)
3151 if(Get(VXObject(_delegable(self
)->_delegate
),
3152 key
,dest
,false,DONT_FALL_BACK
))
3159 return FALLBACK_NO_MATCH
;
3162 case VX_OT_INSTANCE
:
3165 if(_delegable(self
)->GetMetaMethod(this, VX_MT_GET
, closure
))
3169 _nmetamethodscall
++;
3170 AutoDec
ad(&_nmetamethodscall
);
3171 if(Call(closure
, 2, _top
- 2, dest
, false))
3178 //NULL means "clean failure" (not found)
3179 if(type(_lasterror
) != VX_OT_NULL
)
3183 return FALLBACK_ERROR
;
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
,
3204 if(_table(self
)->Set(key
,val
))
3209 case VX_OT_INSTANCE
:
3210 if(_instance(self
)->Set(key
,val
))
3216 if(!key
.IsNumeric())
3218 ThrowError("cannot index %s with type %s",
3219 GetTypeName(self
), GetTypeName(key
));
3222 if(!_array(self
)->Set(tointeger(key
), val
))
3224 Raise_IdxError(key
, self
);
3229 ThrowError("type '%s' does not support index assignment", GetTypeName(self
));
3232 switch(FallBackSet(self
,key
,val
))
3236 case FALLBACK_NO_MATCH
:
3237 break; //keep falling back
3238 case FALLBACK_ERROR
:
3239 return false; // the metamethod failed
3243 if(_table(_roottable
)->Set(key
,val
))
3248 Raise_IdxError(key
, self
);
3252 VXInteger
VXState::FallBackSet(const VXObject
&self
,
3253 const VXObject
&key
,
3254 const VXObject
&val
)
3259 if(_table(self
)->_delegate
)
3261 if(Set(_table(self
)->_delegate
,key
,val
,DONT_FALL_BACK
))
3267 case VX_OT_INSTANCE
:
3268 case VX_OT_USERDATA
:
3272 if(_delegable(self
)->GetMetaMethod(this, VX_MT_SET
, closure
))
3277 _nmetamethodscall
++;
3278 AutoDec
ad(&_nmetamethodscall
);
3279 if(Call(closure
, 3, _top
- 3, t
, false))
3286 //NULL means "clean failure" (not found)
3287 if(type(_lasterror
) != VX_OT_NULL
)
3291 return FALLBACK_ERROR
;
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
,
3312 newobj
= _table(self
)->Clone();
3314 case VX_OT_INSTANCE
:
3316 newobj
= _instance(self
)->Clone(_ss(this));
3319 if(_delegable(newobj
)->_delegate
&&
3320 _delegable(newobj
)->GetMetaMethod(this,VX_MT_CLONED
,closure
))
3324 if(!CallMetaMethod(this, closure
,VX_MT_CLONED
,2,temp_reg
))
3333 target
= _array(self
)->Clone();
3336 ThrowError("cannot clone a '%s'", GetTypeName(self
));
3341 bool VXState::NewSlot(const VXObject
&self
,
3342 const VXObject
&key
,
3343 const VXObject
&val
,
3346 if(type(key
) == VX_OT_NULL
)
3348 ThrowError("null cannot be used as index");
3355 bool rawcall
= true;
3356 if(_table(self
)->_delegate
)
3359 if(!_table(self
)->Get(key
,res
))
3362 if(_delegable(self
)->_delegate
&&
3363 _delegable(self
)->GetMetaMethod(this,VX_MT_NEWSLOT
,closure
))
3368 if(!CallMetaMethod(this, closure
,VX_MT_NEWSLOT
,3,res
))
3382 _table(self
)->NewSlot(key
,val
); //cannot fail
3386 case VX_OT_INSTANCE
:
3390 if(_delegable(self
)->_delegate
&&
3391 _delegable(self
)->GetMetaMethod(this, VX_MT_NEWSLOT
, closure
))
3396 if(!CallMetaMethod(this, closure
, VX_MT_NEWSLOT
, 3,res
))
3402 //ThrowError("class instances do not support the new slot operator");
3403 ThrowError("cannot create slots in class instances; use 'local' instead!");
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");
3417 VXObject oval
= PrintObjVal(key
);
3418 ThrowError("property '%s' already exists",_stringval(oval
));
3424 ThrowError("indexing %s with %s", GetTypeName(self
),GetTypeName(key
));
3433 bool VXState::DeleteSlot(const VXObject
&self
,
3434 const VXObject
&key
,
3440 case VX_OT_INSTANCE
:
3441 case VX_OT_USERDATA
:
3444 //bool handled = false;
3446 if(_delegable(self
)->_delegate
&&
3447 _delegable(self
)->GetMetaMethod(this,VX_MT_DELSLOT
,closure
))
3451 return CallMetaMethod(this, closure
,VX_MT_DELSLOT
,2,res
);
3455 if(type(self
) == VX_OT_TABLE
)
3457 if(_table(self
)->Get(key
,t
))
3459 _table(self
)->Remove(key
);
3463 Raise_IdxError((VXRawObj
&)key
, self
);
3469 ThrowError("cannot delete a slot from %s",GetTypeName(self
));
3477 ThrowError("attempt to delete a slot from a %s",GetTypeName(self
));
3483 bool VXState::Call(VXObject
&closure
,
3485 VXInteger stackbase
,
3489 switch(type(closure
))
3492 return Execute(closure
, nparams
, stackbase
, outres
, raiseerror
);
3494 case VX_OT_NATIVECLOSURE
:
3497 return CallNative(_nativeclosure(closure
), nparams
, stackbase
, outres
,suspend
);
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
);
3514 // populate LastError() with a meaningful message
3515 ThrowError("Call(): not a closure (type: %s)", closure
.TypeString());
3522 bool VXState::EnterFrame(VXInteger newbase
, VXInteger newtop
, bool tailcall
)
3526 if( _callsstacksize
== _alloccallsstacksize
)
3530 ci
= &_callsstack
[_callsstacksize
++];
3531 ci
->_prevstkbase
= (VXInt32
)(newbase
- _stackbase
);
3532 ci
->_prevtop
= (VXInt32
)(_top
- _stackbase
);
3535 ci
->_generator
= NULL
;
3542 _stackbase
= newbase
;
3544 if(newtop
+ MIN_STACK_OVERHEAD
> (VXInteger
)_stack
.size())
3546 if(_nmetamethodscall
)
3548 ThrowError("stack overflow, cannot resize stack while in a metamethod");
3551 _stack
.resize(_stack
.size() + (MIN_STACK_OVERHEAD
<< 2));
3552 RelocateOuters(this);
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
;
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();
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
)
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
)