Browse Source

Added new api to write bytecode as SquiLu code to make it easier to understand bytecode generation.
We can pass -s as option to squilu to have a squilu script bytecode representaion.

mingodad 13 years ago
parent
commit
409fe0966a
9 changed files with 266 additions and 11 deletions
  1. 1 0
      include/sqstdio.h
  2. 1 0
      include/squirrel.h
  3. 20 0
      sq/sq.c
  4. 12 0
      sqstdlib/sqstdio.cpp
  5. 15 1
      squirrel/sqapi.cpp
  6. 7 6
      squirrel/sqclosure.h
  7. 1 1
      squirrel/sqcompiler.cpp
  8. 2 1
      squirrel/sqfuncproto.h
  9. 207 2
      squirrel/sqobject.cpp

+ 1 - 0
include/sqstdio.h

@@ -42,6 +42,7 @@ SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file);
 SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
 SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
 SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
 SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
 SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
 SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
+SQUIRREL_API SQRESULT sqstd_writeclosuretofile_as_source(HSQUIRRELVM v,const SQChar *filename);
 
 
 SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
 SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
 
 

+ 1 - 0
include/squirrel.h

@@ -507,6 +507,7 @@ SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v);
 
 
 /*serialization*/
 /*serialization*/
 SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
 SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
+SQUIRREL_API SQRESULT sq_writeclosure_as_source(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
 SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
 SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
 
 
 /*mem allocation*/
 /*mem allocation*/

+ 20 - 0
sq/sq.c

@@ -91,6 +91,7 @@ int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
 {
 {
 	int i;
 	int i;
 	int compiles_only = 0;
 	int compiles_only = 0;
+	int compiles_as_source_only = 0;
 	//static SQChar temp[500];
 	//static SQChar temp[500];
 	//const SQChar *ret=NULL;
 	//const SQChar *ret=NULL;
 	char * output = NULL;
 	char * output = NULL;
@@ -113,6 +114,9 @@ int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
 				case 'c':
 				case 'c':
 					compiles_only = 1;
 					compiles_only = 1;
 					break;
 					break;
+				case 's':
+					compiles_as_source_only = 1;
+					break;
 				case 'o':
 				case 'o':
 					if(arg < argc) {
 					if(arg < argc) {
 						arg++;
 						arg++;
@@ -172,6 +176,22 @@ int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
 						return _DONE;
 						return _DONE;
 				}
 				}
 			}
 			}
+			else if(compiles_as_source_only) {
+				if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))){
+					const SQChar *outfile = _SC("out.nut");
+					if(output) {
+#ifdef SQUNICODE
+						int len = (int)(strlen(output)+1);
+						mbstowcs(sq_getscratchpad(v,len*sizeof(SQChar)),output,len);
+						outfile = sq_getscratchpad(v,-1);
+#else
+						outfile = output;
+#endif
+					}
+					if(SQ_SUCCEEDED(sqstd_writeclosuretofile_as_source(v,outfile)))
+						return _DONE;
+				}
+			}
 			else {
 			else {
 				//if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQFalse,SQTrue))) {
 				//if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQFalse,SQTrue))) {
 					//return _DONE;
 					//return _DONE;

+ 12 - 0
sqstdlib/sqstdio.cpp

@@ -370,6 +370,18 @@ SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
 	return SQ_ERROR; //forward the error
 	return SQ_ERROR; //forward the error
 }
 }
 
 
+SQRESULT sqstd_writeclosuretofile_as_source(HSQUIRRELVM v,const SQChar *filename)
+{
+	SQFILE file = sqstd_fopen(filename,_SC("wb+"));
+	if(!file) return sq_throwerror(v,_SC("cannot open the file"));
+	if(SQ_SUCCEEDED(sq_writeclosure_as_source(v,file_write,file))) {
+		sqstd_fclose(file);
+		return SQ_OK;
+	}
+	sqstd_fclose(file);
+	return SQ_ERROR; //forward the error
+}
+
 SQInteger _g_io_loadfile(HSQUIRRELVM v)
 SQInteger _g_io_loadfile(HSQUIRRELVM v)
 {
 {
 	const SQChar *filename;
 	const SQChar *filename;

+ 15 - 1
squirrel/sqapi.cpp

@@ -1407,7 +1407,7 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
 	_GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
 	_GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
 	unsigned short tag = SQ_BYTECODE_STREAM_TAG;
 	unsigned short tag = SQ_BYTECODE_STREAM_TAG;
 	if(_closure(*o)->_function->_noutervalues)
 	if(_closure(*o)->_function->_noutervalues)
-		return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));
+		return sq_throwerror(v,_SC("a closure with free valiables bound cannot be serialized"));
 	if(w(up,&tag,2) != 2)
 	if(w(up,&tag,2) != 2)
 		return sq_throwerror(v,_SC("io error"));
 		return sq_throwerror(v,_SC("io error"));
 	if(!_closure(*o)->Save(v,up,w))
 	if(!_closure(*o)->Save(v,up,w))
@@ -1415,6 +1415,20 @@ SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
 	return SQ_OK;
 	return SQ_OK;
 }
 }
 
 
+SQRESULT sq_writeclosure_as_source(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
+{
+	SQObjectPtr *o = NULL;
+	_GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
+	if(_closure(*o)->_function->_noutervalues)
+		return sq_throwerror(v,_SC("a closure with free valiables bound cannot be serialized"));
+    const SQChar decl[] = _SC("local bytecode = ");
+	if(w(up, (void*)decl, scstrlen(decl)) != scstrlen(decl))
+		return sq_throwerror(v,_SC("io error"));
+	if(!_closure(*o)->SaveAsSource(v,up,w))
+		return SQ_ERROR;
+	return SQ_OK;
+}
+
 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
 {
 {
 	SQObjectPtr closure;
 	SQObjectPtr closure;

+ 7 - 6
squirrel/sqclosure.h

@@ -31,7 +31,7 @@ public:
 		this->~SQClosure();
 		this->~SQClosure();
 		sq_vm_free(this,size);
 		sq_vm_free(this,size);
 	}
 	}
-	
+
 	SQClosure *Clone()
 	SQClosure *Clone()
 	{
 	{
 		SQFunctionProto *f = _function;
 		SQFunctionProto *f = _function;
@@ -43,8 +43,9 @@ public:
 		return ret;
 		return ret;
 	}
 	}
 	~SQClosure();
 	~SQClosure();
-	
+
 	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
 	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+	bool SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
 	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
 	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
 #ifndef NO_GARBAGE_COLLECTOR
 #ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable **chain);
 	void Mark(SQCollectable **chain);
@@ -83,7 +84,7 @@ public:
 		this->~SQOuter();
 		this->~SQOuter();
 		sq_vm_free(this,sizeof(SQOuter));
 		sq_vm_free(this,sizeof(SQOuter));
 	}
 	}
-	
+
 #ifndef NO_GARBAGE_COLLECTOR
 #ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable **chain);
 	void Mark(SQCollectable **chain);
 	void Finalize() { _value.Null(); }
 	void Finalize() { _value.Null(); }
@@ -97,7 +98,7 @@ public:
 };
 };
 
 
 //////////////////////////////////////////////
 //////////////////////////////////////////////
-struct SQGenerator : public CHAINABLE_OBJ 
+struct SQGenerator : public CHAINABLE_OBJ
 {
 {
 	enum SQGeneratorState{eRunning,eSuspended,eDead};
 	enum SQGeneratorState{eRunning,eSuspended,eDead};
 private:
 private:
@@ -119,7 +120,7 @@ public:
 	void Release(){
 	void Release(){
 		sq_delete(this,SQGenerator);
 		sq_delete(this,SQGenerator);
 	}
 	}
-	
+
 	bool Yield(SQVM *v,SQInteger target);
 	bool Yield(SQVM *v,SQInteger target);
 	bool Resume(SQVM *v,SQObjectPtr &dest);
 	bool Resume(SQVM *v,SQObjectPtr &dest);
 #ifndef NO_GARBAGE_COLLECTOR
 #ifndef NO_GARBAGE_COLLECTOR
@@ -173,7 +174,7 @@ public:
 		this->~SQNativeClosure();
 		this->~SQNativeClosure();
 		sq_free(this,size);
 		sq_free(this,size);
 	}
 	}
-	
+
 #ifndef NO_GARBAGE_COLLECTOR
 #ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable **chain);
 	void Mark(SQCollectable **chain);
 	void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }
 	void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }

+ 1 - 1
squirrel/sqcompiler.cpp

@@ -1633,7 +1633,7 @@ if(color == "yellow"){
 				if(_token == _SC('=')) {
 				if(_token == _SC('=')) {
 				    if(is_reference) Error(_SC("parameter passed by reference can't have default value"));
 				    if(is_reference) Error(_SC("parameter passed by reference can't have default value"));
 					Lex();
 					Lex();
-					if(_token == _SC('[') || _token == _SC('{')) Error(_SC("array/table default parameter not supported"));
+					if(_token == _SC('[') || _token == _SC('{')) Error(_SC("default parameter with array/table values not supported"));
 					Expression();
 					Expression();
 					funcstate->AddDefaultParam(_fs->TopTarget());
 					funcstate->AddDefaultParam(_fs->TopTarget());
 					defparams++;
 					defparams++;

+ 2 - 1
squirrel/sqfuncproto.h

@@ -130,7 +130,8 @@ public:
 
 
 	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
 	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
 	SQInteger GetLine(SQInstruction *curr);
 	SQInteger GetLine(SQInstruction *curr);
-	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+	bool SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
 	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
 	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
 #ifndef NO_GARBAGE_COLLECTOR
 #ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable **chain);
 	void Mark(SQCollectable **chain);

+ 207 - 2
squirrel/sqobject.cpp

@@ -269,6 +269,19 @@ bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer de
 	return true;
 	return true;
 }
 }
 
 
+bool SafeWriteFmt(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up, const SQChar *fmt, ...)
+{
+    if(fmt){
+        SQChar str[8192];
+        va_list vl;
+        va_start(vl, fmt);
+        SQInteger len = scvsnprintf(str, sizeof(str), fmt, vl);
+        va_end(vl);
+        return SafeWrite(v, write, up, str, len);
+    }
+	return false;
+}
+
 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
 bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
 {
 {
 	if(size && read(up,dest,size) != size) {
 	if(size && read(up,dest,size) != size) {
@@ -277,7 +290,7 @@ bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest
 	}
 	}
 	return true;
 	return true;
 }
 }
-
+
 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)
 bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)
 {
 {
 	return SafeWrite(v,write,up,&tag,sizeof(tag));
 	return SafeWrite(v,write,up,&tag,sizeof(tag));
@@ -294,6 +307,37 @@ bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger3
 	return true;
 	return true;
 }
 }
 
 
+bool WriteObjectAsCode(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o, bool withQuotes=true)
+{
+	SQChar buf[32];
+	SQInteger sz;
+	switch(type(o)){
+	case OT_STRING:{
+            const SQChar *d1 = withQuotes ? _SC("\"") : _SC("[==[");
+            const SQChar *d2 = withQuotes ? _SC("\"") : _SC("]==]");
+            _CHECK_IO(SafeWrite(v,write,up, (void*)d1, scstrlen(d1)));
+            _CHECK_IO(SafeWrite(v,write,up, _stringval(o),rsl(_string(o)->_len)));
+            _CHECK_IO(SafeWrite(v,write,up, (void*)d2, scstrlen(d2)));
+        }
+		break;
+	case OT_INTEGER:
+        sz = scsnprintf(buf, sizeof(buf), "%d", _integer(o));
+		_CHECK_IO(SafeWrite(v,write,up,buf,sz));break;
+	case OT_FLOAT:
+        sz = scsnprintf(buf, sizeof(buf), "%f", _float(o));
+		_CHECK_IO(SafeWrite(v,write,up,buf,sz));break;
+	case OT_NULL:{
+            const SQChar str[] = _SC("null");
+            _CHECK_IO(SafeWrite(v,write,up, (void*)str, scstrlen(str)));
+        }
+		break;
+	default:
+		v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
+		return false;
+	}
+	return true;
+}
+
 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
 bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
 {
 {
 	SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);
 	SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);
@@ -314,7 +358,7 @@ bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o
 		return false;
 		return false;
 	}
 	}
 	return true;
 	return true;
-}
+}
 
 
 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
 bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
 {
 {
@@ -358,6 +402,12 @@ bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
 	return true;
 	return true;
 }
 }
 
 
+bool SQClosure::SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+	_CHECK_IO(_function->SaveAsSource(v,up,write));
+	return true;
+}
+
 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 {
 {
 	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
 	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
@@ -445,6 +495,161 @@ bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
 	_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
 	_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
 	return true;
 	return true;
 }
 }
+
+bool SQFunctionProto::SaveAsSource(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+	SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
+	SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
+	SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
+	SQInteger ndefaultparams = _ndefaultparams;
+	SafeWriteFmt(v,write,up,"{\n");
+	SafeWriteFmt(v,write,up,"\tsource_name = \"%s\",\n", _stringval(_sourcename));
+	SafeWriteFmt(v,write,up,"\tfunction_name = \"%s\",\n", _stringval(_name));
+
+	SafeWriteFmt(v,write,up,"\tliterals = [\n");
+	for(i=0;i<nliterals;i++){
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/", i);
+		_CHECK_IO(WriteObjectAsCode(v,up,write,_literals[i], false));
+		SafeWriteFmt(v,write,up,",\n");
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\tparameters = [\n");
+	for(i=0;i<nparameters;i++){
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/", i);
+		_CHECK_IO(WriteObjectAsCode(v,up,write,_parameters[i]));
+		SafeWriteFmt(v,write,up,",\n");
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\toutervalues = [\n");
+	for(i=0;i<noutervalues;i++){
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/{type=%d,\n", i, _outervalues[i]._type);
+		SafeWriteFmt(v,write,up,"\t\tsrc=");
+		_CHECK_IO(WriteObjectAsCode(v,up,write,_outervalues[i]._src));
+		SafeWriteFmt(v,write,up,",\n");
+		SafeWriteFmt(v,write,up,"\t\tname=");
+		_CHECK_IO(WriteObjectAsCode(v,up,write,_outervalues[i]._name));
+		SafeWriteFmt(v,write,up,"},\n");
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\tlocalvarinfos = [\n");
+	for(i=0;i<nlocalvarinfos;i++){
+	    SQLocalVarInfo &lvi=_localvarinfos[i];
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/{name=", i);
+		_CHECK_IO(WriteObjectAsCode(v,up,write,lvi._name));
+		SafeWriteFmt(v,write,up,", pos=%d", lvi._pos);
+		SafeWriteFmt(v,write,up,", start_op=%d", lvi._start_op);
+		SafeWriteFmt(v,write,up,", end_op=%d", lvi._end_op);
+		SafeWriteFmt(v,write,up,", scope=%d", lvi._scope);
+		SafeWriteFmt(v,write,up,", type=%d},\n", lvi._type);
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\tlineinfos = [\n");
+	for(i=0;i<nlineinfos;i++){
+	    SQLineInfo &li=_lineinfos[i];
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/{line=%d, op=%d},\n", i, li._line, li._op);
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\tdefaultparams = [");
+	for(i=0;i<ndefaultparams;i++){
+		SafeWriteFmt(v,write,up,"%d,", _defaultparams[i]);
+	}
+    SafeWriteFmt(v,write,up,"],\n");
+
+	SafeWriteFmt(v,write,up,"\tinstructions = [\n");
+    SafeWriteFmt(v,write,up,"\t\t//[op_str, op, arg0, arg1, arg2, arg3],\n");
+	const SQChar *str_op;
+#define CASE_OP(v) case v: str_op = _SC(#v); break;
+	for(i=0;i<ninstructions;i++){
+	    SQInstruction &inst = _instructions[i];
+	    switch(inst.op){
+            CASE_OP(_OP_LINE)
+            CASE_OP(_OP_LOAD)
+            CASE_OP(_OP_LOADINT)
+            CASE_OP(_OP_LOADFLOAT)
+            CASE_OP(_OP_DLOAD)
+            CASE_OP(_OP_TAILCALL)
+            CASE_OP(_OP_CALL)
+            CASE_OP(_OP_PREPCALL)
+            CASE_OP(_OP_PREPCALLK)
+            CASE_OP(_OP_GETK)
+            CASE_OP(_OP_MOVE)
+            CASE_OP(_OP_NEWSLOT)
+            CASE_OP(_OP_DELETE)
+            CASE_OP(_OP_SET)
+            CASE_OP(_OP_GET)
+            CASE_OP(_OP_EQ)
+            CASE_OP(_OP_NE)
+            CASE_OP(_OP_ADD)
+            CASE_OP(_OP_SUB)
+            CASE_OP(_OP_MUL)
+            CASE_OP(_OP_DIV)
+            CASE_OP(_OP_MOD)
+            CASE_OP(_OP_BITW)
+            CASE_OP(_OP_RETURN)
+            CASE_OP(_OP_LOADNULLS)
+            CASE_OP(_OP_LOADROOT)
+            CASE_OP(_OP_LOADBOOL)
+            CASE_OP(_OP_DMOVE)
+            CASE_OP(_OP_JMP)
+            //CASE_OP(_OP_JNZ)
+            CASE_OP(_OP_JCMP)
+            CASE_OP(_OP_JZ)
+            CASE_OP(_OP_SETOUTER)
+            CASE_OP(_OP_GETOUTER)
+            CASE_OP(_OP_NEWOBJ)
+            CASE_OP(_OP_APPENDARRAY)
+            CASE_OP(_OP_COMPARITH)
+            CASE_OP(_OP_INC)
+            CASE_OP(_OP_INCL)
+            CASE_OP(_OP_PINC)
+            CASE_OP(_OP_PINCL)
+            CASE_OP(_OP_CMP)
+            CASE_OP(_OP_EXISTS)
+            CASE_OP(_OP_INSTANCEOF)
+            CASE_OP(_OP_AND)
+            CASE_OP(_OP_OR)
+            CASE_OP(_OP_NEG)
+            CASE_OP(_OP_NOT)
+            CASE_OP(_OP_BWNOT)
+            CASE_OP(_OP_CLOSURE)
+            CASE_OP(_OP_YIELD)
+            CASE_OP(_OP_RESUME)
+            CASE_OP(_OP_FOREACH)
+            CASE_OP(_OP_POSTFOREACH)
+            CASE_OP(_OP_CLONE)
+            CASE_OP(_OP_TYPEOF)
+            CASE_OP(_OP_PUSHTRAP)
+            CASE_OP(_OP_POPTRAP)
+            CASE_OP(_OP_THROW)
+            CASE_OP(_OP_NEWSLOTA)
+            CASE_OP(_OP_GETBASE)
+            CASE_OP(_OP_CLOSE)
+            default:
+                str_op = _SC("???");
+	    }
+		SafeWriteFmt(v,write,up,"\t\t/*%d*/[\"%s\", %d, %d, %d, %d, %d],\n", i, str_op, inst.op, inst._arg0, inst._arg1, inst._arg2, inst._arg3);
+	}
+    SafeWriteFmt(v,write,up,"\t],\n");
+
+	SafeWriteFmt(v,write,up,"\tfunctions = [");
+	for(i=0;i<nfunctions;i++){
+	    SafeWriteFmt(v,write,up,"/*%d*/", i);
+	    _CHECK_IO(_funcproto(_functions[i])->SaveAsSource(v,up,write));
+	    SafeWriteFmt(v,write,up,",\n");
+	}
+    SafeWriteFmt(v,write,up,"],\n");
+
+	SafeWriteFmt(v,write,up,"\tstacksize = %d,\n", sizeof(_stacksize));
+	SafeWriteFmt(v,write,up,"\tbgenerator = %d,\n", sizeof(_bgenerator));
+	SafeWriteFmt(v,write,up,"\tvarparams = %d,\n", sizeof(_varparams));
+	SafeWriteFmt(v,write,up,"}");
+	return true;
+}
 
 
 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
 {
 {