static void solve_R1(float p[3], float q[3], float p2[3],float q2[3], float p_scale, Matrix R1) { Matrix T, S; // Construct two local coordinate systems // and find the transformation between them make_frame(p, p_scale, q, T, 1); make_frame(p2, p_scale, q2, S, 0); rmatmult(R1,T,S); }
void send_command(HANDLE * fd, struct receive_tcp_frame * tcp_frame) { struct api_frame frm; struct api_at_command cmd; char frame_buffer[BUF_SIZE]; size_t frame_size; #ifdef _DEBUG_ int i; #endif /* Prepare Cmd */ cmd.frame_id = tcp_frame->frame_id; cmd.command[0] = tcp_frame->command[0]; cmd.command[1] = tcp_frame->command[1]; memcpy(cmd.parameter, tcp_frame->data, tcp_frame->data_size); cmd.size = tcp_frame->data_size; /* Prepare Frame */ frm.cmdid = 0x08; /* Build Frame Data */ make_frame_data_at_command(&cmd, &frm); frame_size=make_frame(&frm, (uint8_t*)frame_buffer, BUF_SIZE); /* Send Frame */ ERR(writeComm(fd, (uint8_t*)frame_buffer, frame_size), "write"); #ifdef _DEBUG_ fprintf(stderr, "DEBUG: Sent XBee frame ["); for(i = 0 ; i < frame_size; ++i) fprintf(stderr, "%02X ", frame_buffer[i]); fprintf(stderr, "]\n"); #endif }
machine *make_machine() { machine *ret = NEW(machine); ret->base_frame = make_frame(NULL, make_table(), make_table(), make_table(), NULL, PAUSE); incref(ret->base_frame); ret->current_frame = ret->base_frame; incref(ret->current_frame); ret->now = ret->base_frame; incref(ret->now); ret->accumulator = NULL; ret->paused = 0; ret->trace = make_stack_trace(arg("bottom-of-the-barrel"), NULL, NULL); incref(ret->trace); add_builtins(ret); add_builtin_numbers(ret); add_builtin_strings(ret); add_builtin_files(ret); return ret; }
void send_to_frame(int fd, uint8_t * data, size_t size) { struct api_frame frm, frm2; struct api_transmit_64 trans; uint8_t frame_buffer[BUF_SIZE]; size_t frame_size; int i; //Prepare Trans memcpy(trans.dest_address, broadcast_address_64, 8); trans.frame_id = 20; trans.options = 0; memcpy(trans.rf_data, data, (size>100?100:size)); trans.size = (size>100?100:size); //Prepare Frame frm.cmdid = 0x00; //Build frame data make_frame_data_transmit_64(&trans, &frm); frame_size=make_frame(&frm, frame_buffer, BUF_SIZE); //Send Frame ERR(write(fd, frame_buffer, frame_size), "write"); cut_frame(frame_buffer, frame_size, &frm2); printf("Frame sent rsize %i size %i id %2X checksum %2X\nData:", frame_size, frm2.size, frm2.cmdid, frm2.checksum); for(i = 0; i < frm2.data_size; ++i) printf("%2X,", frm2.data[i]); printf("\n"); }
void push_instruction_list(machine * m, oyster * ins, table * scope, table * scope_below) { incref(ins); frame *top = NULL; frame **cur = ⊤ while (!nilp(ins)) { (*cur) = make_frame(NULL, scope, NULL, scope_below, car(ins), EVALUATE); incref(*cur); cur = &((*cur)->below); oyster *ins2 = cdr(ins); incref(ins2); decref(ins); ins = ins2; } decref(ins); (*cur) = m->current_frame; m->current_frame = top; }
static frame make_lknv_frame(frame f, int n, int copy, rtype type) { char v[8]; string dv; if (copy) { frame cf = make_frame(f->type, NULL, f->cl, f->code, ""); f = cf; } if (f->type == T_SLOT) return make_knv_frame(f, n); sprintf(v, "_v%c%d", LVAC, n); dv = make_decl(type, v); dv[0] = type; if (f->block) { int b = f->block; f = deblock_frame(f, 1); if (b != -1) f = prepare_frame(f, type); } else if (f->type != type) f = coerce_frame(f, type); f->decls = cons(dv, f->decls); return merge_frames(T_CBOOL, T_UNKNOWN, f, NULL, f->cl + 18, "_lkn(" AMP, v, ", ", NORET(f->code), ")", ""); }
/** * @brief Connects the client to the server. * @param QString host - the host name * @param int port - the port used by the server * @param QString pseudo - the client's name */ void MainWindow::serverConnection(QString host, int port, QString pseudo) { strcpy(_player.name, pseudo.toStdString().c_str()); init_host(_ptr_host, (char*)host.toStdString().c_str(), &_local_addr); assign_port(&_local_addr, port); _player.socket = create_socket(); // Have to test if the client can be connect to the server if(server_connection(_player.socket, _local_addr) >= 0) { qDebug() << "[Server_connection] : Client is connected"; startListeners(); // Have to start listeners threads // Ask to the server to add the new client into its array of players qDebug() << "[Server_connection] : Sending information to the server" << _player.name; frame f = make_frame(_local_addr.sin_addr, _local_addr.sin_addr, CONNECT, _player.name); write_to_server(_player.socket, &f); // When the client is connected, display the mainPage of the application ui->stackedWidget->slideInIdx(1, SlidingStackedWidget::BOTTOM2TOP); } else { //Connection is impossible QMessageBox errorBox(QMessageBox::Question,tr("error"),tr("Can't establish the connection with the server."),QMessageBox::Cancel); errorBox.exec(); } }
static frame make_knv_frame(frame f, int n) { frame fc = make_frame(f->type, copy_list(f->decls, 0), 6, "_knv(" AMP, ""); char v[8], buf[512]; int i, l; string dv, st, next; sprintf(v, "_v%c%d", LVAC, n); dv = make_decl(T_ATOM, v); for (i = 0, st = f->code; ; st = next + 1) { next = strchr(st, NSTC); l = next ? next - st : strlen(st); strncpy(buf + i, st, l); i += l; strcpy(buf + i, ", "); i += 2; if (!next) break; } strcpy(buf + i, "NULL)"); i += 5; fc->decls = cons(dv, fc->decls); return merge_frames(T_CBOOL, T_UNKNOWN, fc, NULL, fc->cl + i + 9, fc->code, v, ", ", buf, ""); }
void send_to_frame(HANDLE * fd, struct receive_tcp_frame * tcp_frame) { struct api_frame frm; struct api_transmit_64 trans; char frame_buffer[BUF_SIZE]; size_t frame_size; #ifdef _DEBUG_ int i; #endif /* Prepare Trans */ memcpy(trans.dest_address, tcp_frame->address, 8); trans.frame_id = tcp_frame->frame_id; trans.options = 0; memcpy(trans.rf_data, tcp_frame->data, (tcp_frame->data_size>100?100:tcp_frame->data_size)); trans.size = (tcp_frame->data_size>100?100:tcp_frame->data_size); /* Prepare Frame */ frm.cmdid = 0x00; /* Build frame data */ make_frame_data_transmit_64(&trans, &frm); frame_size=make_frame(&frm, (uint8_t*)frame_buffer, BUF_SIZE); /* Send Frame */ ERR(writeComm(fd, (uint8_t*)frame_buffer, frame_size), "write"); #ifdef _DEBUG_ fprintf(stderr, "DEBUG: Sent XBee frame ["); for(i = 0 ; i < frame_size; ++i) fprintf(stderr, "%02X ", frame_buffer[i]); fprintf(stderr, "]\n"); #endif }
void main() { //制作游戏窗口 make_frame(); //开始游戏 start_game(); }
item extend_environment(item unev, item argl, item env){ if (length(unev) == length(argl)){ return cons(make_frame(unev, argl), env); } else{ fprintf(stderr, "Too many or too few arguments supplied"); exit(1); } }
void push_new_instruction(machine * m, oyster * instruction, int flag) { frame *t = m->current_frame; m->current_frame = make_frame(t, m->now->scope, m->now->scope_to_be, m->now->scope_below, instruction, flag); incref(m->current_frame); decref(t); }
/** * @brief Sends to the server the message to send to all clients. * This message is formatted like that : "[player_name] : msg". * @param QString msg - the message to send. */ void MainWindow::sendChatMessage(QString msg) { qDebug() << msg; char data[DATA_SIZE] = "\0"; strcat(data, "["); strcat(data, _player.name); strcat(data, "] : "); strcat(data, msg.toStdString().c_str()); frame f = make_frame(_local_addr.sin_addr, _local_addr.sin_addr, SEND_MSG_CHAT, data); write_to_server(_player.socket, &f); }
data_t *extend_environment(const data_t *vars, const data_t *vals, data_t *env) { int lvars = length(vars), lvals = length(vals); if(lvars == lvals) return cons(make_frame(vars, vals), env); if(lvars < lvals) { printf("Too many arguments supplied. (Expected %d, got %d)\n", lvars, lvals); return make_symbol("error"); } else { printf("Too few arguments supplied (Expected %d, got %d)\n", lvars, lvals); return make_symbol("error"); } }
PVideoFrame __stdcall LSMASHVideoSource::GetFrame( int n, IScriptEnvironment *env ) { uint32_t sample_number = n + 1; /* For L-SMASH, sample_number is 1-origin. */ codec_configuration_t *config = &vdh.config; config->lh.priv = env; if( config->error ) return env->NewVideoFrame( vi ); if( libavsmash_get_video_frame( &vdh, sample_number, vi.num_frames ) < 0 ) return env->NewVideoFrame( vi ); PVideoFrame as_frame; if( make_frame( &voh, config->ctx, vdh.frame_buffer, as_frame, env ) < 0 ) env->ThrowError( "LSMASHVideoSource: failed to make a frame." ); return as_frame; }
void execute(Chunk *chunk) { Closure *closure = make_closure(chunk); Frame *frame = make_frame(NULL, closure); VM *vm = make_vm(frame, 0); execute_function(vm); gc(vm); free(vm); // TODO - free last closure [?] // Other closrues should be already taken care of // by the last gc sweep, but this one existed outside // of the heap. }
frame make_cmp_frame(frame f1, frame f2, string op, rtype type, int l, int trsl, int abs) { rtype num = num_type(type) ? type : common_num_type(f1->type, f2->type); if (trsl && (!det_type(f1->type) || !det_type(f2->type) || f1->block == -1 || f2->block == -1)) { if (det_type(f1->type)) f1 = prepare_frame(f1, num); if (det_type(f2->type)) f2 = prepare_frame(f2, num); return make_trsl_frame(f1, f2, num, num == T_NUMBER ? (abs ? merge_fainfix_strings : merge_finfix_strings) : merge_infix_strings, op); } f1 = prepare_frame(f1, num); f2 = prepare_frame(f2, num); f1->code = NORET(f1->code); f2->code = NORET(f2->code); if (num == T_NUMBER) { int n = isnum(f2->code) << 1; string mop = n ? " - " : " - ("; string cp = n ? "" : ")"; if (abs) f1 = merge_frames(num, num, f1, f2, f1->cl + f2->cl + 12 + n, "fabs(", f1->code, mop, f2->code, ")", cp, ""); else f1 = merge_frames(num, num, f1, f2, f1->cl + f2->cl + 5 + n, f1->code, mop, f2->code, cp, ""); f2 = make_frame(num, NULL, l_epsilon + 1, epsilon, ""); } return merge_frames(type == T_UNKNOWN ? num : type, num, f1, f2, f1->cl + f2->cl + l, RET, f1->code, op, f2->code, ""); }
static void coerce_arg(rtype type, rtype ftype, int l, string code, string *buf, int *i, int *lbuf, int int_allowed, frame name) { frame f = make_frame(type, NULL, l, code, ""); if ((type == T_INTNUM || type == T_INTLNG) && !int_allowed) f = coerce_frame(f, T_NUMBER); f = coerce_frame(f, ftype); if (f->decls) name->decls = nconc(name->decls, copy_list(f->decls, 0)); NORET(f->code); *buf = copy_into_buf(*buf, f->code, i, lbuf, strlen(f->code)); mcfree(f->code); mcfree(f); }
static const VSFrameRef *VS_CC vs_filter_get_frame( int n, int activation_reason, void **instance_data, void **frame_data, VSFrameContext *frame_ctx, VSCore *core, const VSAPI *vsapi ) { if( activation_reason != arInitial ) return NULL; lsmas_handler_t *hp = (lsmas_handler_t *)*instance_data; VSVideoInfo *vi = &hp->vi; uint32_t sample_number = MIN( n + 1, vi->numFrames ); /* For L-SMASH, sample_number is 1-origin. */ libavsmash_video_decode_handler_t *vdhp = hp->vdhp; libavsmash_video_output_handler_t *vohp = hp->vohp; if( libavsmash_video_get_error( vdhp ) ) { vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx ); return NULL; } /* Set up VapourSynth error handler. */ vs_basic_handler_t vsbh = { 0 }; vsbh.out = NULL; vsbh.frame_ctx = frame_ctx; vsbh.vsapi = vsapi; lw_log_handler_t *lhp = libavsmash_video_get_log_handler( vdhp ); lhp->priv = &vsbh; lhp->show_log = set_error; /* Get and decode the desired video frame. */ vs_video_output_handler_t *vs_vohp = (vs_video_output_handler_t *)vohp->private_handler; vs_vohp->frame_ctx = frame_ctx; vs_vohp->core = core; vs_vohp->vsapi = vsapi; if( libavsmash_video_get_frame( vdhp, vohp, sample_number ) < 0 ) { vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx ); return NULL; } /* Output video frame. */ AVFrame *av_frame = libavsmash_video_get_frame_buffer( vdhp ); VSFrameRef *vs_frame = make_frame( vohp, av_frame ); if( !vs_frame ) { vsapi->setFilterError( "lsmas: failed to output a video frame.", frame_ctx ); return NULL; } set_frame_properties( vdhp, vi, av_frame, vs_frame, sample_number, vsapi ); return vs_frame; }
static frame prepare_trsl_frame(frame f, frame knv, string trcb) { string trq; string trce = strchr(trcb + 1, TRLC); int l = trcb - f->code; trcb[0] = trce[0] = '\0'; trq = strrchr(f->code, QSMC); trq[-1] = '\0'; knv = knv ? merge_frames(T_UNKNOWN, T_UNKNOWN, knv, NULL, knv->cl + l + 8, knv->code, " " AMP AMP " " NST TABS, f->code, "") : make_frame(T_UNKNOWN, NULL, l + 1, f->code, ""); f = merge_frames(T_UNKNOWN, T_UNKNOWN, f, NULL, trce - trcb, trcb + 1, ""); return knv; }
/** * @brief Disconnects the client from the server. * @pre The client have to be connected before to call this method. */ void MainWindow::serverDisconnection() { // cleaning the gui ui->connectionWidget->clean(); ui->rightMenuWidget->clear(); ui->checkerboardwidget->clear(); frame f ; //Advise the opponent if the client is in a game if(strlen(_opponent_player.name) != 0) { qDebug() << "PPPPPPPPPPPPPPPPPPPPP I'm quit the game"; strcpy(f.data_type, OPPONENT_QUIT); memcpy(f.data, &_opponent_player, sizeof(_opponent_player)); write_to_server(_player.socket, &f); } //Advising the server for the disconnection f = make_frame(_local_addr.sin_addr, _local_addr.sin_addr, DISCONNECT, _player.name); write_to_server(_player.socket,&f); //disconnection of the client server_disconnection(_player.socket); stopListeners(); // Stop all listeners threads qDebug() << "Client is disconnected"; // When the client is disconnected, display the connection page ui->stackedWidget->slideInIdx(0, SlidingStackedWidget::TOP2BOTTOM); strcpy(_player.name, ""); _player.color = 0; strcpy(_opponent_player.name, ""); _opponent_player.color = 0; }
object_t *extend_environment(object_t *vars, object_t *vals, object_t *env) { return cons(make_frame(vars, vals), env); }
/** Run alignment algorithm. \param first_last Last aligned position in first sequence (output) \param second_last Last aligned position in second sequence (output) */ void align(int& first_last, int& second_last) const { adjust_matrix_size(); limit_range(); make_frame(); ASSERT_TRUE(!local() || max_errors() == -1); int& r_row = first_last; int& r_col = second_last; r_row = r_col = -1; for (int row = 0; row <= max_row(); row++) { int start_col = min_col(row); int stop_col = max_col(row); int min_score_col = start_col; for (int col = start_col; col <= stop_col; col++) { ASSERT_TRUE(col >= 0 && col < side()); ASSERT_TRUE(in(row, col)); int match = at(row - 1, col - 1) + substitution(row, col); int gap1 = at(row, col - 1) + gap_penalty(); int gap2 = at(row - 1, col) + gap_penalty(); int score = std::min(match, std::min(gap1, gap2)); if (local()) { score = std::min(score, 0); } at(row, col) = score; if (score < at(row, min_score_col)) { min_score_col = col; } track(row, col) = (score == match) ? MATCH : (score == gap1) ? COL_INC : ROW_INC; } if (max_errors() != -1 && at(row, min_score_col) > max_errors()) { break; } r_row = row; r_col = min_score_col; } if (max_errors() == -1) { // col -> max_col in this row ASSERT_TRUE(in(max_row(), max_col(max_row()))); ASSERT_EQ(r_row, max_row()); r_col = max_col(max_row()); // if stopped earlier because of gap range int last_row = contents().first_size() - 1; int last_col = contents().second_size() - 1; if (r_row == last_row) { while (r_col < last_col) { r_col += 1; track(r_row, r_col) = COL_INC; } } else if (r_col == last_col) { while (r_row < last_row) { r_row += 1; track(r_row, r_col) = ROW_INC; } } else { throw Exception("row and column are not last"); } } }
void execute_function(VM *vm) { restart: { Frame *frame = vm->current; Closure *closure = frame->closure; Chunk *chunk = closure->chunk; StackObject *registers = frame->registers; while (frame->pc < chunk->numinstructions) { int instruction = chunk->instructions[frame->pc]; OpCode o = GET_O(instruction); int a = GET_A(instruction); int b = GET_B(instruction); int c = GET_C(instruction); switch (o) { case OP_MOVE: { if (b < 256) { copy_object(®isters[a], ®isters[b]); } else { copy_constant(vm, ®isters[a], chunk->constants[b - 256]); } } break; case OP_GETUPVAR: { Upval *upval = closure->upvals[b]; if (!upval->open) { // upval is closed copy_object(®isters[a], upval->data.o); } else { // still on stack copy_object(®isters[a], &upval->data.ref.frame->registers[upval->data.ref.slot]); } } break; case OP_SETUPVAR: { Upval *upval = closure->upvals[b]; if (!upval->open) { // upval is closed copy_object(upval->data.o, ®isters[a]); } else { // still on stack copy_object(&upval->data.ref.frame->registers[upval->data.ref.slot], ®isters[a]); } } break; case OP_ADD: { // TODO - make string coercion better // TODO - make string type with special operators if (IS_STR(b) || IS_STR(c)) { char *arg1 = TO_STR(b); char *arg2 = TO_STR(c); char *arg3 = malloc((strlen(arg1) + strlen(arg2) + 1) + sizeof *arg3); strcpy(arg3, arg1); strcat(arg3, arg2); registers[a].value.o = make_string_ref(vm, arg3); registers[a].type = OBJECT_REFERENCE; // put this after free(arg1); free(arg2); } else { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Cannot add types."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 + arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 + arg2; } } } break; case OP_SUB: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to sub non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 - arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 - arg2; } } break; case OP_MUL: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to mul non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 * arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 * arg2; } } break; case OP_DIV: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if ((IS_INT(c) && AS_INT(c) == 0) || (IS_REAL(c) && AS_REAL(c) == 0)) { fatal("Div by 0."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 / arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 / arg2; } } break; case OP_MOD: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if ((IS_INT(c) && AS_INT(c) == 0) || (IS_REAL(c) && AS_REAL(c) == 0)) { fatal("Mod by 0."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 % arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.i = fmod(arg1, arg2); } } break; case OP_POW: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = (int) pow(arg1, arg2); } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = pow(arg1, arg2); } } break; case OP_NEG: { if (IS_INT(b)) { registers[a].type = OBJECT_INT; registers[a].value.i = -AS_INT(b); } else if (IS_REAL(b)) { registers[a].type = OBJECT_INT; registers[a].value.i = -AS_REAL(b); } else { fatal("Tried to negate non-numeric type."); } } break; case OP_NOT: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } registers[a].value.i = registers[a].value.i == 1 ? 0 : 1; } break; case OP_EQ: { if ((IS_INT(b) || IS_REAL(b)) && (IS_INT(c) || IS_REAL(c))) { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 == arg2; } else { fatal("Comparison of reference types not yet supported."); } } break; case OP_LT: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to compare non-numbers."); } double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 < arg2; } break; case OP_LE: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to compare non-numbers."); } double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 <= arg2; } break; case OP_CLOSURE: { Closure *child = make_closure(chunk->children[b]); int i; for (i = 0; i < chunk->children[b]->numupvars; i++) { int inst = chunk->instructions[++frame->pc]; OpCode oc = GET_O(inst); int ac = GET_A(inst); int bc = GET_B(inst); int cc = GET_C(inst); if (oc == OP_MOVE) { // first upval for this variable child->upvals[ac] = make_upval(vm, bc); } else { // share upval child->upvals[ac] = closure->upvals[bc]; child->upvals[ac]->refcount++; } } registers[a].value.o = make_closure_ref(vm, child); registers[a].type = OBJECT_REFERENCE; // put this after } break; case OP_CALL: { if (registers[b].type != OBJECT_REFERENCE || registers[b].value.o->type != OBJECT_CLOSURE) { fatal("Tried to call non-closure."); } // TODO - safety issue (see compile.c for notes) Closure *child = registers[b].value.o->value.c; Frame *subframe = make_frame(frame, child); int i; for (i = 0; i < child->chunk->numparams; i++) { copy_object(&subframe->registers[i + 1], ®isters[c + i]); } vm->current = subframe; goto restart; } break; case OP_RETURN: { UpvalNode *head; for (head = vm->open; head != NULL; ) { Upval *u = head->upval; if (u->data.ref.frame == frame) { StackObject *o = malloc(sizeof *o); if (!o) { fatal("Out of memory."); } u->open = 0; copy_object(o, ®isters[u->data.ref.slot]); u->data.o = o; if (vm->open == head) { vm->open = head->next; } else { head->next->prev = head->prev; head->prev->next = head->next; } UpvalNode *temp = head; head = head->next; free(temp); } else { head = head->next; } } if (vm->current->parent != NULL) { Frame *p = vm->current->parent; StackObject *target = &p->registers[GET_A(p->closure->chunk->instructions[p->pc++])]; if (b < 256) { // debug char *d = obj_to_str(®isters[b]); printf("Return value: %s\n", d); free(d); copy_object(target, ®isters[b]); } else { copy_constant(vm, target, chunk->constants[b - 256]); } free_frame(frame); vm->current = p; goto restart; } else { // debug char *d = obj_to_str(®isters[b]); printf("Return value: %s\n", d); free(d); free_frame(frame); vm->current = NULL; return; } } break; case OP_JUMP: frame->pc += c ? -b : b; break; case OP_JUMP_TRUE: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } if (registers[a].value.i == 1) { frame->pc += c ? -b : b; } } break; case OP_JUMP_FALSE: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } if (registers[a].value.i == 0) { frame->pc += c ? -b : b; } } break; case OP_ENTER_TRY: { vm->catchframe = make_catch_frame(frame, vm->catchframe, frame->pc + b); } break; case OP_LEAVE_TRY: { CatchFrame *temp = vm->catchframe; vm->catchframe = vm->catchframe->parent; free_catch_frame(temp); } break; case OP_THROW: { // TODO - replace unwinding of stack with an exceptions // table per-chunk. It will have an instructions range, // the starting instruction of a handler, and the type of // exception that it may handle. // Exception table: // From To Target Type // 0 4 5 Class TestExc1 // 0 12 12 Class TestExc2 // TODO - implement a way to expect an exception // of a given type instead of a generic catch-all. char *s = obj_to_str(®isters[a]); printf("Exception value: %s!\n", s); free(s); // TODO - this is probably wrong. Not sure how complicated // it will be to handle upvalues and frame destruction here, // so we're just doing it a shitty way for now :D [GO LAZE]. if (!vm->catchframe) { // TODO - print a stack trace [ requires debug symbols :( ] fatal("Exception thrown outside of handler."); } while (vm->current != vm->catchframe->frame) { // TODO - destruct frame vm->current = vm->current->parent; } vm->current->pc = vm->catchframe->target; CatchFrame *temp = vm->catchframe; vm->catchframe = vm->catchframe->parent; free_catch_frame(temp); goto restart; } break; } frame->pc++; } fatal("VM left instruction-space."); } }
frame_ptr make_frame(widget_ptr w, const std::string& name) { key_mapper_ptr keys(new key_mapper()); return make_frame(w, name, keys); }