void registerAll(spire::Acorn& core) { // Systems registerSystem_RenderSimpleGeom(core); registerSystem_RenderFont(core); registerSystem_ArcBallCameraMouse(core); registerSystem_DebugRenderClickBox2D(core); VBOMan::registerSystems(core); IBOMan::registerSystems(core); ShaderMan::registerSystems(core); GeomMan::registerSystems(core); TextureMan::registerSystems(core); FontMan::registerSystems(core); // Components register1(core); register2(core); register3(core); // Register utility systems registerSystem_UtilViewPosAlign(core); // Register utility components core.registerComponent<UtilViewPosAlign>(); }
//execute context l_thread::type_return l_thread::execute(l_call_context& context) { //lock context context.lock(); //save context register3(R_CONTEXT) = l_variable( &context ); //pc... unsigned int pc = 0; l_function& function = m_vm->function(context.get_fun_id()); l_list_command& commands = function.m_commands; //macro #define raise(str)\ {\ push_error(str, pc, (unsigned int)commands[pc].m_line);\ return T_RETURN_ERROR;\ } #define vconst(c) function.m_costants[c] #define top_size (m_top+1) //for all commands for (pc = 0; pc < commands.size(); ++pc) { //current command l_command& cmp = commands[pc]; //opcodes switch (cmp.m_op_code) { case L_JMP: pc = cmp.m_arg - 1; break; case L_RETURN: //push return if(cmp.m_arg) { //get value register3(2) = pop(); //return... return T_RETURN_VALUE; } else { //came back return T_RETURN_VOID; } //.. break; case L_IF: if(top().is_true()) { pc = cmp.m_arg - 1; } pop(); break; case L_IF0: if(top().is_false()) { pc = cmp.m_arg - 1; } pop(); break; case L_IF_OR_POP: if(top().is_true()) { pc = cmp.m_arg - 1; } else { pop(); } break; case L_IF0_OR_POP: if(top().is_false()) { pc = cmp.m_arg - 1; } else { pop(); } break; case L_PUSH: push( stack(cmp.m_arg) ); break; case L_PUSH_NULL: push( l_variable() ); break; case L_PUSH_TRUE: push( l_variable(true) ); break; case L_PUSH_FALSE: push( l_variable(false) ); break; case L_PUSHK: push( vconst(cmp.m_arg) ); break; case L_CLOSER: { //get value l_variable& call_fun = vconst(cmp.m_arg); //... if(call_fun.is_function()) { //new context register3(0) = l_closer::gc_new(get_gc()); //init context register3(0).to<l_closer>()->init(call_fun.m_value.m_fid, this, l_variable(&context)); //push context push(register3(0)); } } break; //////////////////////////////////////////////////////////// case L_ADD: if(!stack(1).add(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_MUL: if(!stack(1).mul(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_SUB: if(!stack(1).sub(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_DIV: if(!stack(1).div(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_MOD: if(!stack(1).mod(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_UNM: if(!stack(0).unm(stack(0))) raise("not valid operation"); break; //////////////////////////////////////////////////////////// case L_EQ: if(!stack(1).equal(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_NEQ: if(!stack(1).not_equal(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_RT: if(!stack(1).rt(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_RE: if(!stack(1).re(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_LT: if(!stack(1).lt(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_LE: if(!stack(1).le(stack(0),stack(1))) raise("not valid operation"); pop(); break; //////////////////////////////////////////////////////////// case L_NOT: if(!stack(0).not_value(stack(0))) raise("not valid operation"); break; case L_OR: if(!stack(1).or_value(stack(0),stack(1))) raise("not valid operation"); pop(); break; case L_AND: if(!stack(1).and_value(stack(0),stack(1))) raise("not valid operation"); pop(); break; //////////////////////////////////////////////////////////// case L_GET_GLOBAL: push( global(context,cmp.m_arg) ); break; case L_SET_GLOBAL: global(context,cmp.m_arg) = pop(); break; //////////////////////////////////////////////////////////// case L_GET_LOCAL: push( strick_local(context,cmp.m_arg) ); break; case L_SET_LOCAL: strick_local(context,cmp.m_arg) = pop(); break; //////////////////////////////////////////////////////////// case L_SET_UP_VALUE: local(context,cmp.m_arg) = pop(); break; case L_GET_UP_VALUE: push( local(context,cmp.m_arg) ); break; //////////////////////////////////////////////////////////// case L_GET_THIS: push(context.this_field()); break; case L_SET_THIS: context.this_field() = pop(); break; case L_SET_THIS_NPOP: context.this_field() = stack(cmp.m_arg); break; //////////////////////////////////////////////////////////// case L_NEW_ARRAY: { register3(0) = l_array::gc_new(get_gc()); //init ? if( cmp.m_arg > 0 ) { //types l_array* vector = register3(0).array(); //put stack into vector for(int i = cmp.m_arg-1; i >= 0; --i) { vector->operator[](i) = pop(); } } //push array (n.b. gc run...) push( register3(0) ); } break; //alloc tablet case L_NEW_TABLE: { register3(0) = l_table::gc_new(get_gc()); //init ? if( cmp.m_arg > 0 ) { //types l_table* table = register3(0).table(); //assert assert(!(cmp.m_arg % 2)); //put stack into vector for(int i = (cmp.m_arg)-1; i >= 0; i-=2) { //push key and value table->operator[](stack(1)) = stack(0); //pop value pop(); //pop key pop(); } } //push table (n.b. gc run...) push( register3(0) ); } break; case L_GET_AT_VAL: { l_variable& r_b = stack(1); const l_variable& r_c = stack(0); //try if ( r_b.is_object() ) { //is a vector if(r_b.is_array()) { //types l_array* vector = r_b.array(); //to size int size_t index = 0; //cast if( r_c.is_int() ) index= (size_t)r_c.m_value.m_i; else if( r_c.is_float() )index= (size_t)r_c.m_value.m_f; else raise( "value isn't a valid key" ); //save last get_this() = stack(1); //get stack(1) = vector->operator[](index) ; } else if(r_b.is_table()) { //types l_table* table = r_b.table(); //is a string? if(!r_c.is_string()) raise( "value isn't a valid key" ); //save last get_this() = stack(1); //get and pop value stack(1) = table->operator[](r_c); } else { raise( "value isn't a vector/table, field not available" ); } } else { raise( "value isn't a vector/table/object, field not avaliable" ); } //pop index pop(); } break; case L_SET_AT_VAL: { //get table/array l_variable& r_a = stack(2); //get index const l_variable& r_b = stack(1); //try if ( r_a.is_object() ) { //is a vector if(r_a.is_array()) { //types l_array* vector = r_a.array(); //to size int size_t index = 0; //cast if( r_b.is_int() ) index= (size_t)r_b.m_value.m_i; else if( r_b.is_float() ) index= (size_t)r_b.m_value.m_f; else raise( "value isn't a valid key" ); //get and pop value vector->operator[](index) = pop(); } else if(r_a.is_table()) { //types l_table* table = r_a.table(); //is a string? if(!r_b.is_string()) raise( "value isn't a valid key" ); //get and pop value table->operator[](r_b) = pop(); } else { raise( "value isn't a vector/table, field not available" ); } } else { //pop value pop(); } //pop index pop(); //pop array/tablet pop(); } break; //for in case L_IT: { //get index l_variable& r_a = top(); //.. //try if ( r_a.is_object() ) { //get object l_obj* this_obj = (l_obj*)r_a.m_value.m_pobj; //is a vector if(r_a.is_array()) { //types l_array* vector = r_a.array(); //pop value pop(); //push it push( vector->get_it() ); } else if (r_a.is_table()) { //types l_table* table = r_a.table(); //pop value pop(); //push it push( table->get_it() ); } else if (r_a.to<l_xrange>()) { //types l_xrange* xrange = static_cast< l_xrange* > ( this_obj ); //pop value pop(); //push it push( xrange->get_it() ); } else { raise( "this value not have a iterator" ); } } else { //pop value pop(); //.. raise( "value isn't a table/array/object, iterator not supported" ); } } break; //for of case L_FOR_IN: case L_FOR_OF: { //get index l_variable& r_it = top(); //try if ( r_it.is_iterator() ) { //types l_iterator* l_it = r_it.iterator(); //is array it if(l_it) { //else assert assert(l_it); //push it if(l_it->valid()) { if(cmp.m_op_code == L_FOR_OF) { //get next push( l_it->get() ); } else //L_FOR_IN { //get next push( l_it->get_id() ); } //next l_it->self_next(); } else { //pop iterator pop(); //and jump pc = cmp.m_arg - 1; } } else { raise( "value isn't a valid iterator" ); } } else { //pop it pop(); //and jump pc = cmp.m_arg - 1; //... raise( "value isn't an iterator" ); } } break; case L_THIS_CALL: case L_CALL: { //get index register3(0) = pop(); //get args if( register3(0).is_cfunction() ) { //return size int n_return = register3(0).m_value.m_pcfun(this,cmp.m_arg); //assert (1 return) assert(n_return <= 1); //error if(n_return<0) { raise( "native call exception" ); } else if(n_return>1) { raise( "native call can't return more than a value" ); } //pop args for(int i=0; i < cmp.m_arg; ++i) { pop(); } //if return if(n_return) push(get_return()); } else if( register3(0).is_closer() ) { //get context l_closer* closer = register3(0).to<l_closer>(); //else assert if(!closer){ assert(0); }; //new function l_function& call_fun = m_vm->function(closer->get_fun_id()); //save last context l_variable last_ctx = register3(R_CONTEXT); //new context register3(1) = l_call_context::gc_new(get_gc()); l_call_context* new_ctx = register3(1).to<l_call_context>(); //this? if(cmp.m_op_code == L_THIS_CALL) { new_ctx->this_field() = get_this(); } //init new_ctx->init(*closer); //lock context new_ctx->lock(); //n args unsigned int n_fun_args = call_fun.m_args_size; //alloc array args..? if (call_fun.m_have_args_list) { //alloc array register3(3) = l_array::gc_new(get_gc()); } //put arguments for(unsigned int arg = 0; arg != cmp.m_arg; ++arg) { if (arg < n_fun_args) { new_ctx->variable( call_fun.constant(arg) ) = pop(); } else if (call_fun.m_have_args_list) { register3(3).array()->push(pop()); } else { pop(); } } //add var list if (call_fun.m_have_args_list) { //push array new_ctx->variable( call_fun.constant(n_fun_args) ) = register3(3); //to null register3(3) = l_variable(); } //save stack long stack_top_bf_call = m_top; //execute call type_return n_return = execute(*new_ctx); //error? if(n_return==T_RETURN_ERROR) { raise( "call exception" ); } //unlock context new_ctx->unlock(); //reset last context register3(R_CONTEXT) = last_ctx; //restore stack m_top = stack_top_bf_call; //return? if(n_return == T_RETURN_VALUE) { push(register3(2)); } } else { raise( "value isn't an function" ); } //dealloc if(cmp.m_op_code == L_THIS_CALL) { get_this() = l_variable(); } } break; default: break; } } return T_RETURN_VOID; }