224 lines
6.8 KiB
C++
224 lines
6.8 KiB
C++
/**
|
|
* @author Alberto DEMICHELIS
|
|
* @author Edouard DUPIN
|
|
* @copyright 2018, Edouard DUPIN, all right reserved
|
|
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
|
|
* @license MPL-2 (see license file)
|
|
*/
|
|
#include <rabbit/SharedState.hpp>
|
|
#include <rabbit/Table.hpp>
|
|
#include <rabbit/String.hpp>
|
|
#include <rabbit/StringTable.hpp>
|
|
#include <rabbit/RegFunction.hpp>
|
|
#include <rabbit/NativeClosure.hpp>
|
|
#include <rabbit/VirtualMachine.hpp>
|
|
|
|
static rabbit::Table *createDefaultDelegate(rabbit::SharedState *ss,const rabbit::RegFunction *funcz)
|
|
{
|
|
int64_t i=0;
|
|
rabbit::Table *t=rabbit::Table::create(ss,0);
|
|
while(funcz[i].name!=0){
|
|
rabbit::NativeClosure *nc = rabbit::NativeClosure::create(ss,funcz[i].f,0);
|
|
nc->_nparamscheck = funcz[i].nparamscheck;
|
|
nc->_name = rabbit::String::create(ss,funcz[i].name);
|
|
if(funcz[i].typemask && !rabbit::compileTypemask(nc->_typecheck,funcz[i].typemask))
|
|
return NULL;
|
|
t->newSlot(rabbit::String::create(ss,funcz[i].name),nc);
|
|
i++;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
|
|
|
|
rabbit::SharedState::SharedState()
|
|
{
|
|
_compilererrorhandler = NULL;
|
|
_printfunc = NULL;
|
|
_errorfunc = NULL;
|
|
_debuginfo = false;
|
|
_notifyallexceptions = false;
|
|
_foreignptr = NULL;
|
|
_releasehook = NULL;
|
|
}
|
|
|
|
#define newsysstring(s) { \
|
|
_systemstrings->pushBack(rabbit::String::create(this,s)); \
|
|
}
|
|
|
|
#define newmetamethod(s) { \
|
|
_metamethods->pushBack(rabbit::String::create(this,s)); \
|
|
_table(_metamethodsmap)->newSlot(_metamethods->back(),(int64_t)(_metamethods->size()-1)); \
|
|
}
|
|
|
|
bool rabbit::compileTypemask(etk::Vector<int64_t> &res,const char *typemask)
|
|
{
|
|
int64_t i = 0;
|
|
int64_t mask = 0;
|
|
while(typemask[i] != 0) {
|
|
switch(typemask[i]) {
|
|
case 'o': mask |= _RT_NULL; break;
|
|
case 'i': mask |= _RT_INTEGER; break;
|
|
case 'f': mask |= _RT_FLOAT; break;
|
|
case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
|
|
case 's': mask |= _RT_STRING; break;
|
|
case 't': mask |= _RT_TABLE; break;
|
|
case 'a': mask |= _RT_ARRAY; break;
|
|
case 'u': mask |= _RT_USERDATA; break;
|
|
case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
|
|
case 'b': mask |= _RT_BOOL; break;
|
|
case 'g': mask |= _RT_GENERATOR; break;
|
|
case 'p': mask |= _RT_USERPOINTER; break;
|
|
case 'v': mask |= _RT_THREAD; break;
|
|
case 'x': mask |= _RT_INSTANCE; break;
|
|
case 'y': mask |= _RT_CLASS; break;
|
|
case 'r': mask |= _RT_WEAKREF; break;
|
|
case '.': mask = -1; res.pushBack(mask); i++; mask = 0; continue;
|
|
case ' ': i++; continue; //ignores spaces
|
|
default:
|
|
return false;
|
|
}
|
|
i++;
|
|
if(typemask[i] == '|') {
|
|
i++;
|
|
if(typemask[i] == 0)
|
|
return false;
|
|
continue;
|
|
}
|
|
res.pushBack(mask);
|
|
mask = 0;
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void rabbit::SharedState::init()
|
|
{
|
|
_scratchpad=NULL;
|
|
_scratchpadsize=0;
|
|
_stringtable = (rabbit::StringTable*)SQ_MALLOC(sizeof(rabbit::StringTable));
|
|
new ((char*)_stringtable) rabbit::StringTable(this);
|
|
sq_new(_metamethods,etk::Vector<rabbit::ObjectPtr>);
|
|
sq_new(_systemstrings,etk::Vector<rabbit::ObjectPtr>);
|
|
sq_new(_types,etk::Vector<rabbit::ObjectPtr>);
|
|
_metamethodsmap = rabbit::Table::create(this,rabbit::MT_LAST-1);
|
|
//adding type strings to avoid memory trashing
|
|
//types names
|
|
newsysstring(_SC("null"));
|
|
newsysstring(_SC("table"));
|
|
newsysstring(_SC("array"));
|
|
newsysstring(_SC("closure"));
|
|
newsysstring(_SC("string"));
|
|
newsysstring(_SC("userdata"));
|
|
newsysstring(_SC("integer"));
|
|
newsysstring(_SC("float"));
|
|
newsysstring(_SC("userpointer"));
|
|
newsysstring(_SC("function"));
|
|
newsysstring(_SC("generator"));
|
|
newsysstring(_SC("thread"));
|
|
newsysstring(_SC("class"));
|
|
newsysstring(_SC("instance"));
|
|
newsysstring(_SC("bool"));
|
|
//meta methods
|
|
newmetamethod(MM_ADD);
|
|
newmetamethod(MM_SUB);
|
|
newmetamethod(MM_MUL);
|
|
newmetamethod(MM_DIV);
|
|
newmetamethod(MM_UNM);
|
|
newmetamethod(MM_MODULO);
|
|
newmetamethod(MM_SET);
|
|
newmetamethod(MM_GET);
|
|
newmetamethod(MM_TYPEOF);
|
|
newmetamethod(MM_NEXTI);
|
|
newmetamethod(MM_CMP);
|
|
newmetamethod(MM_CALL);
|
|
newmetamethod(MM_CLONED);
|
|
newmetamethod(MM_NEWSLOT);
|
|
newmetamethod(MM_DELSLOT);
|
|
newmetamethod(MM_TOSTRING);
|
|
newmetamethod(MM_NEWMEMBER);
|
|
newmetamethod(MM_INHERITED);
|
|
|
|
_constructoridx = rabbit::String::create(this,_SC("constructor"));
|
|
_registry = rabbit::Table::create(this,0);
|
|
_consts = rabbit::Table::create(this,0);
|
|
_table_default_delegate = createDefaultDelegate(this,_table_default_delegate_funcz);
|
|
_array_default_delegate = createDefaultDelegate(this,_array_default_delegate_funcz);
|
|
_string_default_delegate = createDefaultDelegate(this,_string_default_delegate_funcz);
|
|
_number_default_delegate = createDefaultDelegate(this,_number_default_delegate_funcz);
|
|
_closure_default_delegate = createDefaultDelegate(this,_closure_default_delegate_funcz);
|
|
_generator_default_delegate = createDefaultDelegate(this,_generator_default_delegate_funcz);
|
|
_thread_default_delegate = createDefaultDelegate(this,_thread_default_delegate_funcz);
|
|
_class_default_delegate = createDefaultDelegate(this,_class_default_delegate_funcz);
|
|
_instance_default_delegate = createDefaultDelegate(this,_instance_default_delegate_funcz);
|
|
_weakref_default_delegate = createDefaultDelegate(this,_weakref_default_delegate_funcz);
|
|
}
|
|
|
|
rabbit::SharedState::~SharedState()
|
|
{
|
|
if(_releasehook) {
|
|
_releasehook(_foreignptr,0);
|
|
_releasehook = NULL;
|
|
}
|
|
_constructoridx.Null();
|
|
_table(_registry)->finalize();
|
|
_table(_consts)->finalize();
|
|
_table(_metamethodsmap)->finalize();
|
|
_registry.Null();
|
|
_consts.Null();
|
|
_metamethodsmap.Null();
|
|
while(!_systemstrings->empty()) {
|
|
_systemstrings->back().Null();
|
|
_systemstrings->popBack();
|
|
}
|
|
_thread(_root_vm)->finalize();
|
|
_root_vm.Null();
|
|
_table_default_delegate.Null();
|
|
_array_default_delegate.Null();
|
|
_string_default_delegate.Null();
|
|
_number_default_delegate.Null();
|
|
_closure_default_delegate.Null();
|
|
_generator_default_delegate.Null();
|
|
_thread_default_delegate.Null();
|
|
_class_default_delegate.Null();
|
|
_instance_default_delegate.Null();
|
|
_weakref_default_delegate.Null();
|
|
_refs_table.finalize();
|
|
using tmpType = etk::Vector<rabbit::ObjectPtr>;
|
|
sq_delete(_types, tmpType);
|
|
sq_delete(_systemstrings, tmpType);
|
|
sq_delete(_metamethods, tmpType);
|
|
sq_delete(_stringtable, StringTable);
|
|
if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
|
|
}
|
|
|
|
|
|
int64_t rabbit::SharedState::getMetaMethodIdxByName(const rabbit::ObjectPtr &name) {
|
|
if(sq_type(name) != rabbit::OT_STRING) {
|
|
return -1;
|
|
}
|
|
rabbit::ObjectPtr ret;
|
|
if(_table(_metamethodsmap)->get(name,ret)) {
|
|
return _integer(ret);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
char* rabbit::SharedState::getScratchPad(int64_t size) {
|
|
int64_t newsize;
|
|
if(size>0) {
|
|
if(_scratchpadsize < size) {
|
|
newsize = size + (size>>1);
|
|
_scratchpad = (char *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
|
|
_scratchpadsize = newsize;
|
|
} else if(_scratchpadsize >= (size<<5)) {
|
|
newsize = _scratchpadsize >> 1;
|
|
_scratchpad = (char *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
|
|
_scratchpadsize = newsize;
|
|
}
|
|
}
|
|
return _scratchpad;
|
|
}
|