示例#1
0
static void throw_loop_edge_prepare(
		gravm_runstack_t *self)
{
	if(self->cb->edge_abort != NULL && it_prev(&self->top->out_it)) /* previously prepared edges for which abort() needs to be called? */
		self->top->out_cur = self->top->out_it.it.element;
	else
		self->top->out_cur = NULL;
	self->top->ip = GRAVM_RS_IP_BEGIN_EDGE_UNPREPARE;
}
示例#2
0
static void throw_begin_edge_unprepare(
		gravm_runstack_t *self)
{
	int ret;

	if(self->top->out_cur != NULL) { /* prepared edges remaining, abort them */
		assert(self->cb->edge_abort != NULL);
		ret = self->cb->edge_abort(self->user, self->throw_code, self->top->out_cur->id, self->top->user);
		self->invoked = true;
		if(it_prev(&self->top->out_it))
			self->top->out_cur = self->top->out_it.it.element;
		else
			self->top->out_cur = NULL;
		switch(ret) {
			case GRAVM_RS_SUCCESS:
				return;
			THROW_EXCEPTION_CASES
		}
	}
示例#3
0
static void exec_loop_edge_unprepare(
		gravm_runstack_t *self)
{
	int ret;

	assert(self->cb->edge_unprepare != NULL);
	assert(self->top->out_cur != NULL);
	ret = self->cb->edge_unprepare(self->user, self->top->out_cur->id, self->top->user);
	self->invoked = true;
	switch(ret) {
		case GRAVM_RS_SUCCESS:
			if(it_prev(&self->top->out_it))
				self->top->out_cur = self->top->out_it.it.element;
			else
				self->top->ip++;
			return;
		EXEC_EXCEPTION_CASES
	}
}
示例#4
0
static void _rt_run(struct _rt_invocation* inv)
{
	struct _rt_stack* sp = inv->top->sp;
	while(1)
	{
		int tmp;
		switch(*inv->top->pc++)
		{
		case OP_NOOP:
			break;
		case OP_DEBUG:
			break;
		case OP_POP:
			sp++;
			break;
		case OP_ADD:
			if(_rt_num(inv,sp) || _rt_num(inv,sp + 1))
				break;
			sp[1].num += sp[0].num;
			sp++;
			break;
		case OP_SUB:
			if(_rt_num(inv,sp) || _rt_num(inv,sp + 1))
				break;
			sp[1].num -= sp[0].num;
			sp++;
			break;
		case OP_MUL:
			if(_rt_num(inv,sp) || _rt_num(inv,sp + 1))
				break;
			sp[1].num *= sp[0].num;
			sp++;
			break;
		case OP_DIV:
			if(_rt_num(inv,sp) || _rt_num(inv,sp + 1) || sp->num == 0)
				break;
			sp[1].num /= sp[0].num;
			sp++;
			break;
		case OP_NOT:
			sp->num = _rt_test(sp) == 0;
			sp->type = STACK_NUM;
			break;
		case OP_NEG:
			if(_rt_num(inv,sp))
				break;
			sp->num *= -1;
			break;

		case OP_EQ:
			sp[1].num = _rt_equal(inv,sp,sp + 1);
			sp[1].type = STACK_NUM;
			sp++;
			break;
		case OP_NE:
			sp[1].num = _rt_equal(inv,sp,sp + 1) == 0;
			sp[1].type = STACK_NUM;
			sp++;
			break;
		case OP_GE:
			sp[1].num = _rt_compare(inv,sp,sp + 1) >= 0;
			sp++;
			break;
		case OP_GT:
			sp[1].num = _rt_compare(inv,sp,sp + 1) > 0;
			sp++;
			break;
		case OP_LE:
			sp[1].num = _rt_compare(inv,sp,sp + 1) <= 0;
			sp++;
			break;
		case OP_LT:
			sp[1].num = _rt_compare(inv,sp,sp + 1) < 0;
			sp++;
			break;

		case OP_BNZ:
			// emit Is (branch forward conditional)
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			if(_rt_test(sp))
				inv->top->pc += tmp;
			sp++;
		case OP_BZ:
			// emit Is (branch forward conditional)
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			if(_rt_test(sp) == 0)
				inv->top->pc += tmp;
			sp++;
			break;
		case OP_BR:
			// emit Is (branch forward)
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += tmp + sizeof(ushort);
			break;

		case OP_LOOP:	// JIT-HOOK 
			// emit Is (branch back)
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc -= tmp - sizeof(ushort);
			break;
		case OP_ZLOOP:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			if(_rt_test(sp) == 0)
				inv->top->pc -= tmp;
			sp++;
			break;
		case OP_NZLOOP:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			if(_rt_test(sp))
				inv->top->pc -= tmp;
			sp++;
			break;

		case OP_FREE:
			// emit Ic2 (byte,byte)
			tmp = *inv->top->pc++;
			while(tmp-- > 0)
				_rt_free(inv,&inv->top->vars[tmp + *inv->top->pc]);
			inv->top->pc++;
			break;

		case OP_NULL:		// remove
			sp--;
			sp->type = STACK_NULL;
			break;
		case OP_IMM:
			// emit II (imm short)
			sp--;
			sp->type = STACK_NUM;
			sp->num = *((short*)inv->top->pc);
			inv->top->pc += sizeof(short);
			break;
		case OP_STR:
			// emit Is
			sp--;
			sp->type = STACK_RO_PTR;
			sp->single_ptr = inv->top->code->strings;
			st_move(inv->t,&sp->single_ptr,inv->top->pc,sizeof(ushort));
			inv->top->pc += sizeof(ushort);
			break;
		case OP_OBJ:
			sp--;
			sp->type = STACK_OBJ;
			sp->ptr = sp->obj = inv->top->object;
			cle_skip_header(inv->hdl->inst,&sp->ptr);
			break;

		case OP_NEW:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			sp--;
//			if(cle_goto_object_cdat(inv->hdl->inst,inv->top->pc,tmp,&sp->obj))
				if (1)
				_rt_error(inv,__LINE__);
			else
			{
				inv->top->pc += tmp;
				if(_rt_new_obj(inv,sp))
					_rt_error(inv,__LINE__);
			}
			break;
		case OP_CLONE:
			if(sp->type != STACK_OBJ)
				_rt_error(inv,__LINE__);
			else if(_rt_new_obj(inv,sp))
				_rt_error(inv,__LINE__);
			break;
		case OP_ID:
			sp--;
			sp->type = STACK_OBJ;
			sp->obj = inv->top->object;
			_rt_type_id(inv,sp);
			break;
		case OP_IDO:
			_rt_type_id(inv,sp);
			break;
		case OP_FIND:
			inv->top->pc++;
			if(sp->type == STACK_PTR || sp->type == STACK_RO_PTR)
			{
				if(cle_goto_object(inv->hdl->inst,sp->single_ptr,&sp->obj))
					sp->type = STACK_NULL;
				else
				{
					sp->ptr = sp->obj;
					cle_skip_header(inv->hdl->inst,&sp->ptr);
					sp->type = STACK_OBJ;
				}
			}
			else
				_rt_error(inv,__LINE__);
			break;

		case OP_IT:
			inv->top->pc++;
			sp--;
			switch(sp[1].type)
			{
			case STACK_PROP:
				// try to start iterator on value
				break;
			case STACK_COLLECTION:
				it_create(inv->t,&sp->it,&sp[1].ptr);
				sp->type = STACK_ITERATOR_COL;
				break;
			case STACK_PTR:
			case STACK_RO_PTR:
				it_create(inv->t,&sp->it,&sp[1].single_ptr);
				sp->type = STACK_ITERATOR;
				break;
			default:
				_rt_error(inv,__LINE__);
			}
			break;
		case OP_INEXT:
			tmp = *inv->top->pc++;
			switch(sp->type)
			{
			case STACK_ITERATOR:
				sp->num = it_next(inv->t,0,&sp->it,0);
				break;
			case STACK_ITERATOR_COL:
				sp->num = it_next(inv->t,0,&sp->it,sizeof(oid));
				break;
			default:
				_rt_error(inv,__LINE__);
			}
			sp->type = STACK_NUM;
			break;
		case OP_IPREV:
			tmp = *inv->top->pc++;
			switch(sp->type)
			{
			case STACK_ITERATOR:
				sp->num = it_prev(inv->t,0,&sp->it,0);
				break;
			case STACK_ITERATOR_COL:
				sp->num = it_prev(inv->t,0,&sp->it,sizeof(oid));
				break;
			default:
				_rt_error(inv,__LINE__);
			}
			sp->type = STACK_NUM;
			break;
		case OP_IKEY:
			inv->top->pc++;
			if(sp->type != STACK_ITERATOR && sp->type != STACK_ITERATOR_COL)
				_rt_error(inv,__LINE__);
			else
			{
				st_ptr pt;
				st_empty(inv->t,&pt);
				st_append(inv->t,&pt,sp->it.kdata,sp->it.kused);
				sp->single_ptr = sp->single_ptr_w = pt;
				sp->type = STACK_PTR;
			}
			break;
		case OP_IVAL:
			inv->top->pc++;
			if(sp->type == STACK_ITERATOR)
			{
				st_ptr pt;
				if(it_current(inv->t,&sp->it,&pt) == 0)
				{
					sp->single_ptr = sp->single_ptr_w = pt;
					sp->type = STACK_PTR;
				}
				else
					sp->type = STACK_NULL;
			}
			else if(sp->type == STACK_ITERATOR_COL)
			{
				if(sp->it.kused == sizeof(oid))
				{
					// TODO: move to object.c
					st_ptr pt = inv->hdl->inst.root;
					st_move(inv->t,&pt,sp->it.kdata,sizeof(oid));
					sp->ptr = sp->obj = pt;
					cle_skip_header(inv->hdl->inst,&sp->ptr);
					sp->type = STACK_OBJ;
				}
				else
					sp->type = STACK_NULL;
			}
			else
				_rt_error(inv,__LINE__);
			break;

		case OP_OMV:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			sp--;
			sp->obj = inv->top->object;
			if(cle_get_property_host(inv->hdl->inst,&sp->ptr,inv->top->pc,tmp) < 0)
			{
				sp->type = STACK_NULL;
				inv->top->pc += tmp;
			}
			else
			{
				inv->top->pc += tmp;
				sp->ptr = sp->obj;
				cle_skip_header(inv->hdl->inst,&sp->ptr);
				_rt_get(inv,&sp);
			}
			break;
		case OP_MV:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			if(_rt_move(inv,&sp,inv->top->pc,tmp))
				sp->type = STACK_NULL;
			inv->top->pc += tmp;
			break;
		case OP_RIDX:
			if(sp->type == STACK_NUM)
			{
				char buffer[sizeof(rt_number) + HEAD_SIZE];
				buffer[0] = 0;
				buffer[1] = 'N';
				memcpy(buffer + 2,&sp->num,sizeof(rt_number));
				sp++;
				if(_rt_move(inv,&sp,buffer,sizeof(buffer)))
					sp->type = STACK_NULL;
			}
			else if(sp->type == STACK_PTR ||
				sp->type == STACK_RO_PTR)
			{
				st_ptr mv = sp->single_ptr;
				sp++;
				if(_rt_move_st(inv,&sp,&mv))
					sp->type = STACK_NULL;
			}
			break;
		case OP_LVAR:
			sp--;
			*sp = inv->top->vars[*inv->top->pc++];
			break;

		// writer
		case OP_POPW:
			if(sp->type == STACK_OUTPUT)
				sp->out->pop(sp->outdata);
			else
				sp++;
			break;
		case OP_DMVW:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			switch(sp->type)
			{
			case STACK_REF:
				if(sp->var->type == STACK_NULL)
				{
					st_empty(inv->t,&sp->var->single_ptr_w);
					sp->var->single_ptr = sp->var->single_ptr_w;
				}
				else if(sp->var->type != STACK_PTR)
				{
					_rt_error(inv,__LINE__);
					return;
				}
				sp->single_ptr_w = sp->var->single_ptr;
				sp->single_ptr = sp->single_ptr_w;
				sp->type = STACK_PTR;
			case STACK_PTR:
				sp--;
				sp[0] = sp[1];
				st_insert(inv->t,&sp->single_ptr_w,inv->top->pc,tmp);
				break;
			case STACK_OUTPUT:
				if(inv->response_started == 0)
				{
					sp->out->start(sp->outdata);
					inv->response_started = 1;
				}
				else inv->response_started = 2;
				sp->out->push(sp->outdata);
				sp->out->data(sp->outdata,inv->top->pc,tmp);
			}
			inv->top->pc += tmp;
			break;
		case OP_MVW:
			tmp = *((ushort*)inv->top->pc);
			inv->top->pc += sizeof(ushort);
			switch(sp->type)
			{
			case STACK_PTR:
				st_insert(inv->t,&sp->single_ptr_w,inv->top->pc,tmp);
				break;
			case STACK_OUTPUT:
				if(inv->response_started == 0)
				{
					sp->out->start(sp->outdata);
					inv->response_started = 1;
				}
				else inv->response_started = 2;
				sp->out->data(sp->outdata,inv->top->pc,tmp);
			}
			inv->top->pc += tmp;
			break;
		case OP_WIDX:	// replace by OP_OUT ?
			_rt_out(inv,&sp,sp,sp + 1);
			sp++;
			break;

		case OP_OPEN:
			_rt_do_open(inv,&sp);
			break;
		case OP_OPEN_POP:
			// unfinished output
			if(inv->response_started == 2)
				sp->out->next(sp->outdata);
			sp->out->end(sp->outdata,0,0);
			inv->response_started = 1;
			tk_commit_task(sp->outtask);	// well, what if something went wrong??
			sp++;
			break;
		// receive input
		case OP_RECV:
			sp += *inv->top->pc++;
			inv->top->sp = sp;
			return;

		case OP_SET:
			if(inv->top->is_expr != 0)
				_rt_error(inv,__LINE__);
			else if(sp[1].type != STACK_PROP)
				_rt_error(inv,__LINE__);
			else
			{
				switch(sp->type)
				{
				case STACK_PROP:
					if(cle_identity_value(inv->hdl->inst,sp->prop_id,sp->prop_obj,&sp->ptr))
						_rt_error(inv,__LINE__);
					if(cle_set_property_ptr(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,&sp[1].ptr))
						_rt_error(inv,__LINE__);
					// might not be a good idea if prop-val is a mem-ref
					st_copy_st(inv->t,&sp[1].ptr,&sp->ptr);
					break;
				case STACK_RO_PTR:
					// link
					if(cle_set_property_ptr(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,&sp[1].ptr))
						_rt_error(inv,__LINE__);
					st_link(inv->t,&sp[1].ptr,&sp->single_ptr);
					break;
				case STACK_PTR:
					// copy 
					if(cle_set_property_ptr(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,&sp[1].ptr))
						_rt_error(inv,__LINE__);
					st_copy_st(inv->t,&sp[1].ptr,&sp->single_ptr);
					break;
				case STACK_NUM:
					// bin-num
					if(cle_set_property_num(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,sp->num))
						_rt_error(inv,__LINE__);
					break;
				case STACK_OBJ:
					// obj-ref
					if(cle_set_property_ref(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,sp->obj))
						_rt_error(inv,__LINE__);
					break;
				case STACK_CODE:
					// write out path/event to method/handler
					if(st_move(inv->t,&sp->single_ptr,"p",1) == 0)
					{
						if(cle_set_property_ptr(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,&sp[1].ptr))
							_rt_error(inv,__LINE__);
						st_copy_st(inv->t,&sp[1].ptr,&sp->single_ptr);
						break;
					}	// or null
				default:
					// empty / null
					if(cle_set_property_ptr(inv->hdl->inst,sp[1].prop_obj,sp[1].prop_id,&sp[1].ptr))
						_rt_error(inv,__LINE__);
				}
			}
			sp += 2;
			break;
		case OP_MERGE:
			switch(sp->type)
			{
			case STACK_PROP:
				if(inv->top->is_expr != 0)
					_rt_error(inv,__LINE__);
				else if(cle_set_property_ptr(inv->hdl->inst,sp->prop_obj,sp->prop_id,&sp->single_ptr))
					_rt_error(inv,__LINE__);
				else
				{
					sp->single_ptr_w = sp->single_ptr;
					sp->type = STACK_PTR;
				}
				break;
			case STACK_REF:
				if(sp->var->type == STACK_NULL)
				{
					st_empty(inv->t,&sp->var->single_ptr);
					sp->var->single_ptr_w = sp->var->single_ptr;
					sp->var->type = STACK_PTR;
				}
				else if(sp->var->type != STACK_PTR)
					_rt_error(inv,__LINE__);
			case STACK_PTR:
			case STACK_OUTPUT:
				break;
			default:
				_rt_error(inv,__LINE__);
			}
			break;
		case OP_2STR:
			tmp = *inv->top->pc++;	// vars
			if(tmp != 1)
			{
				_rt_error(inv,__LINE__);
				break;
			}
			// fall throu
		case OP_CAT:
			{
				struct _rt_stack to;
				st_empty(inv->t,&to.single_ptr);
				to.single_ptr_w = to.single_ptr;
				to.type = STACK_PTR;
				_rt_out(inv,&sp,&to,sp);
				*sp = to;
			}
			break;
		case OP_NEXT:	// non-string (concat) out-ing [OUT Last Tree]
			if(sp[1].type == STACK_REF)
			{
				if(sp[1].var->type == STACK_NULL)
					*sp[1].var = *sp;
				else _rt_ref_out(inv,&sp,sp + 1);
			}
			else
			{
				if(_rt_out(inv,&sp,sp + 1,sp) == 0)
				{
					sp++;
					if(inv->response_started == 2 && sp->type == STACK_OUTPUT)
					{
						inv->response_started = 1;
						sp->out->next(sp->outdata);
					}
				}
			}
			break;
		case OP_OUTL:
			// TODO: stream out structures
		case OP_OUT:	// stream out string
			if(sp[1].type == STACK_REF)
				_rt_ref_out(inv,&sp,sp + 1);
			else
				_rt_out(inv,&sp,sp + 1,sp);
			sp++;
			break;

		case OP_AVAR:
			inv->top->vars[*inv->top->pc++] = *sp;
			sp++;
			break;
		case OP_DEFP:
			// emit Is2 (branch forward)
			tmp = *inv->top->pc++;	// var
			if(inv->top->vars[tmp].type == STACK_NULL)
			{
				sp--;
				inv->top->vars[tmp].var = sp;
				inv->top->vars[tmp].type = STACK_REF;
				inv->top->pc += sizeof(ushort);
			}
			else
			{
				tmp = *((ushort*)inv->top->pc);
				inv->top->pc += tmp + sizeof(ushort);
			}
			break;
		case OP_END:
			tmp = inv->top->code->body.maxparams;
			while(tmp-- > 0)
				_rt_free(inv,&inv->top->vars[tmp]);

			if(inv->top->parent == 0)
			{
				// unfinished output? -> next
				if(inv->response_started == 2)
					inv->hdl->response->next(inv->hdl->respdata);

				cle_stream_end(inv->hdl);
				return;
			}
			else
			{
				struct _rt_callframe* cf = inv->top;
				inv->top = inv->top->parent;
				sp = inv->top->sp;

				// unref page of origin
				tk_unref(inv->t,cf->pg);
			}
			break;
		case OP_DOCALL:
			tmp = *inv->top->pc++;	// params
			if(_rt_call(inv,sp,tmp) == 0)
			{
				inv->top->parent->sp = sp + 1 + tmp;	// return-stack
				*(--inv->top->sp) = *(sp + 1 + tmp);	// copy output-target
				sp = inv->top->sp;		// set new stack
			}
			break;
		case OP_DOCALL_N:
			tmp = *inv->top->pc++;	// params
			if(_rt_call(inv,sp,tmp) == 0)
			{
				inv->top->parent->sp = sp + tmp;	// return-stack
				inv->top->sp--;
				inv->top->sp->type = STACK_REF;	// ref to sp-top
				inv->top->sp->var = sp + tmp;
				inv->top->sp->var->type = STACK_NULL;
				sp = inv->top->sp;		// set new stack
			}
			break;
		case OP_ERROR:	// system exception
			return;
		default:
			_rt_error(inv,__LINE__);
		}
	}
}