[DEV] continue rework (main step)

This commit is contained in:
Edouard DUPIN 2018-06-29 00:11:33 +02:00
parent 45e2df01f0
commit aa49dbd05d
49 changed files with 1495 additions and 1372 deletions

View File

@ -27,85 +27,110 @@ def get_version():
def configure(target, my_module):
my_module.add_src_file([
'rabbit/Hash.cpp',
'rabbit/RefTable.cpp',
'rabbit/SharedState.cpp',
'rabbit/String.cpp',
'rabbit/StringTable.cpp',
'rabbit/Table.cpp',
'rabbit/sqmem.cpp',
'rabbit/sqbaselib.cpp',
'rabbit/sqapi.cpp',
'rabbit/sqlexer.cpp',
'rabbit/Class.cpp',
'rabbit/ClassMember.cpp',
'rabbit/Instance.cpp',
'rabbit/AutoDec.cpp',
'rabbit/VirtualMachine.cpp',
'rabbit/sqobject.cpp',
'rabbit/sqcompiler.cpp',
'rabbit/sqdebug.cpp',
'rabbit/sqfuncstate.cpp',
'rabbit/RefCounted.cpp',
'rabbit/WeakRef.cpp',
'rabbit/Delegable.cpp',
'rabbit/ObjectType.cpp',
'rabbit/ObjectValue.cpp',
'rabbit/Object.cpp',
'rabbit/ObjectPtr.cpp',
'rabbit/MemberHandle.cpp',
'rabbit/StackInfos.cpp',
'rabbit/RegFunction.cpp',
'rabbit/FunctionInfo.cpp',
'rabbit/MetaMethod.cpp',
'rabbit/ExceptionTrap.cpp',
])
'rabbit/Array.cpp',
'rabbit/AutoDec.cpp',
'rabbit/Class.cpp',
'rabbit/ClassMember.cpp',
'rabbit/Closure.cpp',
'rabbit/Compiler.cpp',
'rabbit/Delegable.cpp',
'rabbit/ExceptionTrap.cpp',
'rabbit/FuncState.cpp',
'rabbit/FunctionInfo.cpp',
'rabbit/FunctionProto.cpp',
'rabbit/Generator.cpp',
'rabbit/Hash.cpp',
'rabbit/Instance.cpp',
'rabbit/Instruction.cpp',
'rabbit/Lexer.cpp',
'rabbit/LineInfo.cpp',
'rabbit/LocalVarInfo.cpp',
'rabbit/MemberHandle.cpp',
'rabbit/MetaMethod.cpp',
'rabbit/NativeClosure.cpp',
'rabbit/Object.cpp',
'rabbit/ObjectPtr.cpp',
'rabbit/ObjectType.cpp',
'rabbit/ObjectValue.cpp',
'rabbit/Outer.cpp',
'rabbit/OuterVar.cpp',
'rabbit/RefCounted.cpp',
'rabbit/RefTable.cpp',
'rabbit/RegFunction.cpp',
'rabbit/SharedState.cpp',
'rabbit/StackInfos.cpp',
'rabbit/String.cpp',
'rabbit/StringTable.cpp',
'rabbit/Table.cpp',
'rabbit/VirtualMachine.cpp',
'rabbit/WeakRef.cpp',
'rabbit/sqapi.cpp',
'rabbit/sqbaselib.cpp',
'rabbit/sqcompiler.cpp',
'rabbit/sqdebug.cpp',
'rabbit/sqfuncstate.cpp',
'rabbit/sqlexer.cpp',
'rabbit/sqmem.cpp',
'rabbit/sqobject.cpp',
])
my_module.compile_version("c++", 2011)
my_module.add_depend([
'z',
'm',
'c',
'etk-base',
])
'z',
'm',
'c',
'etk-base',
])
my_module.add_header_file([
'rabbit/Hash.hpp',
'rabbit/RefTable.hpp',
'rabbit/SharedState.hpp',
'rabbit/String.hpp',
'rabbit/StringTable.hpp',
'rabbit/Table.hpp',
'rabbit/Class.hpp',
'rabbit/ClassMember.hpp',
'rabbit/Instance.hpp',
'rabbit/AutoDec.hpp',
'rabbit/VirtualMachine.hpp',
'rabbit/rabbit.hpp',
'rabbit/sqobject.hpp',
'rabbit/sqopcodes.hpp',
'rabbit/UserData.hpp',
'rabbit/squtils.hpp',
'rabbit/sqpcheader.hpp',
'rabbit/sqfuncproto.hpp',
'rabbit/sqconfig.hpp',
'rabbit/sqcompiler.hpp',
'rabbit/Array.hpp',
'rabbit/sqclosure.hpp',
'rabbit/sqlexer.hpp',
'rabbit/sqfuncstate.hpp',
'rabbit/RefCounted.hpp',
'rabbit/WeakRef.hpp',
'rabbit/Delegable.hpp',
'rabbit/ObjectType.hpp',
'rabbit/ObjectValue.hpp',
'rabbit/Object.hpp',
'rabbit/ObjectPtr.hpp',
'rabbit/MemberHandle.hpp',
'rabbit/StackInfos.hpp',
'rabbit/RegFunction.hpp',
'rabbit/FunctionInfo.hpp',
'rabbit/MetaMethod.hpp',
'rabbit/ExceptionTrap.hpp',
])
'rabbit/Array.hpp',
'rabbit/AutoDec.hpp',
'rabbit/Class.hpp',
'rabbit/ClassMember.hpp',
'rabbit/Closure.hpp',
'rabbit/Compiler.hpp',
'rabbit/Delegable.hpp',
'rabbit/ExceptionTrap.hpp',
'rabbit/FuncState.hpp',
'rabbit/FunctionInfo.hpp',
'rabbit/FunctionProto.hpp',
'rabbit/Generator.hpp',
'rabbit/Hash.hpp',
'rabbit/Instance.hpp',
'rabbit/Instruction.hpp',
'rabbit/Lexer.hpp',
'rabbit/LineInfo.hpp',
'rabbit/LocalVarInfo.hpp',
'rabbit/MemberHandle.hpp',
'rabbit/MetaMethod.hpp',
'rabbit/NativeClosure.hpp',
'rabbit/Object.hpp',
'rabbit/ObjectPtr.hpp',
'rabbit/ObjectType.hpp',
'rabbit/ObjectValue.hpp',
'rabbit/Outer.hpp',
'rabbit/OuterVar.hpp',
'rabbit/RefCounted.hpp',
'rabbit/RefTable.hpp',
'rabbit/RegFunction.hpp',
'rabbit/SharedState.hpp',
'rabbit/StackInfos.hpp',
'rabbit/String.hpp',
'rabbit/StringTable.hpp',
'rabbit/Table.hpp',
'rabbit/UserData.hpp',
'rabbit/VirtualMachine.hpp',
'rabbit/WeakRef.hpp',
'rabbit/rabbit.hpp',
'rabbit/sqclosure.hpp',
'rabbit/sqcompiler.hpp',
'rabbit/sqconfig.hpp',
'rabbit/sqfuncproto.hpp',
'rabbit/sqfuncstate.hpp',
'rabbit/sqlexer.hpp',
'rabbit/sqobject.hpp',
'rabbit/sqopcodes.hpp',
'rabbit/sqpcheader.hpp',
'rabbit/squtils.hpp',
])
return True

135
rabbit/Closure.cpp Normal file
View File

@ -0,0 +1,135 @@
/**
* @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/Closure.hpp>
#define _CHECK_IO(exp) { if(!exp)return false; }
bool SafeWrite(rabbit::VirtualMachine* v,SQWRITEFUNC write,rabbit::UserPointer up,rabbit::UserPointer dest,int64_t size)
{
if(write(up,dest,size) != size) {
v->raise_error(_SC("io error (write function failure)"));
return false;
}
return true;
}
bool SafeRead(rabbit::VirtualMachine* v,SQWRITEFUNC read,rabbit::UserPointer up,rabbit::UserPointer dest,int64_t size)
{
if(size && read(up,dest,size) != size) {
v->raise_error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
return false;
}
return true;
}
bool WriteTag(rabbit::VirtualMachine* v,SQWRITEFUNC write,rabbit::UserPointer up,uint32_t tag)
{
return SafeWrite(v,write,up,&tag,sizeof(tag));
}
bool CheckTag(rabbit::VirtualMachine* v,SQWRITEFUNC read,rabbit::UserPointer up,uint32_t tag)
{
uint32_t t;
_CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
if(t != tag){
v->raise_error(_SC("invalid or corrupted closure stream"));
return false;
}
return true;
}
bool WriteObject(rabbit::VirtualMachine* v,rabbit::UserPointer up,SQWRITEFUNC write,rabbit::ObjectPtr &o)
{
uint32_t _type = (uint32_t)sq_type(o);
_CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
switch(sq_type(o)){
case rabbit::OT_STRING:
_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(int64_t)));
_CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len)));
break;
case rabbit::OT_BOOL:
case rabbit::OT_INTEGER:
_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(int64_t)));break;
case rabbit::OT_FLOAT:
_CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(float_t)));break;
case rabbit::OT_NULL:
break;
default:
v->raise_error(_SC("cannot serialize a %s"),getTypeName(o));
return false;
}
return true;
}
bool ReadObject(rabbit::VirtualMachine* v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &o)
{
uint32_t _type;
_CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
rabbit::ObjectType t = (rabbit::ObjectType)_type;
switch(t){
case rabbit::OT_STRING:{
int64_t len;
_CHECK_IO(SafeRead(v,read,up,&len,sizeof(int64_t)));
_CHECK_IO(SafeRead(v,read,up,_get_shared_state(v)->getScratchPad(sq_rsl(len)),sq_rsl(len)));
o=rabbit::String::create(_get_shared_state(v),_get_shared_state(v)->getScratchPad(-1),len);
}
break;
case rabbit::OT_INTEGER:{
int64_t i;
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(int64_t))); o = i; break;
}
case rabbit::OT_BOOL:{
int64_t i;
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(int64_t))); o._type = rabbit::OT_BOOL; o._unVal.nInteger = i; break;
}
case rabbit::OT_FLOAT:{
float_t f;
_CHECK_IO(SafeRead(v,read,up,&f,sizeof(float_t))); o = f; break;
}
case rabbit::OT_NULL:
o.Null();
break;
default:
v->raise_error(_SC("cannot serialize a %s"),IdType2Name(t));
return false;
}
return true;
}
bool rabbit::Closure::save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write)
{
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(WriteTag(v,write,up,sizeof(rabbit::Char)));
_CHECK_IO(WriteTag(v,write,up,sizeof(int64_t)));
_CHECK_IO(WriteTag(v,write,up,sizeof(float_t)));
_CHECK_IO(_function->save(v,up,write));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
return true;
}
bool rabbit::Closure::load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret)
{
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(CheckTag(v,read,up,sizeof(rabbit::Char)));
_CHECK_IO(CheckTag(v,read,up,sizeof(int64_t)));
_CHECK_IO(CheckTag(v,read,up,sizeof(float_t)));
rabbit::ObjectPtr func;
_CHECK_IO(rabbit::FunctionProto::load(v,up,read,func));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
ret = rabbit::Closure::create(_get_shared_state(v),_funcproto(func),_table(v->_roottable)->getWeakRef(rabbit::OT_TABLE));
//FIXME: load an root for this closure
return true;
}
rabbit::Closure::~Closure()
{
__Objrelease(_root);
__Objrelease(_env);
__Objrelease(_base);
}

76
rabbit/Closure.hpp Normal file
View File

@ -0,0 +1,76 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
#define _CALC_CLOSURE_SIZE(func) (sizeof(rabbit::Closure) + (func->_noutervalues*sizeof(rabbit::ObjectPtr)) + (func->_ndefaultparams*sizeof(rabbit::ObjectPtr)))
class Closure : public rabbit::RefCounted {
private:
Closure(rabbit::SharedState *ss,rabbit::FunctionProto *func){
_function = func;
__ObjaddRef(_function); _base = NULL;
_env = NULL;
_root=NULL;
}
public:
static rabbit::Closure *create(rabbit::SharedState *ss,rabbit::FunctionProto *func,rabbit::WeakRef *root){
int64_t size = _CALC_CLOSURE_SIZE(func);
rabbit::Closure *nc=(rabbit::Closure*)SQ_MALLOC(size);
new (nc) rabbit::Closure(ss,func);
nc->_outervalues = (rabbit::ObjectPtr *)(nc + 1);
nc->_defaultparams = &nc->_outervalues[func->_noutervalues];
nc->_root = root;
__ObjaddRef(nc->_root);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,func->_noutervalues,nc->_outervalues);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,func->_ndefaultparams,nc->_defaultparams);
return nc;
}
void release(){
rabbit::FunctionProto *f = _function;
int64_t size = _CALC_CLOSURE_SIZE(f);
_DESTRUCT_VECTOR(ObjectPtr,f->_noutervalues,_outervalues);
_DESTRUCT_VECTOR(ObjectPtr,f->_ndefaultparams,_defaultparams);
__Objrelease(_function);
this->~rabbit::Closure();
sq_vm_free(this,size);
}
void setRoot(rabbit::WeakRef *r)
{
__Objrelease(_root);
_root = r;
__ObjaddRef(_root);
}
rabbit::Closure *clone()
{
rabbit::FunctionProto *f = _function;
rabbit::Closure * ret = rabbit::Closure::create(NULL,f,_root);
ret->_env = _env;
if(ret->_env) __ObjaddRef(ret->_env);
_COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
_COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
return ret;
}
~rabbit::Closure();
bool save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write);
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::WeakRef *_env;
rabbit::WeakRef *_root;
rabbit::Class *_base;
rabbit::FunctionProto *_function;
rabbit::ObjectPtr *_outervalues;
rabbit::ObjectPtr *_defaultparams;
};
}
#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))

View File

@ -5,6 +5,8 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/Compiler.hpp>
#include <rabbit/sqpcheader.hpp>
#ifndef NO_COMPILER
#include <stdarg.h>
@ -73,10 +75,10 @@ struct SQScope {
if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
_fs->_breaktargets.popBack();_fs->_continuetargets.popBack();}
class SQcompiler
class rabbit::Compiler
{
public:
SQcompiler(rabbit::VirtualMachine *v, SQLEXREADFUNC rg, rabbit::UserPointer up, const rabbit::Char* sourcename, bool raiseerror, bool lineinfo)
rabbit::Compiler(rabbit::VirtualMachine *v, SQLEXREADFUNC rg, rabbit::UserPointer up, const rabbit::Char* sourcename, bool raiseerror, bool lineinfo)
{
_vm=v;
_lex.init(_get_shared_state(v), rg, up,Throwerror,this);
@ -87,7 +89,7 @@ public:
_compilererror[0] = _SC('\0');
}
static void Throwerror(void *ud, const rabbit::Char *s) {
SQcompiler *c = (SQcompiler *)ud;
rabbit::Compiler *c = (rabbit::Compiler *)ud;
c->error(s);
}
void error(const rabbit::Char *s, ...)
@ -170,7 +172,7 @@ public:
_debugline = 1;
_debugop = 0;
SQFuncState funcstate(_get_shared_state(_vm), NULL,Throwerror,this);
FuncState funcstate(_get_shared_state(_vm), NULL,Throwerror,this);
funcstate._name = rabbit::String::create(_get_shared_state(_vm), _SC("main"));
_fs = &funcstate;
_fs->addParameter(_fs->createString(_SC("this")));
@ -481,7 +483,7 @@ public:
_fs->addInstruction(_OP_OR, trg, 0, first_exp, 0);
int64_t jpos = _fs->getCurrentPos();
if(trg != first_exp) _fs->addInstruction(_OP_MOVE, trg, first_exp);
Lex(); INVOKE_EXP(&SQcompiler::LogicalOrExp);
Lex(); INVOKE_EXP(&rabbit::Compiler::LogicalOrExp);
_fs->snoozeOpt();
int64_t second_exp = _fs->popTarget();
if(trg != second_exp) _fs->addInstruction(_OP_MOVE, trg, second_exp);
@ -501,7 +503,7 @@ public:
_fs->addInstruction(_OP_AND, trg, 0, first_exp, 0);
int64_t jpos = _fs->getCurrentPos();
if(trg != first_exp) _fs->addInstruction(_OP_MOVE, trg, first_exp);
Lex(); INVOKE_EXP(&SQcompiler::LogicalAndExp);
Lex(); INVOKE_EXP(&rabbit::Compiler::LogicalAndExp);
_fs->snoozeOpt();
int64_t second_exp = _fs->popTarget();
if(trg != second_exp) _fs->addInstruction(_OP_MOVE, trg, second_exp);
@ -519,30 +521,30 @@ public:
{
BitwiseXorExp();
for(;;) if(_token == _SC('|'))
{BIN_EXP(_OP_BITW, &SQcompiler::BitwiseXorExp,BW_OR);
{BIN_EXP(_OP_BITW, &rabbit::Compiler::BitwiseXorExp,BW_OR);
}else return;
}
void BitwiseXorExp()
{
BitwiseAndExp();
for(;;) if(_token == _SC('^'))
{BIN_EXP(_OP_BITW, &SQcompiler::BitwiseAndExp,BW_XOR);
{BIN_EXP(_OP_BITW, &rabbit::Compiler::BitwiseAndExp,BW_XOR);
}else return;
}
void BitwiseAndExp()
{
EqExp();
for(;;) if(_token == _SC('&'))
{BIN_EXP(_OP_BITW, &SQcompiler::EqExp,BW_AND);
{BIN_EXP(_OP_BITW, &rabbit::Compiler::EqExp,BW_AND);
}else return;
}
void EqExp()
{
CompExp();
for(;;) switch(_token) {
case TK_EQ: BIN_EXP(_OP_EQ, &SQcompiler::CompExp); break;
case TK_NE: BIN_EXP(_OP_NE, &SQcompiler::CompExp); break;
case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQcompiler::CompExp,CMP_3W); break;
case TK_EQ: BIN_EXP(_OP_EQ, &rabbit::Compiler::CompExp); break;
case TK_NE: BIN_EXP(_OP_NE, &rabbit::Compiler::CompExp); break;
case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &rabbit::Compiler::CompExp,CMP_3W); break;
default: return;
}
}
@ -550,12 +552,12 @@ public:
{
ShiftExp();
for(;;) switch(_token) {
case _SC('>'): BIN_EXP(_OP_CMP, &SQcompiler::ShiftExp,CMP_G); break;
case _SC('<'): BIN_EXP(_OP_CMP, &SQcompiler::ShiftExp,CMP_L); break;
case TK_GE: BIN_EXP(_OP_CMP, &SQcompiler::ShiftExp,CMP_GE); break;
case TK_LE: BIN_EXP(_OP_CMP, &SQcompiler::ShiftExp,CMP_LE); break;
case TK_IN: BIN_EXP(_OP_EXISTS, &SQcompiler::ShiftExp); break;
case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQcompiler::ShiftExp); break;
case _SC('>'): BIN_EXP(_OP_CMP, &rabbit::Compiler::ShiftExp,CMP_G); break;
case _SC('<'): BIN_EXP(_OP_CMP, &rabbit::Compiler::ShiftExp,CMP_L); break;
case TK_GE: BIN_EXP(_OP_CMP, &rabbit::Compiler::ShiftExp,CMP_GE); break;
case TK_LE: BIN_EXP(_OP_CMP, &rabbit::Compiler::ShiftExp,CMP_LE); break;
case TK_IN: BIN_EXP(_OP_EXISTS, &rabbit::Compiler::ShiftExp); break;
case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &rabbit::Compiler::ShiftExp); break;
default: return;
}
}
@ -563,9 +565,9 @@ public:
{
PlusExp();
for(;;) switch(_token) {
case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQcompiler::PlusExp,BW_USHIFTR); break;
case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQcompiler::PlusExp,BW_SHIFTL); break;
case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQcompiler::PlusExp,BW_SHIFTR); break;
case TK_USHIFTR: BIN_EXP(_OP_BITW, &rabbit::Compiler::PlusExp,BW_USHIFTR); break;
case TK_SHIFTL: BIN_EXP(_OP_BITW, &rabbit::Compiler::PlusExp,BW_SHIFTL); break;
case TK_SHIFTR: BIN_EXP(_OP_BITW, &rabbit::Compiler::PlusExp,BW_SHIFTR); break;
default: return;
}
}
@ -600,7 +602,7 @@ public:
MultExp();
for(;;) switch(_token) {
case _SC('+'): case _SC('-'):
BIN_EXP(ChooseArithOpByToken(_token), &SQcompiler::MultExp); break;
BIN_EXP(ChooseArithOpByToken(_token), &rabbit::Compiler::MultExp); break;
default: return;
}
}
@ -610,7 +612,7 @@ public:
PrefixedExpr();
for(;;) switch(_token) {
case _SC('*'): case _SC('/'): case _SC('%'):
BIN_EXP(ChooseArithOpByToken(_token), &SQcompiler::PrefixedExpr); break;
BIN_EXP(ChooseArithOpByToken(_token), &rabbit::Compiler::PrefixedExpr); break;
default: return;
}
}
@ -1160,7 +1162,7 @@ public:
_fs->snoozeOpt();
int64_t expend = _fs->getCurrentPos();
int64_t expsize = (expend - expstart) + 1;
SQInstructionVec exp;
rabbit::InstructionVec exp;
if(expsize > 0) {
for(int64_t i = 0; i < expsize; i++)
exp.pushBack(_fs->getInstruction(expstart + i));
@ -1490,7 +1492,7 @@ public:
}
void createFunction(rabbit::Object &name,bool lambda = false)
{
SQFuncState *funcstate = _fs->pushChildState(_get_shared_state(_vm));
FuncState *funcstate = _fs->pushChildState(_get_shared_state(_vm));
funcstate->_name = name;
rabbit::Object paramname;
funcstate->addParameter(_fs->createString(_SC("this")));
@ -1526,7 +1528,7 @@ public:
_fs->popTarget();
}
SQFuncState *currchunk = _fs;
FuncState *currchunk = _fs;
_fs = funcstate;
if(lambda) {
Expression();
@ -1538,7 +1540,7 @@ public:
funcstate->addInstruction(_OP_RETURN, -1);
funcstate->setStacksize(0);
SQFunctionProto *func = funcstate->buildProto();
rabbit::FunctionProto *func = funcstate->buildProto();
#ifdef _DEBUG_DUMP
funcstate->dump(func);
#endif
@ -1546,7 +1548,7 @@ public:
_fs->_functions.pushBack(func);
_fs->popChildState();
}
void ResolveBreaks(SQFuncState *funcstate, int64_t ntoresolve)
void ResolveBreaks(FuncState *funcstate, int64_t ntoresolve)
{
while(ntoresolve > 0) {
int64_t pos = funcstate->_unresolvedbreaks.back();
@ -1556,7 +1558,7 @@ public:
ntoresolve--;
}
}
void ResolveContinues(SQFuncState *funcstate, int64_t ntoresolve, int64_t targetpos)
void ResolveContinues(FuncState *funcstate, int64_t ntoresolve, int64_t targetpos)
{
while(ntoresolve > 0) {
int64_t pos = funcstate->_unresolvedcontinues.back();
@ -1568,9 +1570,9 @@ public:
}
private:
int64_t _token;
SQFuncState *_fs;
FuncState *_fs;
rabbit::ObjectPtr _sourcename;
SQLexer _lex;
rabbit::Lexer _lex;
bool _lineinfo;
bool _raiseerror;
int64_t _debugline;
@ -1584,7 +1586,7 @@ private:
bool compile(rabbit::VirtualMachine *vm,SQLEXREADFUNC rg, rabbit::UserPointer up, const rabbit::Char *sourcename, rabbit::ObjectPtr &out, bool raiseerror, bool lineinfo)
{
SQcompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
rabbit::Compiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
return p.compile(out);
}

84
rabbit/Compiler.hpp Normal file
View File

@ -0,0 +1,84 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
#define TK_IDENTIFIER 258
#define TK_STRING_LITERAL 259
#define TK_INTEGER 260
#define TK_FLOAT 261
#define TK_BASE 262
#define TK_DELETE 263
#define TK_EQ 264
#define TK_NE 265
#define TK_LE 266
#define TK_GE 267
#define TK_SWITCH 268
#define TK_ARROW 269
#define TK_AND 270
#define TK_OR 271
#define TK_IF 272
#define TK_ELSE 273
#define TK_WHILE 274
#define TK_BREAK 275
#define TK_FOR 276
#define TK_DO 277
#define TK_NULL 278
#define TK_FOREACH 279
#define TK_IN 280
#define TK_NEWSLOT 281
#define TK_MODULO 282
#define TK_LOCAL 283
#define TK_CLONE 284
#define TK_FUNCTION 285
#define TK_RETURN 286
#define TK_TYPEOF 287
#define TK_UMINUS 288
#define TK_PLUSEQ 289
#define TK_MINUSEQ 290
#define TK_CONTINUE 291
#define TK_YIELD 292
#define TK_TRY 293
#define TK_CATCH 294
#define TK_THROW 295
#define TK_SHIFTL 296
#define TK_SHIFTR 297
#define TK_RESUME 298
#define TK_DOUBLE_COLON 299
#define TK_CASE 300
#define TK_DEFAULT 301
#define TK_THIS 302
#define TK_PLUSPLUS 303
#define TK_MINUSMINUS 304
#define TK_3WAYSCMP 305
#define TK_USHIFTR 306
#define TK_CLASS 307
#define TK_EXTENDS 308
#define TK_CONSTRUCTOR 310
#define TK_INSTANCEOF 311
#define TK_VARPARAMS 312
#define TK___LINE__ 313
#define TK___FILE__ 314
#define TK_TRUE 315
#define TK_FALSE 316
#define TK_MULEQ 317
#define TK_DIVEQ 318
#define TK_MODEQ 319
#define TK_ATTR_OPEN 320
#define TK_ATTR_CLOSE 321
#define TK_STATIC 322
#define TK_ENUM 323
#define TK_CONST 324
#define TK_RAWCALL 325
typedef void(*compilererrorFunc)(void *ud, const rabbit::Char *s);
bool compile(rabbit::VirtualMachine *vm, SQLEXREADFUNC rg, rabbit::UserPointer up, const rabbit::Char *sourcename, rabbit::ObjectPtr &out, bool raiseerror, bool lineinfo);
}

View File

@ -10,7 +10,7 @@
#include <etk/types.hpp>
#include <rabbit/sqconfig.hpp>
struct SQInstruction;
struct rabbit::Instruction;
namespace rabbit {
class ExceptionTrap {
public:
@ -19,7 +19,7 @@ namespace rabbit {
}
ExceptionTrap(int64_t ss,
int64_t stackbase,
SQInstruction *ip,
rabbit::Instruction *ip,
int64_t ex_target) {
_stacksize = ss;
_stackbase = stackbase;
@ -32,7 +32,7 @@ namespace rabbit {
int64_t _stackbase;
int64_t _stacksize;
SQInstruction *_ip;
rabbit::Instruction *_ip;
int64_t _extarget;
};
}

View File

@ -5,18 +5,18 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/FuncState.hpp>
#include <rabbit/sqpcheader.hpp>
#ifndef NO_COMPILER
#include <rabbit/sqcompiler.hpp>
#include <rabbit/Compiler.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/FuncProto.hpp>
#include <rabbit/sqopcodes.hpp>
#include <rabbit/sqfuncstate.hpp>
#ifdef _DEBUG_DUMP
SQInstructionDesc g_InstrDesc[]={
rabbit::InstructionDesc g_InstrDesc[]={
{_SC("_OP_LINE")},
{_SC("_OP_LOAD")},
{_SC("_OP_LOADINT")},
@ -91,7 +91,7 @@ void dumpLiteral(rabbit::ObjectPtr &o)
}
}
SQFuncState::SQFuncState(rabbit::SharedState *ss,SQFuncState *parent,compilererrorFunc efunc,void *ed)
FuncState::rabbit::FuncState(rabbit::SharedState *ss,rabbit::FuncState *parent,compilererrorFunc efunc,void *ed)
{
_nliterals = 0;
_literals = rabbit::Table::create(ss,0);
@ -112,17 +112,17 @@ SQFuncState::SQFuncState(rabbit::SharedState *ss,SQFuncState *parent,compilererr
}
void SQFuncState::error(const rabbit::Char *err)
void FuncState::error(const rabbit::Char *err)
{
_errfunc(_errtarget,err);
}
#ifdef _DEBUG_DUMP
void SQFuncState::dump(SQFunctionProto *func)
void FuncState::dump(rabbit::FunctionProto *func)
{
uint64_t n=0,i;
int64_t si;
scprintf(_SC("SQInstruction sizeof %d\n"),(int32_t)sizeof(SQInstruction));
scprintf(_SC("rabbit::Instruction sizeof %d\n"),(int32_t)sizeof(rabbit::Instruction));
scprintf(_SC("rabbit::Object sizeof %d\n"), (int32_t)sizeof(rabbit::Object));
scprintf(_SC("--------------------------------------------------------------------\n"));
scprintf(_SC("*****FUNCTION [%s]\n"),sq_type(func->_name)==rabbit::OT_STRING?_stringval(func->_name):_SC("unknown"));
@ -153,20 +153,20 @@ void SQFuncState::dump(SQFunctionProto *func)
}
scprintf(_SC("-----LOCALS\n"));
for(si=0;si<func->_nlocalvarinfos;si++){
SQLocalVarInfo lvi=func->_localvarinfos[si];
rabbit::LocalVarInfo lvi=func->_localvarinfos[si];
scprintf(_SC("[%d] %s \t%d %d\n"), (int32_t)lvi._pos,_stringval(lvi._name), (int32_t)lvi._start_op, (int32_t)lvi._end_op);
n++;
}
scprintf(_SC("-----LINE INFO\n"));
for(i=0;i<_lineinfos.size();i++){
SQLineInfo li=_lineinfos[i];
rabbit::LineInfo li=_lineinfos[i];
scprintf(_SC("op [%d] line [%d] \n"), (int32_t)li._op, (int32_t)li._line);
n++;
}
scprintf(_SC("-----dump\n"));
n=0;
for(i=0;i<_instructions.size();i++){
SQInstruction &inst=_instructions[i];
rabbit::Instruction &inst=_instructions[i];
if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
int64_t lidx = inst._arg1;
@ -217,17 +217,17 @@ void SQFuncState::dump(SQFunctionProto *func)
}
#endif
int64_t SQFuncState::getNumericConstant(const int64_t cons)
int64_t FuncState::getNumericConstant(const int64_t cons)
{
return getConstant(rabbit::ObjectPtr(cons));
}
int64_t SQFuncState::getNumericConstant(const float_t cons)
int64_t FuncState::getNumericConstant(const float_t cons)
{
return getConstant(rabbit::ObjectPtr(cons));
}
int64_t SQFuncState::getConstant(const rabbit::Object &cons)
int64_t FuncState::getConstant(const rabbit::Object &cons)
{
rabbit::ObjectPtr val;
if(!_table(_literals)->get(cons,val))
@ -243,7 +243,7 @@ int64_t SQFuncState::getConstant(const rabbit::Object &cons)
return _integer(val);
}
void SQFuncState::setIntructionParams(int64_t pos,int64_t arg0,int64_t arg1,int64_t arg2,int64_t arg3)
void FuncState::setIntructionParams(int64_t pos,int64_t arg0,int64_t arg1,int64_t arg2,int64_t arg3)
{
_instructions[pos]._arg0=(unsigned char)*((uint64_t *)&arg0);
_instructions[pos]._arg1=(int32_t)*((uint64_t *)&arg1);
@ -251,7 +251,7 @@ void SQFuncState::setIntructionParams(int64_t pos,int64_t arg0,int64_t arg1,int6
_instructions[pos]._arg3=(unsigned char)*((uint64_t *)&arg3);
}
void SQFuncState::setIntructionParam(int64_t pos,int64_t arg,int64_t val)
void FuncState::setIntructionParam(int64_t pos,int64_t arg,int64_t val)
{
switch(arg){
case 0:_instructions[pos]._arg0=(unsigned char)*((uint64_t *)&val);break;
@ -261,10 +261,10 @@ void SQFuncState::setIntructionParam(int64_t pos,int64_t arg,int64_t val)
};
}
int64_t SQFuncState::allocStackPos()
int64_t FuncState::allocStackPos()
{
int64_t npos=_vlocals.size();
_vlocals.pushBack(SQLocalVarInfo());
_vlocals.pushBack(rabbit::LocalVarInfo());
if(_vlocals.size()>((uint64_t)_stacksize)) {
if(_stacksize>MAX_FUNC_STACKSIZE) error(_SC("internal compiler error: too many locals"));
_stacksize=_vlocals.size();
@ -272,7 +272,7 @@ int64_t SQFuncState::allocStackPos()
return npos;
}
int64_t SQFuncState::pushTarget(int64_t n)
int64_t FuncState::pushTarget(int64_t n)
{
if(n!=-1){
_targetstack.pushBack(n);
@ -283,18 +283,18 @@ int64_t SQFuncState::pushTarget(int64_t n)
return n;
}
int64_t SQFuncState::getUpTarget(int64_t n){
int64_t FuncState::getUpTarget(int64_t n){
return _targetstack[((_targetstack.size()-1)-n)];
}
int64_t SQFuncState::topTarget(){
int64_t FuncState::topTarget(){
return _targetstack.back();
}
int64_t SQFuncState::popTarget()
int64_t FuncState::popTarget()
{
uint64_t npos=_targetstack.back();
assert(npos < _vlocals.size());
SQLocalVarInfo &t = _vlocals[npos];
rabbit::LocalVarInfo &t = _vlocals[npos];
if(sq_type(t._name)==rabbit::OT_NULL){
_vlocals.popBack();
}
@ -302,17 +302,17 @@ int64_t SQFuncState::popTarget()
return npos;
}
int64_t SQFuncState::getStacksize()
int64_t FuncState::getStacksize()
{
return _vlocals.size();
}
int64_t SQFuncState::CountOuters(int64_t stacksize)
int64_t FuncState::CountOuters(int64_t stacksize)
{
int64_t outers = 0;
int64_t k = _vlocals.size() - 1;
while(k >= stacksize) {
SQLocalVarInfo &lvi = _vlocals[k];
rabbit::LocalVarInfo &lvi = _vlocals[k];
k--;
if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
outers++;
@ -321,12 +321,12 @@ int64_t SQFuncState::CountOuters(int64_t stacksize)
return outers;
}
void SQFuncState::setStacksize(int64_t n)
void FuncState::setStacksize(int64_t n)
{
int64_t size=_vlocals.size();
while(size>n){
size--;
SQLocalVarInfo lvi = _vlocals.back();
rabbit::LocalVarInfo lvi = _vlocals.back();
if(sq_type(lvi._name)!=rabbit::OT_NULL){
if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
_outers--;
@ -338,7 +338,7 @@ void SQFuncState::setStacksize(int64_t n)
}
}
bool SQFuncState::isConstant(const rabbit::Object &name,rabbit::Object &e)
bool FuncState::isConstant(const rabbit::Object &name,rabbit::Object &e)
{
rabbit::ObjectPtr val;
if(_table(_sharedstate->_consts)->get(name,val)) {
@ -348,17 +348,17 @@ bool SQFuncState::isConstant(const rabbit::Object &name,rabbit::Object &e)
return false;
}
bool SQFuncState::isLocal(uint64_t stkpos)
bool FuncState::isLocal(uint64_t stkpos)
{
if(stkpos>=_vlocals.size())return false;
else if(sq_type(_vlocals[stkpos]._name)!=rabbit::OT_NULL)return true;
return false;
}
int64_t SQFuncState::pushLocalVariable(const rabbit::Object &name)
int64_t FuncState::pushLocalVariable(const rabbit::Object &name)
{
int64_t pos=_vlocals.size();
SQLocalVarInfo lvi;
rabbit::LocalVarInfo lvi;
lvi._name=name;
lvi._start_op=getCurrentPos()+1;
lvi._pos=_vlocals.size();
@ -369,11 +369,11 @@ int64_t SQFuncState::pushLocalVariable(const rabbit::Object &name)
int64_t SQFuncState::getLocalVariable(const rabbit::Object &name)
int64_t FuncState::getLocalVariable(const rabbit::Object &name)
{
int64_t locals=_vlocals.size();
while(locals>=1){
SQLocalVarInfo &lvi = _vlocals[locals-1];
rabbit::LocalVarInfo &lvi = _vlocals[locals-1];
if(sq_type(lvi._name)==rabbit::OT_STRING && _string(lvi._name)==_string(name)){
return locals-1;
}
@ -382,14 +382,14 @@ int64_t SQFuncState::getLocalVariable(const rabbit::Object &name)
return -1;
}
void SQFuncState::markLocalAsOuter(int64_t pos)
void FuncState::markLocalAsOuter(int64_t pos)
{
SQLocalVarInfo &lvi = _vlocals[pos];
rabbit::LocalVarInfo &lvi = _vlocals[pos];
lvi._end_op = UINT_MINUS_ONE;
_outers++;
}
int64_t SQFuncState::getOuterVariable(const rabbit::Object &name)
int64_t FuncState::getOuterVariable(const rabbit::Object &name)
{
int64_t outers = _outervalues.size();
for(int64_t i = 0; i<outers; i++) {
@ -402,13 +402,13 @@ int64_t SQFuncState::getOuterVariable(const rabbit::Object &name)
if(pos == -1) {
pos = _parent->getOuterVariable(name);
if(pos != -1) {
_outervalues.pushBack(SQOuterVar(name,rabbit::ObjectPtr(int64_t(pos)),otOUTER)); //local
_outervalues.pushBack(rabbit::OuterVar(name,rabbit::ObjectPtr(int64_t(pos)),otOUTER)); //local
return _outervalues.size() - 1;
}
}
else {
_parent->markLocalAsOuter(pos);
_outervalues.pushBack(SQOuterVar(name,rabbit::ObjectPtr(int64_t(pos)),otLOCAL)); //local
_outervalues.pushBack(rabbit::OuterVar(name,rabbit::ObjectPtr(int64_t(pos)),otLOCAL)); //local
return _outervalues.size() - 1;
@ -417,16 +417,16 @@ int64_t SQFuncState::getOuterVariable(const rabbit::Object &name)
return -1;
}
void SQFuncState::addParameter(const rabbit::Object &name)
void FuncState::addParameter(const rabbit::Object &name)
{
pushLocalVariable(name);
_parameters.pushBack(name);
}
void SQFuncState::addLineInfos(int64_t line,bool lineop,bool force)
void FuncState::addLineInfos(int64_t line,bool lineop,bool force)
{
if(_lastline!=line || force){
SQLineInfo li;
rabbit::LineInfo li;
li._line=line;li._op=(getCurrentPos()+1);
if(lineop)addInstruction(_OP_LINE,0,line);
if(_lastline!=line) {
@ -436,12 +436,12 @@ void SQFuncState::addLineInfos(int64_t line,bool lineop,bool force)
}
}
void SQFuncState::discardTarget()
void FuncState::discardTarget()
{
int64_t discardedtarget = popTarget();
int64_t size = _instructions.size();
if(size > 0 && _optimization){
SQInstruction &pi = _instructions[size-1];//previous instruction
rabbit::Instruction &pi = _instructions[size-1];//previous instruction
switch(pi.op) {
case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
if(pi._arg0 == discardedtarget) {
@ -451,11 +451,11 @@ void SQFuncState::discardTarget()
}
}
void SQFuncState::addInstruction(SQInstruction &i)
void FuncState::addInstruction(rabbit::Instruction &i)
{
int64_t size = _instructions.size();
if(size > 0 && _optimization){ //simple optimizer
SQInstruction &pi = _instructions[size-1];//previous instruction
rabbit::Instruction &pi = _instructions[size-1];//previous instruction
switch(i.op) {
case _OP_JZ:
if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
@ -584,24 +584,24 @@ void SQFuncState::addInstruction(SQInstruction &i)
_instructions.pushBack(i);
}
rabbit::Object SQFuncState::createString(const rabbit::Char *s,int64_t len)
rabbit::Object FuncState::createString(const rabbit::Char *s,int64_t len)
{
rabbit::ObjectPtr ns(rabbit::String::create(_sharedstate,s,len));
_table(_strings)->newSlot(ns,(int64_t)1);
return ns;
}
rabbit::Object SQFuncState::createTable()
rabbit::Object FuncState::createTable()
{
rabbit::ObjectPtr nt(rabbit::Table::create(_sharedstate,0));
_table(_strings)->newSlot(nt,(int64_t)1);
return nt;
}
SQFunctionProto *SQFuncState::buildProto()
rabbit::FunctionProto *FuncState::buildProto()
{
SQFunctionProto *f=SQFunctionProto::create(_ss,_instructions.size(),
rabbit::FunctionProto *f=rabbit::FunctionProto::create(_ss,_instructions.size(),
_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
_lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
@ -625,29 +625,29 @@ SQFunctionProto *SQFuncState::buildProto()
for(uint64_t ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
for(uint64_t nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(rabbit::Instruction));
f->_varparams = _varparams;
return f;
}
SQFuncState *SQFuncState::pushChildState(rabbit::SharedState *ss)
FuncState *rabbit::FuncState::pushChildState(rabbit::SharedState *ss)
{
SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
new (child) SQFuncState(ss,this,_errfunc,_errtarget);
FuncState *child = (rabbit::FuncState *)sq_malloc(sizeof(rabbit::FuncState));
new (child) FuncState(ss,this,_errfunc,_errtarget);
_childstates.pushBack(child);
return child;
}
void SQFuncState::popChildState()
void FuncState::popChildState()
{
SQFuncState *child = _childstates.back();
sq_delete(child,SQFuncState);
FuncState *child = _childstates.back();
sq_delete(child,FuncState);
_childstates.popBack();
}
SQFuncState::~SQFuncState()
FuncState::~rabbit::FuncState()
{
while(_childstates.size() > 0)
{

92
rabbit/FuncState.hpp Normal file
View File

@ -0,0 +1,92 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class FuncState {
public:
FuncState(rabbit::SharedState *ss,rabbit::FuncState *parent,compilererrorFunc efunc,void *ed);
~FuncState();
#ifdef _DEBUG_DUMP
void dump(rabbit::FunctionProto *func);
#endif
void error(const rabbit::Char *err);
FuncState *pushChildState(rabbit::SharedState *ss);
void popChildState();
void addInstruction(SQOpcode _op,int64_t arg0=0,int64_t arg1=0,int64_t arg2=0,int64_t arg3=0){rabbit::Instruction i(_op,arg0,arg1,arg2,arg3);addInstruction(i);}
void addInstruction(rabbit::Instruction &i);
void setIntructionParams(int64_t pos,int64_t arg0,int64_t arg1,int64_t arg2=0,int64_t arg3=0);
void setIntructionParam(int64_t pos,int64_t arg,int64_t val);
rabbit::Instruction &getInstruction(int64_t pos){return _instructions[pos];}
void popInstructions(int64_t size){for(int64_t i=0;i<size;i++)_instructions.popBack();}
void setStacksize(int64_t n);
int64_t CountOuters(int64_t stacksize);
void snoozeOpt(){_optimization=false;}
void addDefaultParam(int64_t trg) { _defaultparams.pushBack(trg); }
int64_t getDefaultParamCount() { return _defaultparams.size(); }
int64_t getCurrentPos(){return _instructions.size()-1;}
int64_t getNumericConstant(const int64_t cons);
int64_t getNumericConstant(const float_t cons);
int64_t pushLocalVariable(const rabbit::Object &name);
void addParameter(const rabbit::Object &name);
//void addOuterValue(const rabbit::Object &name);
int64_t getLocalVariable(const rabbit::Object &name);
void markLocalAsOuter(int64_t pos);
int64_t getOuterVariable(const rabbit::Object &name);
int64_t generateCode();
int64_t getStacksize();
int64_t calcStackFramesize();
void addLineInfos(int64_t line,bool lineop,bool force=false);
rabbit::FunctionProto *buildProto();
int64_t allocStackPos();
int64_t pushTarget(int64_t n=-1);
int64_t popTarget();
int64_t topTarget();
int64_t getUpTarget(int64_t n);
void discardTarget();
bool isLocal(uint64_t stkpos);
rabbit::Object createString(const rabbit::Char *s,int64_t len = -1);
rabbit::Object createTable();
bool isConstant(const rabbit::Object &name,rabbit::Object &e);
int64_t _returnexp;
etk::Vector<rabbit::LocalVarInfo> _vlocals;
etk::Vector<int64_t> _targetstack;
int64_t _stacksize;
bool _varparams;
bool _bgenerator;
etk::Vector<int64_t> _unresolvedbreaks;
etk::Vector<int64_t> _unresolvedcontinues;
etk::Vector<rabbit::ObjectPtr> _functions;
etk::Vector<rabbit::ObjectPtr> _parameters;
etk::Vector<rabbit::OuterVar> _outervalues;
rabbit::InstructionVec _instructions;
etk::Vector<rabbit::LocalVarInfo> _localvarinfos;
rabbit::ObjectPtr _literals;
rabbit::ObjectPtr _strings;
rabbit::ObjectPtr _name;
rabbit::ObjectPtr _sourcename;
int64_t _nliterals;
etk::Vector<rabbit::LineInfo> _lineinfos;
FuncState *_parent;
etk::Vector<int64_t> _scope_blocks;
etk::Vector<int64_t> _breaktargets;
etk::Vector<int64_t> _continuetargets;
etk::Vector<int64_t> _defaultparams;
int64_t _lastline;
int64_t _traps; //contains number of nested exception traps
int64_t _outers;
bool _optimization;
rabbit::SharedState *_sharedstate;
etk::Vector<FuncState*> _childstates;
int64_t getConstant(const rabbit::Object &cons);
private:
compilererrorFunc _errfunc;
void *_errtarget;
rabbit::SharedState *_ss;
};
}

224
rabbit/FunctionProto.cpp Normal file
View File

@ -0,0 +1,224 @@
/**
* @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/FunctionProto.hpp>
const rabbit::Char* rabbit::FunctionProto::getLocal(rabbit::VirtualMachine *vm,uint64_t stackbase,uint64_t nseq,uint64_t nop)
{
uint64_t nvars=_nlocalvarinfos;
const rabbit::Char *res=NULL;
if(nvars>=nseq){
for(uint64_t i=0;i<nvars;i++){
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
{
if(nseq==0){
vm->push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
res=_stringval(_localvarinfos[i]._name);
break;
}
nseq--;
}
}
}
return res;
}
int64_t rabbit::FunctionProto::getLine(rabbit::Instruction *curr)
{
int64_t op = (int64_t)(curr-_instructions);
int64_t line=_lineinfos[0]._line;
int64_t low = 0;
int64_t high = _nlineinfos - 1;
int64_t mid = 0;
while(low <= high)
{
mid = low + ((high - low) >> 1);
int64_t curop = _lineinfos[mid]._op;
if(curop > op)
{
high = mid - 1;
}
else if(curop < op) {
if(mid < (_nlineinfos - 1)
&& _lineinfos[mid + 1]._op >= op) {
break;
}
low = mid + 1;
}
else { //equal
break;
}
}
while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
line = _lineinfos[mid]._line;
return line;
}
rabbit::FunctionProto::FunctionProto(rabbit::SharedState *ss)
{
_stacksize=0;
_bgenerator=false;
}
rabbit::FunctionProto::~FunctionProto()
{
}
bool rabbit::FunctionProto::save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write)
{
int64_t i,nliterals = _nliterals,nparameters = _nparameters;
int64_t noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
int64_t nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
int64_t ndefaultparams = _ndefaultparams;
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(WriteObject(v,up,write,_sourcename));
_CHECK_IO(WriteObject(v,up,write,_name));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
_CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
_CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
_CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
_CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
_CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
_CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
_CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nliterals;i++){
_CHECK_IO(WriteObject(v,up,write,_literals[i]));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nparameters;i++){
_CHECK_IO(WriteObject(v,up,write,_parameters[i]));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<noutervalues;i++){
_CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(uint64_t)));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nlocalvarinfos;i++){
rabbit::LocalVarInfo &lvi=_localvarinfos[i];
_CHECK_IO(WriteObject(v,up,write,lvi._name));
_CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(uint64_t)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(uint64_t)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(uint64_t)));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(rabbit::LineInfo)*nlineinfos));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(int64_t)*ndefaultparams));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(rabbit::Instruction)*ninstructions));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nfunctions;i++){
_CHECK_IO(_funcproto(_functions[i])->save(v,up,write));
}
_CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
_CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
return true;
}
bool rabbit::FunctionProto::load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret)
{
int64_t i, nliterals,nparameters;
int64_t noutervalues ,nlocalvarinfos ;
int64_t nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
rabbit::ObjectPtr sourcename, name;
rabbit::ObjectPtr o;
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(ReadObject(v, up, read, sourcename));
_CHECK_IO(ReadObject(v, up, read, name));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));
_CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
_CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
_CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
_CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
_CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
_CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
_CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
rabbit::FunctionProto *f = rabbit::FunctionProto::create(NULL,ninstructions,nliterals,nparameters,
nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
rabbit::ObjectPtr proto = f; //gets a ref in case of failure
f->_sourcename = sourcename;
f->_name = name;
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0;i < nliterals; i++){
_CHECK_IO(ReadObject(v, up, read, o));
f->_literals[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nparameters; i++){
_CHECK_IO(ReadObject(v, up, read, o));
f->_parameters[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < noutervalues; i++){
uint64_t type;
rabbit::ObjectPtr name;
_CHECK_IO(SafeRead(v,read,up, &type, sizeof(uint64_t)));
_CHECK_IO(ReadObject(v, up, read, o));
_CHECK_IO(ReadObject(v, up, read, name));
f->_outervalues[i] = rabbit::OuterVar(name,o, (rabbit::OuterType)type);
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nlocalvarinfos; i++){
rabbit::LocalVarInfo lvi;
_CHECK_IO(ReadObject(v, up, read, lvi._name));
_CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(uint64_t)));
_CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(uint64_t)));
_CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(uint64_t)));
f->_localvarinfos[i] = lvi;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(rabbit::LineInfo)*nlineinfos));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(int64_t)*ndefaultparams));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(rabbit::Instruction)*ninstructions));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nfunctions; i++){
_CHECK_IO(_funcproto(o)->load(v, up, read, o));
f->_functions[i] = o;
}
_CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
_CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
_CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
ret = f;
return true;
}

105
rabbit/FunctionProto.hpp Normal file
View File

@ -0,0 +1,105 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(rabbit::FunctionProto) \
+((ni-1)*sizeof(rabbit::Instruction))+(nl*sizeof(rabbit::ObjectPtr)) \
+(nparams*sizeof(rabbit::ObjectPtr))+(nfuncs*sizeof(rabbit::ObjectPtr)) \
+(nouters*sizeof(rabbit::OuterVar))+(nlineinf*sizeof(rabbit::LineInfo)) \
+(localinf*sizeof(rabbit::LocalVarInfo))+(defparams*sizeof(int64_t)))
class FunctionProto : public rabbit::RefCounted {
private:
FunctionProto(rabbit::SharedState *ss);
~FunctionProto();
public:
static rabbit::FunctionProto *create(rabbit::SharedState *ss,int64_t ninstructions,
int64_t nliterals,int64_t nparameters,
int64_t nfunctions,int64_t noutervalues,
int64_t nlineinfos,int64_t nlocalvarinfos,int64_t ndefaultparams)
{
rabbit::FunctionProto *f;
//I compact the whole class and members in a single memory allocation
f = (rabbit::FunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
new (f) rabbit::FunctionProto(ss);
f->_ninstructions = ninstructions;
f->_literals = (rabbit::ObjectPtr*)&f->_instructions[ninstructions];
f->_nliterals = nliterals;
f->_parameters = (rabbit::ObjectPtr*)&f->_literals[nliterals];
f->_nparameters = nparameters;
f->_functions = (rabbit::ObjectPtr*)&f->_parameters[nparameters];
f->_nfunctions = nfunctions;
f->_outervalues = (rabbit::OuterVar*)&f->_functions[nfunctions];
f->_noutervalues = noutervalues;
f->_lineinfos = (rabbit::LineInfo *)&f->_outervalues[noutervalues];
f->_nlineinfos = nlineinfos;
f->_localvarinfos = (rabbit::LocalVarInfo *)&f->_lineinfos[nlineinfos];
f->_nlocalvarinfos = nlocalvarinfos;
f->_defaultparams = (int64_t *)&f->_localvarinfos[nlocalvarinfos];
f->_ndefaultparams = ndefaultparams;
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nliterals,f->_literals);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nparameters,f->_parameters);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nfunctions,f->_functions);
_CONSTRUCT_VECTOR(rabbit::OuterVar,f->_noutervalues,f->_outervalues);
//_CONSTRUCT_VECTOR(rabbit::LineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
_CONSTRUCT_VECTOR(rabbit::LocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
return f;
}
void release(){
_DESTRUCT_VECTOR(ObjectPtr,_nliterals,_literals);
_DESTRUCT_VECTOR(ObjectPtr,_nparameters,_parameters);
_DESTRUCT_VECTOR(ObjectPtr,_nfunctions,_functions);
_DESTRUCT_VECTOR(rabbit::OuterVar,_noutervalues,_outervalues);
//_DESTRUCT_VECTOR(rabbit::LineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
_DESTRUCT_VECTOR(rabbit::LocalVarInfo,_nlocalvarinfos,_localvarinfos);
int64_t size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
this->~rabbit::FunctionProto();
sq_vm_free(this,size);
}
const rabbit::Char* getLocal(rabbit::VirtualMachine *v,uint64_t stackbase,uint64_t nseq,uint64_t nop);
int64_t getLine(rabbit::Instruction *curr);
bool save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write);
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::ObjectPtr _sourcename;
rabbit::ObjectPtr _name;
int64_t _stacksize;
bool _bgenerator;
int64_t _varparams;
int64_t _nlocalvarinfos;
rabbit::LocalVarInfo *_localvarinfos;
int64_t _nlineinfos;
rabbit::LineInfo *_lineinfos;
int64_t _nliterals;
rabbit::ObjectPtr *_literals;
int64_t _nparameters;
rabbit::ObjectPtr *_parameters;
int64_t _nfunctions;
rabbit::ObjectPtr *_functions;
int64_t _noutervalues;
rabbit::OuterVar *_outervalues;
int64_t _ndefaultparams;
int64_t *_defaultparams;
int64_t _ninstructions;
rabbit::Instruction _instructions[1];
};
}

87
rabbit/Generator.cpp Normal file
View File

@ -0,0 +1,87 @@
/**
* @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/Generator.hpp>
bool rabbit::Generator::yield(rabbit::VirtualMachine *v,int64_t target)
{
if(_state==eSuspended) { v->raise_error(_SC("internal vm error, yielding dead generator")); return false;}
if(_state==eDead) { v->raise_error(_SC("internal vm error, yielding a dead generator")); return false; }
int64_t size = v->_top-v->_stackbase;
_stack.resize(size);
rabbit::Object _this = v->_stack[v->_stackbase];
_stack[0] = ISREFCOUNTED(sq_type(_this)) ? rabbit::ObjectPtr(_refcounted(_this)->getWeakRef(sq_type(_this))) : _this;
for(int64_t n =1; n<target; n++) {
_stack[n] = v->_stack[v->_stackbase+n];
}
for(int64_t j =0; j < size; j++)
{
v->_stack[v->_stackbase+j].Null();
}
_ci = *v->ci;
_ci._generator=NULL;
for(int64_t i=0;i<_ci._etraps;i++) {
_etraps.pushBack(v->_etraps.back());
v->_etraps.popBack();
// store relative stack base and size in case of resume to other _top
rabbit::ExceptionTrap &et = _etraps.back();
et._stackbase -= v->_stackbase;
et._stacksize -= v->_stackbase;
}
_state=eSuspended;
return true;
}
bool rabbit::Generator::resume(rabbit::VirtualMachine *v,rabbit::ObjectPtr &dest)
{
if(_state==eDead){ v->raise_error(_SC("resuming dead generator")); return false; }
if(_state==eRunning){ v->raise_error(_SC("resuming active generator")); return false; }
int64_t size = _stack.size();
int64_t target = &dest - &(v->_stack[v->_stackbase]);
assert(target>=0 && target<=255);
int64_t newbase = v->_top;
if(!v->enterFrame(v->_top, v->_top + size, false))
return false;
v->ci->_generator = this;
v->ci->_target = (int32_t)target;
v->ci->_closure = _ci._closure;
v->ci->_ip = _ci._ip;
v->ci->_literals = _ci._literals;
v->ci->_ncalls = _ci._ncalls;
v->ci->_etraps = _ci._etraps;
v->ci->_root = _ci._root;
for(int64_t i=0;i<_ci._etraps;i++) {
v->_etraps.pushBack(_etraps.back());
_etraps.popBack();
rabbit::ExceptionTrap &et = v->_etraps.back();
// restore absolute stack base and size
et._stackbase += newbase;
et._stacksize += newbase;
}
rabbit::Object _this = _stack[0];
v->_stack[v->_stackbase] = sq_type(_this) == rabbit::OT_WEAKREF ? _weakref(_this)->_obj : _this;
for(int64_t n = 1; n<size; n++) {
v->_stack[v->_stackbase+n] = _stack[n];
_stack[n].Null();
}
_state=eRunning;
if (v->_debughook)
v->callDebugHook(_SC('c'));
return true;
}

47
rabbit/Generator.hpp Normal file
View File

@ -0,0 +1,47 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class Generator : public rabbit::RefCounted {
public:
enum rabbit::GeneratorState{eRunning,eSuspended,eDead};
private:
rabbit::Generator(rabbit::SharedState *ss,rabbit::Closure *closure){
_closure=closure;
_state=eRunning;
_ci._generator=NULL;
}
public:
static rabbit::Generator *create(rabbit::SharedState *ss,rabbit::Closure *closure){
rabbit::Generator *nc=(rabbit::Generator*)SQ_MALLOC(sizeof(rabbit::Generator));
new (nc) rabbit::Generator(ss,closure);
return nc;
}
~rabbit::Generator()
{
}
void kill(){
_state=eDead;
_stack.resize(0);
_closure.Null();}
void release(){
sq_delete(this,rabbit::Generator);
}
bool yield(rabbit::VirtualMachine *v,int64_t target);
bool resume(rabbit::VirtualMachine *v,rabbit::ObjectPtr &dest);
rabbit::ObjectPtr _closure;
etk::Vector<rabbit::ObjectPtr> _stack;
rabbit::VirtualMachine::callInfo _ci;
etk::Vector<rabbit::ExceptionTrap> _etraps;
rabbit::GeneratorState _state;
};
}

9
rabbit/Instruction.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/Instruction.hpp>

12
rabbit/Instruction.hpp Normal file
View File

@ -0,0 +1,12 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
}

View File

@ -5,10 +5,7 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#include <rabbit/sqpcheader.hpp>
#include <ctype.h>
#include <stdlib.h>
#include <rabbit/Lexer.hpp>
#include <rabbit/sqcompiler.hpp>
@ -23,13 +20,13 @@
#define TERMINATE_BUFFER() {_longstr.pushBack(_SC('\0'));}
#define ADD_KEYWORD(key,id) _keywords->newSlot( rabbit::String::create(ss, _SC(#key)) ,int64_t(id))
SQLexer::SQLexer(){}
SQLexer::~SQLexer()
rabbit::Lexer::Lexer(){}
rabbit::Lexer::~Lexer()
{
_keywords->release();
}
void SQLexer::init(rabbit::SharedState *ss, SQLEXREADFUNC rg, rabbit::UserPointer up,compilererrorFunc efunc,void *ed)
void rabbit::Lexer::init(rabbit::SharedState *ss, SQLEXREADFUNC rg, rabbit::UserPointer up,compilererrorFunc efunc,void *ed)
{
_errfunc = efunc;
_errtarget = ed;
@ -84,12 +81,12 @@ void SQLexer::init(rabbit::SharedState *ss, SQLEXREADFUNC rg, rabbit::UserPointe
next();
}
void SQLexer::error(const rabbit::Char *err)
void rabbit::Lexer::error(const rabbit::Char *err)
{
_errfunc(_errtarget,err);
}
void SQLexer::next()
void rabbit::Lexer::next()
{
int64_t t = _readf(_up);
if(t > MAX_CHAR) error(_SC("Invalid character"));
@ -101,7 +98,7 @@ void SQLexer::next()
_reached_eof = SQTrue;
}
const rabbit::Char *SQLexer::tok2Str(int64_t tok)
const rabbit::Char *rabbit::Lexer::tok2Str(int64_t tok)
{
rabbit::ObjectPtr itr, key, val;
int64_t nitr;
@ -113,7 +110,7 @@ const rabbit::Char *SQLexer::tok2Str(int64_t tok)
return NULL;
}
void SQLexer::lexBlockComment()
void rabbit::Lexer::lexBlockComment()
{
bool done = false;
while(!done) {
@ -125,12 +122,12 @@ void SQLexer::lexBlockComment()
}
}
}
void SQLexer::lexLineComment()
void rabbit::Lexer::lexLineComment()
{
do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
}
int64_t SQLexer::Lex()
int64_t rabbit::Lexer::Lex()
{
_lasttokenline = _currentline;
while(CUR_CHAR != RABBIT_EOB) {
@ -285,7 +282,7 @@ int64_t SQLexer::Lex()
return 0;
}
int64_t SQLexer::getIDType(const rabbit::Char *s,int64_t len)
int64_t rabbit::Lexer::getIDType(const rabbit::Char *s,int64_t len)
{
rabbit::ObjectPtr t;
if(_keywords->getStr(s,len, t)) {
@ -296,7 +293,7 @@ int64_t SQLexer::getIDType(const rabbit::Char *s,int64_t len)
#ifdef SQUNICODE
#if WCHAR_SIZE == 2
int64_t SQLexer::addUTF16(uint64_t ch)
int64_t rabbit::Lexer::addUTF16(uint64_t ch)
{
if (ch >= 0x10000)
{
@ -312,7 +309,7 @@ int64_t SQLexer::addUTF16(uint64_t ch)
}
#endif
#else
int64_t SQLexer::addUTF8(uint64_t ch)
int64_t rabbit::Lexer::addUTF8(uint64_t ch)
{
if (ch < 0x80) {
APPEND_CHAR((char)ch);
@ -340,7 +337,7 @@ int64_t SQLexer::addUTF8(uint64_t ch)
}
#endif
int64_t SQLexer::processStringHexEscape(rabbit::Char *dest, int64_t maxdigits)
int64_t rabbit::Lexer::processStringHexEscape(rabbit::Char *dest, int64_t maxdigits)
{
NEXT();
if (!isxdigit(CUR_CHAR)) error(_SC("hexadecimal number expected"));
@ -354,7 +351,7 @@ int64_t SQLexer::processStringHexEscape(rabbit::Char *dest, int64_t maxdigits)
return n;
}
int64_t SQLexer::readString(int64_t ndelim,bool verbatim)
int64_t rabbit::Lexer::readString(int64_t ndelim,bool verbatim)
{
INIT_TEMP_STRING();
NEXT();
@ -482,7 +479,7 @@ int64_t isexponent(int64_t c) { return c == 'e' || c=='E'; }
#define MAX_HEX_DIGITS (sizeof(int64_t)*2)
int64_t SQLexer::readNumber()
int64_t rabbit::Lexer::readNumber()
{
#define TINT 1
#define TFLOAT 2
@ -551,7 +548,7 @@ int64_t SQLexer::readNumber()
return 0;
}
int64_t SQLexer::readId()
int64_t rabbit::Lexer::readId()
{
int64_t res;
INIT_TEMP_STRING();

61
rabbit/Lexer.hpp Normal file
View File

@ -0,0 +1,61 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
#ifdef SQUNICODE
typedef Char LexChar;
#else
typedef unsigned char LexChar;
#endif
class Lexer {
public:
Lexer();
~Lexer();
void init(SharedState *ss,SQLEXREADFUNC rg,UserPointer up,compilererrorFunc efunc,void *ed);
void error(const Char *err);
int64_t Lex();
const Char *tok2Str(int64_t tok);
private:
int64_t getIDType(const Char *s,int64_t len);
int64_t readString(int64_t ndelim,bool verbatim);
int64_t readNumber();
void lexBlockComment();
void lexLineComment();
int64_t readId();
void next();
#ifdef SQUNICODE
#if WCHAR_SIZE == 2
int64_t addUTF16(uint64_t ch);
#endif
#else
int64_t addUTF8(uint64_t ch);
#endif
int64_t processStringHexEscape(Char *dest, int64_t maxdigits);
int64_t _curtoken;
Table *_keywords;
Bool _reached_eof;
public:
int64_t _prevtoken;
int64_t _currentline;
int64_t _lasttokenline;
int64_t _currentcolumn;
const Char *_svalue;
int64_t _nvalue;
float_t _fvalue;
SQLEXREADFUNC _readf;
UserPointer _up;
LexChar _currdata;
SharedState *_sharedstate;
etk::Vector<Char> _longstr;
compilererrorFunc _errfunc;
void *_errtarget;
};
}

9
rabbit/LineInfo.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/LineInfo.hpp>

16
rabbit/LineInfo.hpp Normal file
View File

@ -0,0 +1,16 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class LineInfo {
public:
int64_t _line;
int64_t _op;
};
}

9
rabbit/LocalVarInfo.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/LocalVarInfo.hpp>

26
rabbit/LocalVarInfo.hpp Normal file
View File

@ -0,0 +1,26 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class LocalVarInfo {
public:
LocalVarInfo():_start_op(0),_end_op(0),_pos(0){}
LocalVarInfo(const LocalVarInfo &lvi) {
_name=lvi._name;
_start_op=lvi._start_op;
_end_op=lvi._end_op;
_pos=lvi._pos;
}
rabbit::ObjectPtr _name;
uint64_t _start_op;
uint64_t _end_op;
uint64_t _pos;
};
}

View File

9
rabbit/NativeClosure.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/NativeClosure.hpp>

63
rabbit/NativeClosure.hpp Normal file
View File

@ -0,0 +1,63 @@
/**
* @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)
*/
#pragma once
#include <etk/types.hpp>
namespace rabbit {
#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(rabbit::NativeClosure) + (noutervalues*sizeof(rabbit::ObjectPtr)))
class NativeClosure : public rabbit::RefCounted {
private:
rabbit::NativeClosure(rabbit::SharedState *ss,SQFUNCTION func){
_function=func;
_env = NULL;
}
public:
static rabbit::NativeClosure *create(rabbit::SharedState *ss,SQFUNCTION func,int64_t nouters)
{
int64_t size = _CALC_NATVIVECLOSURE_SIZE(nouters);
rabbit::NativeClosure *nc=(rabbit::NativeClosure*)SQ_MALLOC(size);
new (nc) rabbit::NativeClosure(ss,func);
nc->_outervalues = (rabbit::ObjectPtr *)(nc + 1);
nc->_noutervalues = nouters;
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,nc->_noutervalues,nc->_outervalues);
return nc;
}
rabbit::NativeClosure *clone()
{
rabbit::NativeClosure * ret = rabbit::NativeClosure::create(NULL,_function,_noutervalues);
ret->_env = _env;
if(ret->_env) __ObjaddRef(ret->_env);
ret->_name = _name;
_COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);
ret->_typecheck = _typecheck;
ret->_nparamscheck = _nparamscheck;
return ret;
}
~rabbit::NativeClosure()
{
__Objrelease(_env);
}
void release(){
int64_t size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);
_DESTRUCT_VECTOR(ObjectPtr,_noutervalues,_outervalues);
this->~rabbit::NativeClosure();
sq_free(this,size);
}
int64_t _nparamscheck;
etk::Vector<int64_t> _typecheck;
rabbit::ObjectPtr *_outervalues;
uint64_t _noutervalues;
rabbit::WeakRef *_env;
SQFUNCTION _function;
rabbit::ObjectPtr _name;
};
}

View File

@ -53,15 +53,15 @@ RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_TABLE, rabbit::Table, pTable)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLASS, rabbit::Class, pClass)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_INSTANCE, rabbit::Instance, pInstance)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_ARRAY, rabbit::Array, pArray)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_OUTER, SQOuter, pOuter)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_GENERATOR, SQGenerator, pGenerator)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_CLOSURE, rabbit::Closure, pClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_NATIVECLOSURE, rabbit::NativeClosure, pNativeClosure)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_OUTER, rabbit::Outer, pOuter)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_GENERATOR, rabbit::Generator, pGenerator)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_STRING, rabbit::String, pString)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_USERDATA, rabbit::UserData, pUserData)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_WEAKREF, rabbit::WeakRef, pWeakRef)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_THREAD, rabbit::VirtualMachine, pThread)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_FUNCPROTO, SQFunctionProto, pFunctionProto)
RABBIT_OBJ_REF_TYPE_INSTANCIATE(rabbit::OT_FUNCPROTO, rabbit::FunctionProto, pFunctionProto)
RABBIT_SCALAR_TYPE_INSTANCIATE(rabbit::OT_INTEGER, int64_t, nInteger)
RABBIT_SCALAR_TYPE_INSTANCIATE(rabbit::OT_FLOAT, float_t, fFloat)

View File

@ -37,15 +37,15 @@ namespace rabbit {
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLASS, rabbit::Class, pClass)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_INSTANCE, rabbit::Instance, pInstance)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_ARRAY, rabbit::Array, pArray)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLOSURE, SQClosure, pClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_NATIVECLOSURE, SQNativeClosure, pNativeClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_OUTER, SQOuter, pOuter)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_GENERATOR, SQGenerator, pGenerator)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_CLOSURE, rabbit::Closure, pClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_NATIVECLOSURE, rabbit::NativeClosure, pNativeClosure)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_OUTER, rabbit::Outer, pOuter)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_GENERATOR, rabbit::Generator, pGenerator)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_STRING, rabbit::String, pString)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_USERDATA, UserData, pUserData)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_WEAKREF, WeakRef, pWeakRef)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_THREAD, VirtualMachine, pThread)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_FUNCPROTO, SQFunctionProto, pFunctionProto)
RABBIT_OBJ_REF_TYPE_DECLARE(rabbit::OT_FUNCPROTO, rabbit::FunctionProto, pFunctionProto)
RABBIT_SCALAR_TYPE_DECLARE(rabbit::OT_INTEGER, int64_t, nInteger)
RABBIT_SCALAR_TYPE_DECLARE(rabbit::OT_FLOAT, float_t, fFloat)

View File

@ -13,13 +13,13 @@
namespace rabbit {
union ObjectValue {
struct SQClosure *pClosure;
struct SQOuter *pOuter;
struct SQGenerator *pGenerator;
struct SQNativeClosure *pNativeClosure;
struct rabbit::Closure *pClosure;
struct rabbit::Outer *pOuter;
struct rabbit::Generator *pGenerator;
struct rabbit::NativeClosure *pNativeClosure;
int64_t nInteger;
float_t fFloat;
struct SQFunctionProto *pFunctionProto;
struct rabbit::FunctionProto *pFunctionProto;
rabbit::Table* pTable;
rabbit::String* pString;

9
rabbit/Outer.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/Outer.hpp>

37
rabbit/Outer.hpp Normal file
View File

@ -0,0 +1,37 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class Outer : public rabbit::RefCounted {
private:
rabbit::Outer(rabbit::SharedState *ss, rabbit::ObjectPtr *outer){
_valptr = outer;
_next = NULL;
}
public:
static rabbit::Outer *create(rabbit::SharedState *ss, rabbit::ObjectPtr *outer) {
rabbit::Outer *nc = (rabbit::Outer*)SQ_MALLOC(sizeof(rabbit::Outer));
new (nc) rabbit::Outer(ss, outer);
return nc;
}
~Outer() {
}
void release()
{
this->~rabbit::Outer();
sq_vm_free(this,sizeof(rabbit::Outer));
}
rabbit::ObjectPtr *_valptr; /* pointer to value on stack, or _value below */
int64_t _idx; /* idx in stack array, for relocation */
rabbit::ObjectPtr _value; /* value of outer after stack frame is closed */
rabbit::Outer *_next; /* pointer to next outer when frame is open */
};
}

9
rabbit/OuterVar.cpp Normal file
View File

@ -0,0 +1,9 @@
/**
* @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/OuterVar.hpp>

34
rabbit/OuterVar.hpp Normal file
View File

@ -0,0 +1,34 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
enum OuterType {
otLOCAL = 0,
otOUTER = 1
};
class OuterVar {
public:
OuterVar(){}
OuterVar(const ObjectPtr &name,const ObjectPtr &src, OuterType t) {
_name = name;
_src=src;
_type=t;
}
OuterVar(const OuterVar &ov) {
_type=ov._type;
_src=ov._src;
_name=ov._name;
}
rabbit::OuterType _type;
rabbit::ObjectPtr _name;
rabbit::ObjectPtr _src;
};
}

View File

@ -144,13 +144,13 @@ void rabbit::RefTable::allocNodes(uint64_t size)
for(n = 0; n < size - 1; n++) {
bucks[n] = NULL;
temp->refs = 0;
new (&temp->obj) rabbit::ObjectPtr;
new ((char*)&temp->obj) ObjectPtr;
temp->next = temp+1;
temp++;
}
bucks[n] = NULL;
temp->refs = 0;
new (&temp->obj) rabbit::ObjectPtr;
new ((char*)&temp->obj) ObjectPtr;
temp->next = NULL;
_freelist = nodes;
_nodes = nodes;

View File

@ -5,18 +5,17 @@
* @copyright 2003-2017, Alberto DEMICHELIS, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <rabbit/SharedState.hpp>
#include <rabbit/Table.hpp>
#include <rabbit/String.hpp>
#include <rabbit/RegFunction.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){
SQNativeClosure *nc = SQNativeClosure::create(ss,funcz[i].f,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 && !compileTypemask(nc->_typecheck,funcz[i].typemask))

View File

@ -8,8 +8,10 @@
#pragma once
#include <etk/types.hpp>
#include <etk/Vector.hpp>
#include <rabbit/sqconfig.hpp>
#include <rabbit/RefTable.hpp>
#include <rabbit/rabbit.hpp>
namespace rabbit {
class StringTable;

View File

@ -376,9 +376,9 @@ bool rabbit::VirtualMachine::init(rabbit::VirtualMachine *friendvm, int64_t stac
}
bool rabbit::VirtualMachine::startcall(SQClosure *closure,int64_t target,int64_t args,int64_t stackbase,bool tailcall)
bool rabbit::VirtualMachine::startcall(rabbit::Closure *closure,int64_t target,int64_t args,int64_t stackbase,bool tailcall)
{
SQFunctionProto *func = closure->_function;
rabbit::FunctionProto *func = closure->_function;
int64_t paramssize = func->_nparameters;
const int64_t newtop = stackbase + func->_stacksize;
@ -434,8 +434,8 @@ bool rabbit::VirtualMachine::startcall(SQClosure *closure,int64_t target,int64_t
}
if (closure->_function->_bgenerator) {
SQFunctionProto *f = closure->_function;
SQGenerator *gen = SQGenerator::create(_get_shared_state(this), closure);
rabbit::FunctionProto *f = closure->_function;
rabbit::Generator *gen = rabbit::Generator::create(_get_shared_state(this), closure);
if(!gen->yield(this,f->_stacksize))
return false;
rabbit::ObjectPtr temp;
@ -562,8 +562,8 @@ bool rabbit::VirtualMachine::FOREACH_OP(rabbit::ObjectPtr &o1,rabbit::ObjectPtr
}
break;
case rabbit::OT_GENERATOR:
if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
if(_generator(o1)->_state == SQGenerator::eSuspended) {
if(_generator(o1)->_state == rabbit::Generator::eDead) _FINISH(exitpos);
if(_generator(o1)->_state == rabbit::Generator::eSuspended) {
int64_t idx = 0;
if(sq_type(o4) == rabbit::OT_INTEGER) {
idx = _integer(o4) + 1;
@ -585,13 +585,13 @@ bool rabbit::VirtualMachine::FOREACH_OP(rabbit::ObjectPtr &o1,rabbit::ObjectPtr
#define _GUARD(exp) { if(!exp) { SQ_THROW();} }
bool rabbit::VirtualMachine::CLOSURE_OP(rabbit::ObjectPtr &target, SQFunctionProto *func)
bool rabbit::VirtualMachine::CLOSURE_OP(rabbit::ObjectPtr &target, rabbit::FunctionProto *func)
{
int64_t nouters;
SQClosure *closure = SQClosure::create(_get_shared_state(this), func,_table(_roottable)->getWeakRef(rabbit::OT_TABLE));
rabbit::Closure *closure = rabbit::Closure::create(_get_shared_state(this), func,_table(_roottable)->getWeakRef(rabbit::OT_TABLE));
if((nouters = func->_noutervalues)) {
for(int64_t i = 0; i<nouters; i++) {
SQOuterVar &v = func->_outervalues[i];
rabbit::OuterVar &v = func->_outervalues[i];
switch(v._type){
case otLOCAL:
findOuter(closure->_outervalues[i], &STK(_integer(v._src)));
@ -671,7 +671,7 @@ bool rabbit::VirtualMachine::IsFalse(rabbit::ObjectPtr &o)
}
return false;
}
extern SQInstructionDesc g_InstrDesc[];
extern rabbit::InstructionDesc g_InstrDesc[];
bool rabbit::VirtualMachine::execute(rabbit::ObjectPtr &closure, int64_t nargs, int64_t stackbase,rabbit::ObjectPtr &outres, rabbit::Bool raiseerror,ExecutionType et)
{
if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { raise_error(_SC("Native stack overflow")); return false; }
@ -710,7 +710,7 @@ exception_restore:
{
for(;;)
{
const SQInstruction &_i_ = *ci->_ip++;
const rabbit::Instruction &_i_ = *ci->_ip++;
//dumpstack(_stackbase);
//scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-_closure(ci->_closure)->_function->_instructions,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
switch(_i_.op)
@ -885,14 +885,14 @@ exception_restore:
continue;
case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
case _OP_GETOUTER: {
SQClosure *cur_cls = _closure(ci->_closure);
SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
rabbit::Closure *cur_cls = _closure(ci->_closure);
rabbit::Outer *otr = _outer(cur_cls->_outervalues[arg1]);
TARGET = *(otr->_valptr);
}
continue;
case _OP_SETOUTER: {
SQClosure *cur_cls = _closure(ci->_closure);
SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
rabbit::Closure *cur_cls = _closure(ci->_closure);
rabbit::Outer *otr = _outer(cur_cls->_outervalues[arg1]);
*(otr->_valptr) = STK(arg2);
if(arg0 != 0xFF) {
TARGET = STK(arg2);
@ -994,8 +994,8 @@ exception_restore:
raise_error(_SC("attempt to perform a bitwise op on a %s"), getTypeName(STK(arg1)));
SQ_THROW();
case _OP_CLOSURE: {
SQClosure *c = ci->_closure._unVal.pClosure;
SQFunctionProto *fp = c->_function;
rabbit::Closure *c = ci->_closure._unVal.pClosure;
rabbit::FunctionProto *fp = c->_function;
if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
continue;
}
@ -1026,13 +1026,13 @@ exception_restore:
continue;
case _OP_POSTFOREACH:
assert(sq_type(STK(arg0)) == rabbit::OT_GENERATOR);
if(_generator(STK(arg0))->_state == SQGenerator::eDead)
if(_generator(STK(arg0))->_state == rabbit::Generator::eDead)
ci->_ip += (sarg1 - 1);
continue;
case _OP_CLONE: _GUARD(clone(STK(arg1), TARGET)); continue;
case _OP_TYPEOF: _GUARD(typeOf(STK(arg1), TARGET)) continue;
case _OP_PUSHTRAP:{
SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
rabbit::Instruction *_iv = _closure(ci->_closure)->_function->_instructions;
_etraps.pushBack(rabbit::ExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
ci->_etraps++;
}
@ -1049,7 +1049,7 @@ exception_restore:
_GUARD(newSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : rabbit::ObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
continue;
case _OP_GETBASE:{
SQClosure *clo = _closure(ci->_closure);
rabbit::Closure *clo = _closure(ci->_closure);
if(clo->_base) {
TARGET = clo->_base;
}
@ -1127,7 +1127,7 @@ void rabbit::VirtualMachine::callerrorHandler(rabbit::ObjectPtr &error)
void rabbit::VirtualMachine::callDebugHook(int64_t type,int64_t forcedline)
{
_debughook = false;
SQFunctionProto *func=_closure(ci->_closure)->_function;
rabbit::FunctionProto *func=_closure(ci->_closure)->_function;
if(_debughook_native) {
const rabbit::Char *src = sq_type(func->_sourcename) == rabbit::OT_STRING?_stringval(func->_sourcename):NULL;
const rabbit::Char *fname = sq_type(func->_name) == rabbit::OT_STRING?_stringval(func->_name):NULL;
@ -1148,7 +1148,7 @@ void rabbit::VirtualMachine::callDebugHook(int64_t type,int64_t forcedline)
_debughook = true;
}
bool rabbit::VirtualMachine::callNative(SQNativeClosure *nclosure, int64_t nargs, int64_t newbase, rabbit::ObjectPtr &retval, int32_t target,bool &suspend, bool &tailcall)
bool rabbit::VirtualMachine::callNative(rabbit::NativeClosure *nclosure, int64_t nargs, int64_t newbase, rabbit::ObjectPtr &retval, int32_t target,bool &suspend, bool &tailcall)
{
int64_t nparamscheck = nclosure->_nparamscheck;
int64_t newtop = newbase + nargs + nclosure->_noutervalues;
@ -1217,7 +1217,7 @@ bool rabbit::VirtualMachine::callNative(SQNativeClosure *nclosure, int64_t nargs
return true;
}
bool rabbit::VirtualMachine::tailcall(SQClosure *closure, int64_t parambase,int64_t nparams)
bool rabbit::VirtualMachine::tailcall(rabbit::Closure *closure, int64_t parambase,int64_t nparams)
{
int64_t last_top = _top;
rabbit::ObjectPtr clo = closure;
@ -1629,9 +1629,9 @@ bool rabbit::VirtualMachine::callMetaMethod(rabbit::ObjectPtr &closure,rabbit::M
void rabbit::VirtualMachine::findOuter(rabbit::ObjectPtr &target, rabbit::ObjectPtr *stackindex)
{
SQOuter **pp = &_openouters;
SQOuter *p;
SQOuter *otr;
rabbit::Outer **pp = &_openouters;
rabbit::Outer *p;
rabbit::Outer *otr;
while ((p = *pp) != NULL && p->_valptr >= stackindex) {
if (p->_valptr == stackindex) {
@ -1640,7 +1640,7 @@ void rabbit::VirtualMachine::findOuter(rabbit::ObjectPtr &target, rabbit::Object
}
pp = &p->_next;
}
otr = SQOuter::create(_get_shared_state(this), stackindex);
otr = rabbit::Outer::create(_get_shared_state(this), stackindex);
otr->_next = *pp;
// TODO: rework this, this is absolutly not safe...
otr->_idx = (stackindex - &_stack[0]);
@ -1699,7 +1699,7 @@ void rabbit::VirtualMachine::leaveFrame() {
void rabbit::VirtualMachine::relocateOuters()
{
SQOuter *p = _openouters;
rabbit::Outer *p = _openouters;
while (p) {
p->_valptr = &_stack[p->_idx];
p = p->_next;
@ -1707,7 +1707,7 @@ void rabbit::VirtualMachine::relocateOuters()
}
void rabbit::VirtualMachine::closeOuters(rabbit::ObjectPtr *stackindex) {
SQOuter *p;
rabbit::Outer *p;
while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
p->_value = *(p->_valptr);
p->_valptr = &p->_value;

View File

@ -38,10 +38,10 @@ namespace rabbit {
{
public:
struct callInfo{
SQInstruction *_ip;
rabbit::Instruction *_ip;
rabbit::ObjectPtr *_literals;
rabbit::ObjectPtr _closure;
SQGenerator *_generator;
rabbit::Generator *_generator;
int32_t _etraps;
int32_t _prevstkbase;
int32_t _prevtop;
@ -64,10 +64,10 @@ namespace rabbit {
bool init(VirtualMachine *friendvm, int64_t stacksize);
bool execute(rabbit::ObjectPtr &func, int64_t nargs, int64_t stackbase, rabbit::ObjectPtr &outres, rabbit::Bool raiseerror, ExecutionType et = ET_CALL);
//starts a native call return when the NATIVE closure returns
bool callNative(SQNativeClosure *nclosure, int64_t nargs, int64_t newbase, rabbit::ObjectPtr &retval, int32_t target, bool &suspend,bool &tailcall);
bool tailcall(SQClosure *closure, int64_t firstparam, int64_t nparams);
bool callNative(rabbit::NativeClosure *nclosure, int64_t nargs, int64_t newbase, rabbit::ObjectPtr &retval, int32_t target, bool &suspend,bool &tailcall);
bool tailcall(rabbit::Closure *closure, int64_t firstparam, int64_t nparams);
//starts a RABBIT call in the same "Execution loop"
bool startcall(SQClosure *closure, int64_t target, int64_t nargs, int64_t stackbase, bool tailcall);
bool startcall(rabbit::Closure *closure, int64_t target, int64_t nargs, int64_t stackbase, bool tailcall);
bool createClassInstance(rabbit::Class *theclass, rabbit::ObjectPtr &inst, rabbit::ObjectPtr &constructor);
//call a generic closure pure RABBIT or NATIVE
bool call(rabbit::ObjectPtr &closure, int64_t nparams, int64_t stackbase, rabbit::ObjectPtr &outres,rabbit::Bool raiseerror);
@ -110,7 +110,7 @@ namespace rabbit {
bool BW_OP(uint64_t op,rabbit::ObjectPtr &trg,const rabbit::ObjectPtr &o1,const rabbit::ObjectPtr &o2);
bool NEG_OP(rabbit::ObjectPtr &trg,const rabbit::ObjectPtr &o1);
bool CMP_OP(CmpOP op, const rabbit::ObjectPtr &o1,const rabbit::ObjectPtr &o2,rabbit::ObjectPtr &res);
bool CLOSURE_OP(rabbit::ObjectPtr &target, SQFunctionProto *func);
bool CLOSURE_OP(rabbit::ObjectPtr &target, rabbit::FunctionProto *func);
bool CLASS_OP(rabbit::ObjectPtr &target,int64_t base,int64_t attrs);
//return true if the loop is finished
bool FOREACH_OP(rabbit::ObjectPtr &o1,rabbit::ObjectPtr &o2,rabbit::ObjectPtr &o3,rabbit::ObjectPtr &o4,int64_t arg_2,int exitpos,int &jump);
@ -152,7 +152,7 @@ namespace rabbit {
int64_t _top;
int64_t _stackbase;
SQOuter* _openouters;
rabbit::Outer* _openouters;
rabbit::ObjectPtr _roottable;
rabbit::ObjectPtr _lasterror;
rabbit::ObjectPtr _errorhandler;

View File

@ -138,7 +138,7 @@ rabbit::Result sq_compile(rabbit::VirtualMachine* v,SQLEXREADFUNC read,rabbit::U
rabbit::ObjectPtr o;
#ifndef NO_COMPILER
if(compile(v, read, p, sourcename, o, raiseerror?true:false, _get_shared_state(v)->_debuginfo)) {
v->push(SQClosure::create(_get_shared_state(v), _funcproto(o), _table(v->_roottable)->getWeakRef(rabbit::OT_TABLE)));
v->push(rabbit::Closure::create(_get_shared_state(v), _funcproto(o), _table(v->_roottable)->getWeakRef(rabbit::OT_TABLE)));
return SQ_OK;
}
return SQ_ERROR;
@ -386,7 +386,7 @@ rabbit::Result sq_arrayinsert(rabbit::VirtualMachine* v,int64_t idx,int64_t dest
void sq_newclosure(rabbit::VirtualMachine* v,SQFUNCTION func,uint64_t nfreevars)
{
SQNativeClosure *nc = SQNativeClosure::create(_get_shared_state(v), func,nfreevars);
rabbit::NativeClosure *nc = rabbit::NativeClosure::create(_get_shared_state(v), func,nfreevars);
nc->_nparamscheck = 0;
for(uint64_t i = 0; i < nfreevars; i++) {
nc->_outervalues[i] = v->top();
@ -399,15 +399,15 @@ rabbit::Result sq_getclosureinfo(rabbit::VirtualMachine* v,int64_t idx,uint64_t
{
rabbit::Object o = stack_get(v, idx);
if(sq_type(o) == rabbit::OT_CLOSURE) {
SQClosure *c = _closure(o);
SQFunctionProto *proto = c->_function;
rabbit::Closure *c = _closure(o);
rabbit::FunctionProto *proto = c->_function;
*nparams = (uint64_t)proto->_nparameters;
*nfreevars = (uint64_t)proto->_noutervalues;
return SQ_OK;
}
else if(sq_type(o) == rabbit::OT_NATIVECLOSURE)
{
SQNativeClosure *c = _nativeclosure(o);
rabbit::NativeClosure *c = _nativeclosure(o);
*nparams = (uint64_t)c->_nparamscheck;
*nfreevars = c->_noutervalues;
return SQ_OK;
@ -419,7 +419,7 @@ rabbit::Result sq_setnativeclosurename(rabbit::VirtualMachine* v,int64_t idx,con
{
rabbit::Object o = stack_get(v, idx);
if(sq_isnativeclosure(o)) {
SQNativeClosure *nc = _nativeclosure(o);
rabbit::NativeClosure *nc = _nativeclosure(o);
nc->_name = rabbit::String::create(_get_shared_state(v),name);
return SQ_OK;
}
@ -431,7 +431,7 @@ rabbit::Result sq_setparamscheck(rabbit::VirtualMachine* v,int64_t nparamscheck,
rabbit::Object o = stack_get(v, -1);
if(!sq_isnativeclosure(o))
return sq_throwerror(v, _SC("native closure expected"));
SQNativeClosure *nc = _nativeclosure(o);
rabbit::NativeClosure *nc = _nativeclosure(o);
nc->_nparamscheck = nparamscheck;
if(typemask) {
etk::Vector<int64_t> res;
@ -463,7 +463,7 @@ rabbit::Result sq_bindenv(rabbit::VirtualMachine* v,int64_t idx)
rabbit::WeakRef *w = _refcounted(env)->getWeakRef(sq_type(env));
rabbit::ObjectPtr ret;
if(sq_isclosure(o)) {
SQClosure *c = _closure(o)->clone();
rabbit::Closure *c = _closure(o)->clone();
__Objrelease(c->_env);
c->_env = w;
__ObjaddRef(c->_env);
@ -474,7 +474,7 @@ rabbit::Result sq_bindenv(rabbit::VirtualMachine* v,int64_t idx)
ret = c;
}
else { //then must be a native closure
SQNativeClosure *c = _nativeclosure(o)->clone();
rabbit::NativeClosure *c = _nativeclosure(o)->clone();
__Objrelease(c->_env);
c->_env = w;
__ObjaddRef(c->_env);
@ -1109,8 +1109,8 @@ const rabbit::Char *sq_getlocal(rabbit::VirtualMachine* v,uint64_t level,uint64_
rabbit::VirtualMachine::callInfo &ci=v->_callsstack[lvl];
if(sq_type(ci._closure)!=rabbit::OT_CLOSURE)
return NULL;
SQClosure *c=_closure(ci._closure);
SQFunctionProto *func=c->_function;
rabbit::Closure *c=_closure(ci._closure);
rabbit::FunctionProto *func=c->_function;
if(func->_noutervalues > (int64_t)idx) {
v->push(*_outer(c->_outervalues[idx])->_valptr);
return _stringval(func->_outervalues[idx]._name);
@ -1208,7 +1208,7 @@ rabbit::Result sq_tailcall(rabbit::VirtualMachine* v, int64_t nparams)
if (sq_type(res) != rabbit::OT_CLOSURE) {
return sq_throwerror(v, _SC("only closure can be tail called"));
}
SQClosure *clo = _closure(res);
rabbit::Closure *clo = _closure(res);
if (clo->_function->_bgenerator)
{
return sq_throwerror(v, _SC("generators cannot be tail called"));
@ -1312,7 +1312,7 @@ rabbit::Result sq_readclosure(rabbit::VirtualMachine* v,SQREADFUNC r,rabbit::Use
return sq_throwerror(v,_SC("io error"));
if(tag != SQ_BYTECODE_STREAM_TAG)
return sq_throwerror(v,_SC("invalid stream"));
if(!SQClosure::load(v,up,r,closure))
if(!rabbit::Closure::load(v,up,r,closure))
return SQ_ERROR;
v->push(closure);
return SQ_OK;
@ -1351,17 +1351,17 @@ const rabbit::Char *sq_getfreevariable(rabbit::VirtualMachine* v,int64_t idx,uin
switch(sq_type(self))
{
case rabbit::OT_CLOSURE:{
SQClosure *clo = _closure(self);
SQFunctionProto *fp = clo->_function;
rabbit::Closure *clo = _closure(self);
rabbit::FunctionProto *fp = clo->_function;
if(((uint64_t)fp->_noutervalues) > nval) {
v->push(*(_outer(clo->_outervalues[nval])->_valptr));
SQOuterVar &ov = fp->_outervalues[nval];
rabbit::OuterVar &ov = fp->_outervalues[nval];
name = _stringval(ov._name);
}
}
break;
case rabbit::OT_NATIVECLOSURE:{
SQNativeClosure *clo = _nativeclosure(self);
rabbit::NativeClosure *clo = _nativeclosure(self);
if(clo->_noutervalues > nval) {
v->push(clo->_outervalues[nval]);
name = _SC("@NATIVE");
@ -1379,7 +1379,7 @@ rabbit::Result sq_setfreevariable(rabbit::VirtualMachine* v,int64_t idx,uint64_t
switch(sq_type(self))
{
case rabbit::OT_CLOSURE:{
SQFunctionProto *fp = _closure(self)->_function;
rabbit::FunctionProto *fp = _closure(self)->_function;
if(((uint64_t)fp->_noutervalues) > nval){
*(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
}

View File

@ -972,7 +972,7 @@ static int64_t closure_getinfos(rabbit::VirtualMachine* v) {
rabbit::Object o = stack_get(v,1);
rabbit::Table *res = rabbit::Table::create(_get_shared_state(v),4);
if(sq_type(o) == rabbit::OT_CLOSURE) {
SQFunctionProto *f = _closure(o)->_function;
rabbit::FunctionProto *f = _closure(o)->_function;
int64_t nparams = f->_nparameters + (f->_varparams?1:0);
rabbit::ObjectPtr params = rabbit::Array::create(_get_shared_state(v),nparams);
rabbit::ObjectPtr defparams = rabbit::Array::create(_get_shared_state(v),f->_ndefaultparams);
@ -993,7 +993,7 @@ static int64_t closure_getinfos(rabbit::VirtualMachine* v) {
res->newSlot(rabbit::String::create(_get_shared_state(v),_SC("defparams"),-1),defparams);
}
else { //rabbit::OT_NATIVECLOSURE
SQNativeClosure *nc = _nativeclosure(o);
rabbit::NativeClosure *nc = _nativeclosure(o);
res->newSlot(rabbit::String::create(_get_shared_state(v),_SC("native"),-1),true);
res->newSlot(rabbit::String::create(_get_shared_state(v),_SC("name"),-1),nc->_name);
res->newSlot(rabbit::String::create(_get_shared_state(v),_SC("paramscheck"),-1),nc->_nparamscheck);
@ -1032,9 +1032,9 @@ static int64_t generator_getstatus(rabbit::VirtualMachine* v)
{
rabbit::Object &o=stack_get(v,1);
switch(_generator(o)->_state){
case SQGenerator::eSuspended:v->push(rabbit::String::create(_get_shared_state(v),_SC("suspended")));break;
case SQGenerator::eRunning:v->push(rabbit::String::create(_get_shared_state(v),_SC("running")));break;
case SQGenerator::eDead:v->push(rabbit::String::create(_get_shared_state(v),_SC("dead")));break;
case rabbit::Generator::eSuspended:v->push(rabbit::String::create(_get_shared_state(v),_SC("suspended")));break;
case rabbit::Generator::eRunning:v->push(rabbit::String::create(_get_shared_state(v),_SC("running")));break;
case rabbit::Generator::eDead:v->push(rabbit::String::create(_get_shared_state(v),_SC("dead")));break;
}
return 1;
}

View File

@ -1,196 +0,0 @@
/**
* @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)
*/
#pragma once
#include <rabbit/Class.hpp>
#include <rabbit/sqconfig.hpp>
#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(rabbit::ObjectPtr)) + (func->_ndefaultparams*sizeof(rabbit::ObjectPtr)))
struct SQFunctionProto;
struct SQClosure : public rabbit::RefCounted
{
private:
SQClosure(rabbit::SharedState *ss,SQFunctionProto *func){
_function = func;
__ObjaddRef(_function); _base = NULL;
_env = NULL;
_root=NULL;
}
public:
static SQClosure *create(rabbit::SharedState *ss,SQFunctionProto *func,rabbit::WeakRef *root){
int64_t size = _CALC_CLOSURE_SIZE(func);
SQClosure *nc=(SQClosure*)SQ_MALLOC(size);
new (nc) SQClosure(ss,func);
nc->_outervalues = (rabbit::ObjectPtr *)(nc + 1);
nc->_defaultparams = &nc->_outervalues[func->_noutervalues];
nc->_root = root;
__ObjaddRef(nc->_root);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,func->_noutervalues,nc->_outervalues);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,func->_ndefaultparams,nc->_defaultparams);
return nc;
}
void release(){
SQFunctionProto *f = _function;
int64_t size = _CALC_CLOSURE_SIZE(f);
_DESTRUCT_VECTOR(ObjectPtr,f->_noutervalues,_outervalues);
_DESTRUCT_VECTOR(ObjectPtr,f->_ndefaultparams,_defaultparams);
__Objrelease(_function);
this->~SQClosure();
sq_vm_free(this,size);
}
void setRoot(rabbit::WeakRef *r)
{
__Objrelease(_root);
_root = r;
__ObjaddRef(_root);
}
SQClosure *clone()
{
SQFunctionProto *f = _function;
SQClosure * ret = SQClosure::create(NULL,f,_root);
ret->_env = _env;
if(ret->_env) __ObjaddRef(ret->_env);
_COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
_COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
return ret;
}
~SQClosure();
bool save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write);
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::WeakRef *_env;
rabbit::WeakRef *_root;
rabbit::Class *_base;
SQFunctionProto *_function;
rabbit::ObjectPtr *_outervalues;
rabbit::ObjectPtr *_defaultparams;
};
//////////////////////////////////////////////
struct SQOuter : public rabbit::RefCounted
{
private:
SQOuter(rabbit::SharedState *ss, rabbit::ObjectPtr *outer){
_valptr = outer;
_next = NULL;
}
public:
static SQOuter *create(rabbit::SharedState *ss, rabbit::ObjectPtr *outer)
{
SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter));
new (nc) SQOuter(ss, outer);
return nc;
}
~SQOuter() {
}
void release()
{
this->~SQOuter();
sq_vm_free(this,sizeof(SQOuter));
}
rabbit::ObjectPtr *_valptr; /* pointer to value on stack, or _value below */
int64_t _idx; /* idx in stack array, for relocation */
rabbit::ObjectPtr _value; /* value of outer after stack frame is closed */
SQOuter *_next; /* pointer to next outer when frame is open */
};
//////////////////////////////////////////////
struct SQGenerator : public rabbit::RefCounted
{
enum SQGeneratorState{eRunning,eSuspended,eDead};
private:
SQGenerator(rabbit::SharedState *ss,SQClosure *closure){
_closure=closure;
_state=eRunning;
_ci._generator=NULL;
}
public:
static SQGenerator *create(rabbit::SharedState *ss,SQClosure *closure){
SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
new (nc) SQGenerator(ss,closure);
return nc;
}
~SQGenerator()
{
}
void kill(){
_state=eDead;
_stack.resize(0);
_closure.Null();}
void release(){
sq_delete(this,SQGenerator);
}
bool yield(rabbit::VirtualMachine *v,int64_t target);
bool resume(rabbit::VirtualMachine *v,rabbit::ObjectPtr &dest);
rabbit::ObjectPtr _closure;
etk::Vector<rabbit::ObjectPtr> _stack;
rabbit::VirtualMachine::callInfo _ci;
etk::Vector<rabbit::ExceptionTrap> _etraps;
SQGeneratorState _state;
};
#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(rabbit::ObjectPtr)))
struct SQNativeClosure : public rabbit::RefCounted
{
private:
SQNativeClosure(rabbit::SharedState *ss,SQFUNCTION func){
_function=func;
_env = NULL;
}
public:
static SQNativeClosure *create(rabbit::SharedState *ss,SQFUNCTION func,int64_t nouters)
{
int64_t size = _CALC_NATVIVECLOSURE_SIZE(nouters);
SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size);
new (nc) SQNativeClosure(ss,func);
nc->_outervalues = (rabbit::ObjectPtr *)(nc + 1);
nc->_noutervalues = nouters;
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,nc->_noutervalues,nc->_outervalues);
return nc;
}
SQNativeClosure *clone()
{
SQNativeClosure * ret = SQNativeClosure::create(NULL,_function,_noutervalues);
ret->_env = _env;
if(ret->_env) __ObjaddRef(ret->_env);
ret->_name = _name;
_COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);
ret->_typecheck = _typecheck;
ret->_nparamscheck = _nparamscheck;
return ret;
}
~SQNativeClosure()
{
__Objrelease(_env);
}
void release(){
int64_t size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);
_DESTRUCT_VECTOR(ObjectPtr,_noutervalues,_outervalues);
this->~SQNativeClosure();
sq_free(this,size);
}
int64_t _nparamscheck;
etk::Vector<int64_t> _typecheck;
rabbit::ObjectPtr *_outervalues;
uint64_t _noutervalues;
rabbit::WeakRef *_env;
SQFUNCTION _function;
rabbit::ObjectPtr _name;
};

View File

@ -1,84 +0,0 @@
/**
* @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)
*/
#pragma once
namespace rabbit {
class VirtualMachine;
}
#define TK_IDENTIFIER 258
#define TK_STRING_LITERAL 259
#define TK_INTEGER 260
#define TK_FLOAT 261
#define TK_BASE 262
#define TK_DELETE 263
#define TK_EQ 264
#define TK_NE 265
#define TK_LE 266
#define TK_GE 267
#define TK_SWITCH 268
#define TK_ARROW 269
#define TK_AND 270
#define TK_OR 271
#define TK_IF 272
#define TK_ELSE 273
#define TK_WHILE 274
#define TK_BREAK 275
#define TK_FOR 276
#define TK_DO 277
#define TK_NULL 278
#define TK_FOREACH 279
#define TK_IN 280
#define TK_NEWSLOT 281
#define TK_MODULO 282
#define TK_LOCAL 283
#define TK_CLONE 284
#define TK_FUNCTION 285
#define TK_RETURN 286
#define TK_TYPEOF 287
#define TK_UMINUS 288
#define TK_PLUSEQ 289
#define TK_MINUSEQ 290
#define TK_CONTINUE 291
#define TK_YIELD 292
#define TK_TRY 293
#define TK_CATCH 294
#define TK_THROW 295
#define TK_SHIFTL 296
#define TK_SHIFTR 297
#define TK_RESUME 298
#define TK_DOUBLE_COLON 299
#define TK_CASE 300
#define TK_DEFAULT 301
#define TK_THIS 302
#define TK_PLUSPLUS 303
#define TK_MINUSMINUS 304
#define TK_3WAYSCMP 305
#define TK_USHIFTR 306
#define TK_CLASS 307
#define TK_EXTENDS 308
#define TK_CONSTRUCTOR 310
#define TK_INSTANCEOF 311
#define TK_VARPARAMS 312
#define TK___LINE__ 313
#define TK___FILE__ 314
#define TK_TRUE 315
#define TK_FALSE 316
#define TK_MULEQ 317
#define TK_DIVEQ 318
#define TK_MODEQ 319
#define TK_ATTR_OPEN 320
#define TK_ATTR_CLOSE 321
#define TK_STATIC 322
#define TK_ENUM 323
#define TK_CONST 324
#define TK_RAWCALL 325
typedef void(*compilererrorFunc)(void *ud, const rabbit::Char *s);
bool compile(rabbit::VirtualMachine *vm, SQLEXREADFUNC rg, rabbit::UserPointer up, const rabbit::Char *sourcename, rabbit::ObjectPtr &out, bool raiseerror, bool lineinfo);

View File

@ -124,11 +124,21 @@ namespace rabbit {
#define SQTrue (1)
#define SQFalse (0)
struct SQClosure;
struct SQGenerator;
struct SQNativeClosure;
struct SQFunctionProto;
struct SQOuter;
#ifdef _SQ64
#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
#else
#define UINT_MINUS_ONE (0xFFFFFFFF)
#endif
struct rabbit::Closure;
struct rabbit::Generator;
struct rabbit::NativeClosure;
struct rabbit::FunctionProto;
struct rabbit::Outer;
namespace rabbit {
class UserData;
class Array;

View File

@ -21,8 +21,8 @@ rabbit::Result sq_getfunctioninfo(rabbit::VirtualMachine* v,int64_t level,rabbit
if (cssize > level) {
rabbit::VirtualMachine::callInfo &ci = v->_callsstack[cssize-level-1];
if(sq_isclosure(ci._closure)) {
SQClosure *c = _closure(ci._closure);
SQFunctionProto *proto = c->_function;
rabbit::Closure *c = _closure(ci._closure);
rabbit::FunctionProto *proto = c->_function;
fi->funcid = proto;
fi->name = sq_type(proto->_name) == rabbit::OT_STRING?_stringval(proto->_name):_SC("unknown");
fi->source = sq_type(proto->_sourcename) == rabbit::OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
@ -41,7 +41,7 @@ rabbit::Result sq_stackinfos(rabbit::VirtualMachine* v, int64_t level, rabbit::S
rabbit::VirtualMachine::callInfo &ci = v->_callsstack[cssize-level-1];
switch (sq_type(ci._closure)) {
case rabbit::OT_CLOSURE:{
SQFunctionProto *func = _closure(ci._closure)->_function;
rabbit::FunctionProto *func = _closure(ci._closure)->_function;
if (sq_type(func->_name) == rabbit::OT_STRING)
si->funcname = _stringval(func->_name);
if (sq_type(func->_sourcename) == rabbit::OT_STRING)

View File

@ -1,152 +0,0 @@
/**
* @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)
*/
#pragma once
#include <rabbit/sqopcodes.hpp>
enum SQOuterType {
otLOCAL = 0,
otOUTER = 1
};
struct SQOuterVar
{
SQOuterVar(){}
SQOuterVar(const rabbit::ObjectPtr &name,const rabbit::ObjectPtr &src,SQOuterType t)
{
_name = name;
_src=src;
_type=t;
}
SQOuterVar(const SQOuterVar &ov)
{
_type=ov._type;
_src=ov._src;
_name=ov._name;
}
SQOuterType _type;
rabbit::ObjectPtr _name;
rabbit::ObjectPtr _src;
};
struct SQLocalVarInfo
{
SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){}
SQLocalVarInfo(const SQLocalVarInfo &lvi)
{
_name=lvi._name;
_start_op=lvi._start_op;
_end_op=lvi._end_op;
_pos=lvi._pos;
}
rabbit::ObjectPtr _name;
uint64_t _start_op;
uint64_t _end_op;
uint64_t _pos;
};
struct SQLineInfo { int64_t _line;int64_t _op; };
typedef etk::Vector<SQOuterVar> SQOuterVarVec;
typedef etk::Vector<SQLocalVarInfo> SQLocalVarInfoVec;
typedef etk::Vector<SQLineInfo> SQLineInfoVec;
#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(rabbit::ObjectPtr)) \
+(nparams*sizeof(rabbit::ObjectPtr))+(nfuncs*sizeof(rabbit::ObjectPtr)) \
+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
+(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(int64_t)))
struct SQFunctionProto : public rabbit::RefCounted
{
private:
SQFunctionProto(rabbit::SharedState *ss);
~SQFunctionProto();
public:
static SQFunctionProto *create(rabbit::SharedState *ss,int64_t ninstructions,
int64_t nliterals,int64_t nparameters,
int64_t nfunctions,int64_t noutervalues,
int64_t nlineinfos,int64_t nlocalvarinfos,int64_t ndefaultparams)
{
SQFunctionProto *f;
//I compact the whole class and members in a single memory allocation
f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
new (f) SQFunctionProto(ss);
f->_ninstructions = ninstructions;
f->_literals = (rabbit::ObjectPtr*)&f->_instructions[ninstructions];
f->_nliterals = nliterals;
f->_parameters = (rabbit::ObjectPtr*)&f->_literals[nliterals];
f->_nparameters = nparameters;
f->_functions = (rabbit::ObjectPtr*)&f->_parameters[nparameters];
f->_nfunctions = nfunctions;
f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
f->_noutervalues = noutervalues;
f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
f->_nlineinfos = nlineinfos;
f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
f->_nlocalvarinfos = nlocalvarinfos;
f->_defaultparams = (int64_t *)&f->_localvarinfos[nlocalvarinfos];
f->_ndefaultparams = ndefaultparams;
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nliterals,f->_literals);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nparameters,f->_parameters);
_CONSTRUCT_VECTOR(rabbit::ObjectPtr,f->_nfunctions,f->_functions);
_CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
//_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
return f;
}
void release(){
_DESTRUCT_VECTOR(ObjectPtr,_nliterals,_literals);
_DESTRUCT_VECTOR(ObjectPtr,_nparameters,_parameters);
_DESTRUCT_VECTOR(ObjectPtr,_nfunctions,_functions);
_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
int64_t size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
this->~SQFunctionProto();
sq_vm_free(this,size);
}
const rabbit::Char* getLocal(rabbit::VirtualMachine *v,uint64_t stackbase,uint64_t nseq,uint64_t nop);
int64_t getLine(SQInstruction *curr);
bool save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write);
static bool load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret);
rabbit::ObjectPtr _sourcename;
rabbit::ObjectPtr _name;
int64_t _stacksize;
bool _bgenerator;
int64_t _varparams;
int64_t _nlocalvarinfos;
SQLocalVarInfo *_localvarinfos;
int64_t _nlineinfos;
SQLineInfo *_lineinfos;
int64_t _nliterals;
rabbit::ObjectPtr *_literals;
int64_t _nparameters;
rabbit::ObjectPtr *_parameters;
int64_t _nfunctions;
rabbit::ObjectPtr *_functions;
int64_t _noutervalues;
SQOuterVar *_outervalues;
int64_t _ndefaultparams;
int64_t *_defaultparams;
int64_t _ninstructions;
SQInstruction _instructions[1];
};

View File

@ -1,94 +0,0 @@
/**
* @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)
*/
#pragma once
#include <rabbit/squtils.hpp>
struct SQFuncState
{
SQFuncState(rabbit::SharedState *ss,SQFuncState *parent,compilererrorFunc efunc,void *ed);
~SQFuncState();
#ifdef _DEBUG_DUMP
void dump(SQFunctionProto *func);
#endif
void error(const rabbit::Char *err);
SQFuncState *pushChildState(rabbit::SharedState *ss);
void popChildState();
void addInstruction(SQOpcode _op,int64_t arg0=0,int64_t arg1=0,int64_t arg2=0,int64_t arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);addInstruction(i);}
void addInstruction(SQInstruction &i);
void setIntructionParams(int64_t pos,int64_t arg0,int64_t arg1,int64_t arg2=0,int64_t arg3=0);
void setIntructionParam(int64_t pos,int64_t arg,int64_t val);
SQInstruction &getInstruction(int64_t pos){return _instructions[pos];}
void popInstructions(int64_t size){for(int64_t i=0;i<size;i++)_instructions.popBack();}
void setStacksize(int64_t n);
int64_t CountOuters(int64_t stacksize);
void snoozeOpt(){_optimization=false;}
void addDefaultParam(int64_t trg) { _defaultparams.pushBack(trg); }
int64_t getDefaultParamCount() { return _defaultparams.size(); }
int64_t getCurrentPos(){return _instructions.size()-1;}
int64_t getNumericConstant(const int64_t cons);
int64_t getNumericConstant(const float_t cons);
int64_t pushLocalVariable(const rabbit::Object &name);
void addParameter(const rabbit::Object &name);
//void addOuterValue(const rabbit::Object &name);
int64_t getLocalVariable(const rabbit::Object &name);
void markLocalAsOuter(int64_t pos);
int64_t getOuterVariable(const rabbit::Object &name);
int64_t generateCode();
int64_t getStacksize();
int64_t calcStackFramesize();
void addLineInfos(int64_t line,bool lineop,bool force=false);
SQFunctionProto *buildProto();
int64_t allocStackPos();
int64_t pushTarget(int64_t n=-1);
int64_t popTarget();
int64_t topTarget();
int64_t getUpTarget(int64_t n);
void discardTarget();
bool isLocal(uint64_t stkpos);
rabbit::Object createString(const rabbit::Char *s,int64_t len = -1);
rabbit::Object createTable();
bool isConstant(const rabbit::Object &name,rabbit::Object &e);
int64_t _returnexp;
SQLocalVarInfoVec _vlocals;
etk::Vector<int64_t> _targetstack;
int64_t _stacksize;
bool _varparams;
bool _bgenerator;
etk::Vector<int64_t> _unresolvedbreaks;
etk::Vector<int64_t> _unresolvedcontinues;
etk::Vector<rabbit::ObjectPtr> _functions;
etk::Vector<rabbit::ObjectPtr> _parameters;
SQOuterVarVec _outervalues;
SQInstructionVec _instructions;
SQLocalVarInfoVec _localvarinfos;
rabbit::ObjectPtr _literals;
rabbit::ObjectPtr _strings;
rabbit::ObjectPtr _name;
rabbit::ObjectPtr _sourcename;
int64_t _nliterals;
SQLineInfoVec _lineinfos;
SQFuncState *_parent;
etk::Vector<int64_t> _scope_blocks;
etk::Vector<int64_t> _breaktargets;
etk::Vector<int64_t> _continuetargets;
etk::Vector<int64_t> _defaultparams;
int64_t _lastline;
int64_t _traps; //contains number of nested exception traps
int64_t _outers;
bool _optimization;
rabbit::SharedState *_sharedstate;
etk::Vector<SQFuncState*> _childstates;
int64_t getConstant(const rabbit::Object &cons);
private:
compilererrorFunc _errfunc;
void *_errtarget;
rabbit::SharedState *_ss;
};

View File

@ -1,59 +0,0 @@
/**
* @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)
*/
#pragma once
#ifdef SQUNICODE
typedef rabbit::Char LexChar;
#else
typedef unsigned char LexChar;
#endif
struct SQLexer
{
SQLexer();
~SQLexer();
void init(rabbit::SharedState *ss,SQLEXREADFUNC rg,rabbit::UserPointer up,compilererrorFunc efunc,void *ed);
void error(const rabbit::Char *err);
int64_t Lex();
const rabbit::Char *tok2Str(int64_t tok);
private:
int64_t getIDType(const rabbit::Char *s,int64_t len);
int64_t readString(int64_t ndelim,bool verbatim);
int64_t readNumber();
void lexBlockComment();
void lexLineComment();
int64_t readId();
void next();
#ifdef SQUNICODE
#if WCHAR_SIZE == 2
int64_t addUTF16(uint64_t ch);
#endif
#else
int64_t addUTF8(uint64_t ch);
#endif
int64_t processStringHexEscape(rabbit::Char *dest, int64_t maxdigits);
int64_t _curtoken;
rabbit::Table *_keywords;
rabbit::Bool _reached_eof;
public:
int64_t _prevtoken;
int64_t _currentline;
int64_t _lasttokenline;
int64_t _currentcolumn;
const rabbit::Char *_svalue;
int64_t _nvalue;
float_t _fvalue;
SQLEXREADFUNC _readf;
rabbit::UserPointer _up;
LexChar _currdata;
rabbit::SharedState *_sharedstate;
etk::Vector<rabbit::Char> _longstr;
compilererrorFunc _errfunc;
void *_errtarget;
};

View File

@ -1,433 +0,0 @@
/**
* @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/sqpcheader.hpp>
#include <rabbit/VirtualMachine.hpp>
#include <rabbit/Array.hpp>
#include <rabbit/UserData.hpp>
#include <rabbit/sqfuncproto.hpp>
#include <rabbit/sqclosure.hpp>
bool SQGenerator::yield(rabbit::VirtualMachine *v,int64_t target)
{
if(_state==eSuspended) { v->raise_error(_SC("internal vm error, yielding dead generator")); return false;}
if(_state==eDead) { v->raise_error(_SC("internal vm error, yielding a dead generator")); return false; }
int64_t size = v->_top-v->_stackbase;
_stack.resize(size);
rabbit::Object _this = v->_stack[v->_stackbase];
_stack[0] = ISREFCOUNTED(sq_type(_this)) ? rabbit::ObjectPtr(_refcounted(_this)->getWeakRef(sq_type(_this))) : _this;
for(int64_t n =1; n<target; n++) {
_stack[n] = v->_stack[v->_stackbase+n];
}
for(int64_t j =0; j < size; j++)
{
v->_stack[v->_stackbase+j].Null();
}
_ci = *v->ci;
_ci._generator=NULL;
for(int64_t i=0;i<_ci._etraps;i++) {
_etraps.pushBack(v->_etraps.back());
v->_etraps.popBack();
// store relative stack base and size in case of resume to other _top
rabbit::ExceptionTrap &et = _etraps.back();
et._stackbase -= v->_stackbase;
et._stacksize -= v->_stackbase;
}
_state=eSuspended;
return true;
}
bool SQGenerator::resume(rabbit::VirtualMachine *v,rabbit::ObjectPtr &dest)
{
if(_state==eDead){ v->raise_error(_SC("resuming dead generator")); return false; }
if(_state==eRunning){ v->raise_error(_SC("resuming active generator")); return false; }
int64_t size = _stack.size();
int64_t target = &dest - &(v->_stack[v->_stackbase]);
assert(target>=0 && target<=255);
int64_t newbase = v->_top;
if(!v->enterFrame(v->_top, v->_top + size, false))
return false;
v->ci->_generator = this;
v->ci->_target = (int32_t)target;
v->ci->_closure = _ci._closure;
v->ci->_ip = _ci._ip;
v->ci->_literals = _ci._literals;
v->ci->_ncalls = _ci._ncalls;
v->ci->_etraps = _ci._etraps;
v->ci->_root = _ci._root;
for(int64_t i=0;i<_ci._etraps;i++) {
v->_etraps.pushBack(_etraps.back());
_etraps.popBack();
rabbit::ExceptionTrap &et = v->_etraps.back();
// restore absolute stack base and size
et._stackbase += newbase;
et._stacksize += newbase;
}
rabbit::Object _this = _stack[0];
v->_stack[v->_stackbase] = sq_type(_this) == rabbit::OT_WEAKREF ? _weakref(_this)->_obj : _this;
for(int64_t n = 1; n<size; n++) {
v->_stack[v->_stackbase+n] = _stack[n];
_stack[n].Null();
}
_state=eRunning;
if (v->_debughook)
v->callDebugHook(_SC('c'));
return true;
}
void rabbit::Array::extend(const rabbit::Array *a){
int64_t xlen;
if((xlen=a->size()))
for(int64_t i=0;i<xlen;i++)
append((*a)[i]);
}
const rabbit::Char* SQFunctionProto::getLocal(rabbit::VirtualMachine *vm,uint64_t stackbase,uint64_t nseq,uint64_t nop)
{
uint64_t nvars=_nlocalvarinfos;
const rabbit::Char *res=NULL;
if(nvars>=nseq){
for(uint64_t i=0;i<nvars;i++){
if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
{
if(nseq==0){
vm->push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
res=_stringval(_localvarinfos[i]._name);
break;
}
nseq--;
}
}
}
return res;
}
int64_t SQFunctionProto::getLine(SQInstruction *curr)
{
int64_t op = (int64_t)(curr-_instructions);
int64_t line=_lineinfos[0]._line;
int64_t low = 0;
int64_t high = _nlineinfos - 1;
int64_t mid = 0;
while(low <= high)
{
mid = low + ((high - low) >> 1);
int64_t curop = _lineinfos[mid]._op;
if(curop > op)
{
high = mid - 1;
}
else if(curop < op) {
if(mid < (_nlineinfos - 1)
&& _lineinfos[mid + 1]._op >= op) {
break;
}
low = mid + 1;
}
else { //equal
break;
}
}
while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
line = _lineinfos[mid]._line;
return line;
}
SQClosure::~SQClosure()
{
__Objrelease(_root);
__Objrelease(_env);
__Objrelease(_base);
}
#define _CHECK_IO(exp) { if(!exp)return false; }
bool SafeWrite(rabbit::VirtualMachine* v,SQWRITEFUNC write,rabbit::UserPointer up,rabbit::UserPointer dest,int64_t size)
{
if(write(up,dest,size) != size) {
v->raise_error(_SC("io error (write function failure)"));
return false;
}
return true;
}
bool SafeRead(rabbit::VirtualMachine* v,SQWRITEFUNC read,rabbit::UserPointer up,rabbit::UserPointer dest,int64_t size)
{
if(size && read(up,dest,size) != size) {
v->raise_error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
return false;
}
return true;
}
bool WriteTag(rabbit::VirtualMachine* v,SQWRITEFUNC write,rabbit::UserPointer up,uint32_t tag)
{
return SafeWrite(v,write,up,&tag,sizeof(tag));
}
bool CheckTag(rabbit::VirtualMachine* v,SQWRITEFUNC read,rabbit::UserPointer up,uint32_t tag)
{
uint32_t t;
_CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
if(t != tag){
v->raise_error(_SC("invalid or corrupted closure stream"));
return false;
}
return true;
}
bool WriteObject(rabbit::VirtualMachine* v,rabbit::UserPointer up,SQWRITEFUNC write,rabbit::ObjectPtr &o)
{
uint32_t _type = (uint32_t)sq_type(o);
_CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
switch(sq_type(o)){
case rabbit::OT_STRING:
_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(int64_t)));
_CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len)));
break;
case rabbit::OT_BOOL:
case rabbit::OT_INTEGER:
_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(int64_t)));break;
case rabbit::OT_FLOAT:
_CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(float_t)));break;
case rabbit::OT_NULL:
break;
default:
v->raise_error(_SC("cannot serialize a %s"),getTypeName(o));
return false;
}
return true;
}
bool ReadObject(rabbit::VirtualMachine* v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &o)
{
uint32_t _type;
_CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
rabbit::ObjectType t = (rabbit::ObjectType)_type;
switch(t){
case rabbit::OT_STRING:{
int64_t len;
_CHECK_IO(SafeRead(v,read,up,&len,sizeof(int64_t)));
_CHECK_IO(SafeRead(v,read,up,_get_shared_state(v)->getScratchPad(sq_rsl(len)),sq_rsl(len)));
o=rabbit::String::create(_get_shared_state(v),_get_shared_state(v)->getScratchPad(-1),len);
}
break;
case rabbit::OT_INTEGER:{
int64_t i;
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(int64_t))); o = i; break;
}
case rabbit::OT_BOOL:{
int64_t i;
_CHECK_IO(SafeRead(v,read,up,&i,sizeof(int64_t))); o._type = rabbit::OT_BOOL; o._unVal.nInteger = i; break;
}
case rabbit::OT_FLOAT:{
float_t f;
_CHECK_IO(SafeRead(v,read,up,&f,sizeof(float_t))); o = f; break;
}
case rabbit::OT_NULL:
o.Null();
break;
default:
v->raise_error(_SC("cannot serialize a %s"),IdType2Name(t));
return false;
}
return true;
}
bool SQClosure::save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write)
{
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(WriteTag(v,write,up,sizeof(rabbit::Char)));
_CHECK_IO(WriteTag(v,write,up,sizeof(int64_t)));
_CHECK_IO(WriteTag(v,write,up,sizeof(float_t)));
_CHECK_IO(_function->save(v,up,write));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
return true;
}
bool SQClosure::load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret)
{
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
_CHECK_IO(CheckTag(v,read,up,sizeof(rabbit::Char)));
_CHECK_IO(CheckTag(v,read,up,sizeof(int64_t)));
_CHECK_IO(CheckTag(v,read,up,sizeof(float_t)));
rabbit::ObjectPtr func;
_CHECK_IO(SQFunctionProto::load(v,up,read,func));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
ret = SQClosure::create(_get_shared_state(v),_funcproto(func),_table(v->_roottable)->getWeakRef(rabbit::OT_TABLE));
//FIXME: load an root for this closure
return true;
}
SQFunctionProto::SQFunctionProto(rabbit::SharedState *ss)
{
_stacksize=0;
_bgenerator=false;
}
SQFunctionProto::~SQFunctionProto()
{
}
bool SQFunctionProto::save(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQWRITEFUNC write)
{
int64_t i,nliterals = _nliterals,nparameters = _nparameters;
int64_t noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
int64_t nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
int64_t ndefaultparams = _ndefaultparams;
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(WriteObject(v,up,write,_sourcename));
_CHECK_IO(WriteObject(v,up,write,_name));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
_CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
_CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
_CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
_CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
_CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
_CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
_CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nliterals;i++){
_CHECK_IO(WriteObject(v,up,write,_literals[i]));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nparameters;i++){
_CHECK_IO(WriteObject(v,up,write,_parameters[i]));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<noutervalues;i++){
_CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(uint64_t)));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nlocalvarinfos;i++){
SQLocalVarInfo &lvi=_localvarinfos[i];
_CHECK_IO(WriteObject(v,up,write,lvi._name));
_CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(uint64_t)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(uint64_t)));
_CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(uint64_t)));
}
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(int64_t)*ndefaultparams));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
for(i=0;i<nfunctions;i++){
_CHECK_IO(_funcproto(_functions[i])->save(v,up,write));
}
_CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
_CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
return true;
}
bool SQFunctionProto::load(rabbit::VirtualMachine *v,rabbit::UserPointer up,SQREADFUNC read,rabbit::ObjectPtr &ret)
{
int64_t i, nliterals,nparameters;
int64_t noutervalues ,nlocalvarinfos ;
int64_t nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
rabbit::ObjectPtr sourcename, name;
rabbit::ObjectPtr o;
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(ReadObject(v, up, read, sourcename));
_CHECK_IO(ReadObject(v, up, read, name));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));
_CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
_CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
_CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
_CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
_CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
_CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
_CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
SQFunctionProto *f = SQFunctionProto::create(NULL,ninstructions,nliterals,nparameters,
nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
rabbit::ObjectPtr proto = f; //gets a ref in case of failure
f->_sourcename = sourcename;
f->_name = name;
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0;i < nliterals; i++){
_CHECK_IO(ReadObject(v, up, read, o));
f->_literals[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nparameters; i++){
_CHECK_IO(ReadObject(v, up, read, o));
f->_parameters[i] = o;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < noutervalues; i++){
uint64_t type;
rabbit::ObjectPtr name;
_CHECK_IO(SafeRead(v,read,up, &type, sizeof(uint64_t)));
_CHECK_IO(ReadObject(v, up, read, o));
_CHECK_IO(ReadObject(v, up, read, name));
f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nlocalvarinfos; i++){
SQLocalVarInfo lvi;
_CHECK_IO(ReadObject(v, up, read, lvi._name));
_CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(uint64_t)));
_CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(uint64_t)));
_CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(uint64_t)));
f->_localvarinfos[i] = lvi;
}
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(int64_t)*ndefaultparams));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
_CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
for(i = 0; i < nfunctions; i++){
_CHECK_IO(_funcproto(o)->load(v, up, read, o));
f->_functions[i] = o;
}
_CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
_CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
_CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
ret = f;
return true;
}

View File

@ -1,46 +0,0 @@
/**
* @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)
*/
#pragma once
#include <rabbit/squtils.hpp>
#include <rabbit/RefCounted.hpp>
#include <rabbit/WeakRef.hpp>
#ifdef _SQ64
#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
#else
#define UINT_MINUS_ONE (0xFFFFFFFF)
#endif
#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
#define _CONSTRUCT_VECTOR(type, size, ptr) { \
for(int64_t n = 0; n < ((int64_t)size); n++) { \
new (&ptr[n]) type(); \
} \
}
#define _DESTRUCT_VECTOR(type, size, ptr) { \
for(int64_t nl = 0; nl < ((int64_t)size); nl++) { \
ptr[nl].~type(); \
} \
}
#define _COPY_VECTOR(dest, src, size) { \
for(int64_t _n_ = 0; _n_ < ((int64_t)size); _n_++) { \
dest[_n_] = src[_n_]; \
} \
}
#define _NULL_SQOBJECT_VECTOR(vec, size) { \
for(int64_t _n_ = 0; _n_ < ((int64_t)size); _n_++) { \
vec[_n_].Null(); \
} \
}

View File

@ -107,14 +107,14 @@ enum SQOpcode
_OP_CLOSE= 0x3C
};
struct SQInstructionDesc {
struct rabbit::InstructionDesc {
const rabbit::Char *name;
};
struct SQInstruction
struct rabbit::Instruction
{
SQInstruction(){};
SQInstruction(SQOpcode _op,int64_t a0=0,int64_t a1=0,int64_t a2=0,int64_t a3=0)
rabbit::Instruction(){};
rabbit::Instruction(SQOpcode _op,int64_t a0=0,int64_t a1=0,int64_t a2=0,int64_t a3=0)
{ op = (unsigned char)_op;
_arg0 = (unsigned char)a0;_arg1 = (int32_t)a1;
_arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
@ -129,7 +129,7 @@ struct SQInstruction
};
#include <rabbit/squtils.hpp>
typedef etk::Vector<SQInstruction> SQInstructionVec;
typedef etk::Vector<rabbit::Instruction> rabbit::InstructionVec;
#define NEW_SLOT_ATTRIBUTES_FLAG 0x01
#define NEW_SLOT_STATIC_FLAG 0x02

View File

@ -1,24 +0,0 @@
/**
* @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)
*/
#pragma once
#if defined(_MSC_VER) && defined(_DEBUG)
#include <crtdbg.hpp>
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <new>
//rabbit stuff
#include <rabbit/rabbit.hpp>
#include <rabbit/sqobject.hpp>

View File

@ -21,5 +21,28 @@ void sq_vm_free(void *p,uint64_t size);
#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
#include <etk/Vector.hpp>
#define _CONSTRUCT_VECTOR(type, size, ptr) { \
for(int64_t n = 0; n < ((int64_t)size); n++) { \
new (&ptr[n]) type(); \
} \
}
#define _DESTRUCT_VECTOR(type, size, ptr) { \
for(int64_t nl = 0; nl < ((int64_t)size); nl++) { \
ptr[nl].~type(); \
} \
}
#define _COPY_VECTOR(dest, src, size) { \
for(int64_t _n_ = 0; _n_ < ((int64_t)size); _n_++) { \
dest[_n_] = src[_n_]; \
} \
}
#define _NULL_SQOBJECT_VECTOR(vec, size) { \
for(int64_t _n_ = 0; _n_ < ((int64_t)size); _n_++) { \
vec[_n_].Null(); \
} \
}