summaryrefslogblamecommitdiffstats
path: root/squirrel_3_0_1_stable/sqplus/SquirrelVM.h
blob: ee66a2b76dcbe2bccec4f02474899b4649706fe4 (plain) (tree)


















































































































































































                                                                                                                                               
#ifndef _SQUIRREL_VM_H_
#define _SQUIRREL_VM_H_

#include "SquirrelObject.h"

struct SquirrelError {
    SquirrelError();
    SquirrelError(const SQChar* s):desc(s){}
    const SQChar *desc;
};

// This class can hold a reference to a SquirrelVM. It keeps a Squirrel ref
// to the VM to protect it from being deleted while held.
struct SquirrelVMSys { 
    SquirrelVMSys() { }
    ~SquirrelVMSys();
    
    void Set( HSQUIRRELVM v );
    void Set( const SquirrelObject& ov );
    void Reset( ){ _vm.Reset(); } 
    
    SquirrelVMSys& operator = (HSQUIRRELVM v){ Set(v); return *this; }
    operator HSQUIRRELVM () const;
    
protected:    
    void PushRefVM(HSQUIRRELVM v);
    void PopRefVM();
    SquirrelObject _vm;
    friend class SquirrelVM;
};

// Notes on creating / destroying SquirrelVM:s:
//
// VM:s created through sq_open are special since they create a new 
// SQSharedState. That shared state is later shared by any new thread
// or friend VM. sq_close can be used for closing VM:s created through
// sq_open (but not for friend VMs). 
//
// Using squirrel references in SquirrelVMSys and SquirrelVM, one must
// make sure that these are all reset if one calls sq_close manually.
//
// When there are no more references to a VM, it is destroyed automatically,
// but the shared state is not! For VM:s created by SquirrelVM, it keeps 
// a list of shared states it has created and will destroy them all on 
// app shutdown. 

class SquirrelVM {
    friend class SquirrelObject;
    friend struct SquirrelError;
    friend struct SquirrelVMSys;
    
public:
    // If a VM is passed as arg here, Init will not alter it. Otherwise 
    // a new VM is created and initialized. A squirrel reference is kept 
    // while it is the current VM.
    static bool Init( HSQUIRRELVM v=NULL );
    
    // Initialize with an externally created VM, without adding a ref 
    // on it. NOTE: This may not be compatible with Set/GetVMSys as 
    // we're just working with raw pointers here.
    static bool InitNoRef( HSQUIRRELVM v );
    static BOOL IsInitialized(){return _VM == NULL?FALSE:TRUE;}
    
    static void Release();   // Release ref on VM and reset VM pointer
    static void Shutdown(){ Release(); }
    static void AppFinalShutdown();  // Call when finally shutting down app
    
    static BOOL Update(); //debugger and maybe GC later
    
    static SquirrelObject CompileScript(const SQChar *s);
    static SquirrelObject CompileBuffer(const SQChar *s,const SQChar * debugInfo=_SC("console_buffer"));
    static SquirrelObject RunScript(const SquirrelObject &o,SquirrelObject *_this = NULL);
    
    static void PrintFunc(HSQUIRRELVM v,const SQChar* s,...);
    
    static BOOL BeginCall(const SquirrelObject &func);
    static BOOL BeginCall(const SquirrelObject &func,SquirrelObject &_this);
    
    static void PushParam(const SquirrelObject &o);
    static void PushParam(const SQChar *s);
    static void PushParam(SQInteger n);
    static void PushParam(SQFloat f);
    static void PushParam(SQUserPointer up);
    static void PushParamNull();
    
    static SquirrelObject EndCall();
    static SquirrelObject CreateString(const SQChar *s);
    static SquirrelObject CreateTable();    
    static SquirrelObject CreateArray(int size);
    static SquirrelObject CreateInstance(SquirrelObject &oclass); // oclass is an existing class. Create an 'instance' (OT_INSTANCE) of oclass.
    static SquirrelObject CreateFunction(SQFUNCTION func);
    static SquirrelObject CreateUserData(int size);

    static const SquirrelObject &GetRootTable();
    static HSQUIRRELVM GetVMPtr() { return _VM; }

    // The sandbox VM ptr is one which cannot access functions bound with 
    // SqPlus. It is suitable for running non-trusted scripts that can only
    // access basic functionality.
    static void SetSandboxVMPtr(HSQUIRRELVM v) {
      _sandboxVM = v;
    } // SetSandboxVMPtr
  
    static HSQUIRRELVM GetSandboxVMPtr() {
      return _sandboxVM;
    } // GetSandboxVMPtr
  
    static void GetVMSys(SquirrelVMSys & vmSys) {
      vmSys.Set( _vm );
    } // GetVMSys

    static void SetVMSys(const SquirrelVMSys & vmSys) {
      Release();
      HSQUIRRELVM v = (HSQUIRRELVM)vmSys;
      if( v ) 
          Init( v );
    } // SetVMSys

    static void PushValue(INT val) {
        sq_pushinteger(_VM,val);
    } // PushValue
    static void PushValue(FLOAT val) {
        sq_pushfloat(_VM,val);
    } // PushValue
    static void PushValue(bool val) { // Compiler treats SQBool as INT.
        sq_pushbool(_VM,val);
    } // PushValue
    static void PushValue(SQChar * val) {
        sq_pushstring(_VM,val,-1);
    } // PushValue
    static void PushValue(SQUserPointer val) {
        sq_pushuserpointer(_VM,val);
    } // PushValue
    static void PushValue(const SQChar * val) {
        sq_pushstring(_VM,val,-1);
    } // PushValue
    static void PushObject(SquirrelObject & so) {
        sq_pushobject(_VM,so._o);
    } // PushObject
    static void Pop(SQInteger nelemstopop) {
        sq_pop(_VM,nelemstopop);
    } // Pop
    
    static void PushRootTable(void);
    
    // Create/bind a function on the table currently on the stack.
    static SquirrelObject CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);
    // Create/bind a function on the table so. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args.
    static SquirrelObject CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);
    // Create/bind a function to the root table. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args.
    static SquirrelObject CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);

    // This is a helper to correct a difference in referncing new VM:s in 
    // ref counted versus garbage collected modes. NOTE: Only use after creating
    // a VM with:  1 - sq_open()  2 - Creating a ref to the VM (SquirrelObject)
    static void DropVMRefIfRefCounted( HSQUIRRELVM v );
  

private:
    static SquirrelObject _vm;        // This is a Squirrel reference to the VM
    static HSQUIRRELVM    _VM;        // The raw C++ pointer
    static bool           _no_vm_ref; // Set if we only keep the raw C++ pointer and no ref
    static int _CallState;
    static SquirrelObject * _root;    // Cached root table if non NULL
    static HSQUIRRELVM _sandboxVM;    // The sandbox VM (that cannot use bound functions)
};


template<typename T>
inline BOOL SquirrelObject::ArrayAppend(T item) {
    sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
    SquirrelVM::PushValue(item);
    BOOL res = sq_arrayappend(SquirrelVM::_VM,-2) == SQ_OK;
    sq_pop(SquirrelVM::_VM,1);
    return res;
} // ArrayAppend

#endif //_SQUIRREL_VM_H_