void compile_triple_set(compiler_wrapper *cw, ast_node *n) { ast_triple_set_node *node = (ast_triple_set_node *)n; if(node->index_node->type == AINDEX) { ast_index_node *idn = (ast_index_node *)node->index_node; compile(cw, idn->target); compile(cw, idn->indexer); append_op(cw, LI_DDUPLICATE, node->lineno); append_op(cw, LI_LOAD_INDEX, node->lineno); compile(cw, node->new_val); append_op(cw, instr_for_char(node->op), node->lineno); append_op(cw, LI_SINK_FIRST, node->lineno); append_op(cw, LI_SAVE_INDEX, node->lineno); } else { ast_member_access_node *man = (ast_member_access_node *)node->index_node; char *name = man->ident; int idx = find_prev_name(cw, name); if(idx < 0) { idx = (int)cw->rnames.count; arr_append(&cw->rnames, name); } compile(cw, man->object); append_op(cw, LI_SDUPLICATE, node->lineno); append_op(cw, LI_LOAD_MEMBER, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); compile(cw, node->new_val); append_op(cw, instr_for_char(node->op), node->lineno); append_op(cw, LI_FLIP_TWO, node->lineno); append_op(cw, LI_SAVE_MEMBER, node->lineno); int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); } }
void compile_object_simple(compiler_wrapper *cw, ast_object_decl_node *node) { int ct = 0; ast_node *list = node->payload; arraylist names = arr_create(20); for(; list; list = list->next) { arr_append(&names, ((ast_value_node *)list)->value.s); list = list->next; compile(cw, list); ct++; } if(node->obj) compile(cw, node->obj); else append_op(cw, LI_PUSH_NEW_OBJECT, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, ct); append_op(cw, LI_MAKE_OBJECT, node->lineno); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); int i; for(i = ct - 1; i >= 0; i--) { char *sid = arr_get(&names, i); char *nsid = malloc(strlen(sid) + 1); strcpy(nsid, sid); int i = find_prev_name(cw, nsid); if(i < 0) { i = (int)cw->rnames.count; arr_append(&cw->rnames, nsid); } unsigned char buf[4]; int_to_byte_array(buf, i); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); } arr_free(&names); }
// Used to compile constants and variables void compile_value(compiler_wrapper *cw, ast_node *root) { ast_value_node *node = (ast_value_node *)root; if(node->value_type == VVAR) { compile_var(cw, node); return; } lky_object *obj = wrapper_to_obj(node_to_wrapper(node)); long idx = find_prev_const(cw, obj); if(idx < 0) { idx = cw->rcon.count; arr_append(&cw->rcon, obj); } append_op(cw, LI_LOAD_CONST, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
void compile_set_member(compiler_wrapper *cw, ast_node *root) { ast_binary_node *bin = (ast_binary_node *)root; ast_member_access_node *left = (ast_member_access_node *)bin->left; ast_node *right = bin->right; compile(cw, right); compile(cw, left->object); int idx = find_prev_name(cw, left->ident); if(idx < 0) { idx = (int)cw->rnames.count; arr_append(&cw->rnames, left->ident); } append_op(cw, LI_SAVE_MEMBER, root->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], root->lineno); append_op(cw, buf[1], root->lineno); append_op(cw, buf[2], root->lineno); append_op(cw, buf[3], root->lineno); }
char switch_to_close(compiler_wrapper *cw, char *sid, int idx) { lky_object *o = arr_get(&cw->rops, idx); lky_instruction istr = OBJ_NUM_UNWRAP(o); if(istr == LI_LOAD_CLOSE || istr == LI_SAVE_CLOSE) return 0; istr = istr == LI_LOAD_LOCAL ? LI_LOAD_CLOSE : LI_SAVE_CLOSE; cw->rops.items[idx] = lobjb_build_int(istr); char *nsid = malloc(strlen(sid) + 1); strcpy(nsid, sid); int i = find_prev_name(cw, nsid); if(i < 0) { i = (int)cw->rnames.count; arr_append(&cw->rnames, nsid); } unsigned char buf[4]; int_to_byte_array(buf, i); cw->rops.items[idx + 1] = lobjb_build_int(buf[0]); cw->rops.items[idx + 2] = lobjb_build_int(buf[1]); cw->rops.items[idx + 3] = lobjb_build_int(buf[2]); cw->rops.items[idx + 4] = lobjb_build_int(buf[3]); return 1; }
void compile_iter_loop(compiler_wrapper *cw, ast_node *root) { ast_loop_node *node = (ast_loop_node *)root; compile(cw, node->onloop); append_op(cw, LI_MAKE_ITER, node->lineno); int tagOut = next_if_tag(cw); int tagLoop = next_if_tag(cw); int start = (int)cw->rops.count; append_op(cw, LI_NEXT_ITER_OR_JUMP, node->lineno); append_op(cw, tagOut, node->lineno); append_op(cw, -1, node->lineno); append_op(cw, -1, node->lineno); append_op(cw, -1, node->lineno); append_var_info(cw, ((ast_value_node *)(node->init))->value.s, 0, node->lineno); append_op(cw, LI_POP, node->lineno); if(node->condition) { append_op(cw, LI_ITER_INDEX, node->lineno); append_var_info(cw, ((ast_value_node *)(node->condition))->value.s, 0, node->lineno); append_op(cw, LI_POP, node->lineno); } lky_object *wrapLoop = lobjb_build_int(tagLoop); lky_object *wrapOut = lobjb_build_int(tagOut); pool_add(&ast_memory_pool, wrapLoop); pool_add(&ast_memory_pool, wrapOut); arr_append(&cw->loop_start_stack, wrapLoop); arr_append(&cw->loop_end_stack, wrapOut); compile_compound(cw, node->payload->next); arr_remove(&cw->loop_start_stack, NULL, cw->loop_start_stack.count - 1); arr_remove(&cw->loop_end_stack, NULL, cw->loop_end_stack.count - 1); append_op(cw, tagLoop, node->lineno); append_op(cw, LI_JUMP, node->lineno); // Add the jump to the start location unsigned char buf[4]; int_to_byte_array(buf, start); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); append_op(cw, tagOut, node->lineno); append_op(cw, LI_POP, node->lineno); cw->save_val = 1; }
void compile_class_decl(compiler_wrapper *cw, ast_node *root) { ast_class_decl_node *node = (ast_class_decl_node *)root; arraylist list = arr_create(10); ast_node *member = node->members->next; for(; member; member = member->next) { ast_class_member_node *m = (ast_class_member_node *)member; //append_op(cw, m->prefix); compile(cw, m->payload); arr_append(&list, member); } int init_flag = 0; if(node->super) { compile(cw, node->super); init_flag |= 2; } if(node->init) { compile(cw, ((ast_class_member_node *)node->init)->payload); init_flag |= 1; } append_op(cw, LI_MAKE_CLASS, node->lineno); append_op(cw, list.count, node->lineno); append_op(cw, init_flag, node->lineno); int i; for(i = list.count - 1; i >= 0; i--) { ast_class_member_node *m = (ast_class_member_node *)arr_get(&list, i); append_op(cw, m->prefix, node->lineno); long idx = find_prev_name(cw, m->name); if(idx < 0) { idx = cw->rnames.count; char *nid = malloc(strlen(m->name) + 1); strcpy(nid, m->name); arr_append(&cw->rnames, nid); } unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); } }
// Compiles a function declaration void compile_function(compiler_wrapper *cw, ast_node *root) { ast_func_decl_node *node = (ast_func_decl_node *)root; // We want to build a new compiler wrapper for building // the function in a new context. compiler_wrapper nw; nw.local_idx = 0; nw.saved_locals = hm_create(100, 1); nw.rnames = arr_create(10); nw.rindices = arr_create(100); nw.used_names = copy_arraylist(cw->used_names); nw.repl = 0; nw.impl_name = node->impl_name; // Deal with parameters int argc = 0; ast_value_node *v = (ast_value_node *)node->params; for(; v; v = (ast_value_node *)v->next) { char *idf = v->value.s; char *nid = malloc(strlen(idf) + 1); strcpy(nid, idf); arr_append(&nw.rnames, nid); argc++; } nw.save_val = 0; lky_object_code *code = compile_ast_ext(node->payload->next, &nw); if(node->refname) { char *refname = node->refname; code->refname = malloc(strlen(refname) + 1); strcpy(code->refname, refname); } long idx = cw->rcon.count; arr_append(&cw->rcon, code); append_op(cw, LI_LOAD_CONST, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); append_op(cw, LI_MAKE_FUNCTION, node->lineno); append_op(cw, argc, node->lineno); }
// Compile special unit syntax void compile_unit_value(compiler_wrapper *cw, ast_node *root) { ast_unit_value_node *node = (ast_unit_value_node *)root; long idx = cw->rcon.count; arr_append(&cw->rcon, stlun_cinit(node->val, node->fmt)); append_op(cw, LI_LOAD_CONST, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
// Used to compile regexes void compile_regex(compiler_wrapper *cw, ast_node *root) { ast_regex_node *node = (ast_regex_node *)root; lky_object *rgx = stlrgx_cinit(node->pattern, node->flags); append_op(cw, LI_LOAD_CONST, node->lineno); int idx = cw->rcon.count; arr_append(&cw->rcon, rgx); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
// Compiles array literals void compile_array(compiler_wrapper *cw, ast_node *n) { ast_array_node *node = (ast_array_node *)n; int ct = 0; ast_node *list = node->list; for(; list; list = list->next) { compile(cw, list); ct++; } append_op(cw, LI_MAKE_ARRAY, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, ct); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
void compile_load(compiler_wrapper *cw, ast_node *n) { ast_load_node *node = (ast_load_node *)n; char *f = node->name; int idx = find_prev_name(cw, f); if(idx < 0) { idx = (int)cw->rnames.count; arr_append(&cw->rnames, f); } append_op(cw, LI_LOAD_MODULE, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
void compile_member_access(compiler_wrapper *cw, ast_node *n) { ast_member_access_node *node = (ast_member_access_node *)n; char *name = node->ident; int idx = find_prev_name(cw, name); if(idx < 0) { idx = (int)cw->rnames.count; arr_append(&cw->rnames, name); } compile(cw, node->object); append_op(cw, LI_LOAD_MEMBER, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
void compile_var(compiler_wrapper *cw, ast_value_node *node) { append_var_info(cw, node->value.s, 1, node->lineno); return; int idx = find_prev_name(cw, node->value.s); if(idx < 0) { idx = (int)cw->rnames.count; char *ns = malloc(strlen(node->value.s) + 1); strcpy(ns, node->value.s); arr_append(&cw->rnames, ns); } append_op(cw, LI_LOAD_CLOSE, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); }
void do_read(evutil_socket_t fd, short events, void *arg) { (void) events; struct fd_state *state = arg; ssize_t result; while (1) { assert(state->write_event); result = recv(fd, RingBuffer_ends_at(state->buffer), RingBuffer_available_space(state->buffer), 0); if (result <= 0) break; state->rtmp->total_read += result; RingBuffer_commit_write(state->buffer, result); while (RingBuffer_available_data(state->buffer) > 0) { RtmpOutputMessage *this_output = rtmp_create_output_message(); int result_multiplex = rtmp_multiplex(state->rtmp, state->buffer, this_output); check(result_multiplex >= 0, "rtmp_multiplex error %d", result_multiplex); if (state->rtmp->end == 1) { event_del(state->write_event); rtmp_destroy_output_message(this_output); free_fd_state(state); return; } if (this_output->length > 0) { printf("Add block with length=%u\n", this_output->length); List_push(state->outputs, this_output); assert(state->write_event); event_add(state->write_event, NULL); } else { rtmp_destroy_output_message(this_output); } if (result_multiplex == 0) break; } printf("total_read=%u, last_total_read=%u\n", state->rtmp->total_read, state->rtmp->last_total_read); if (rtmp_should_acknowledge(state->rtmp) == 1) { RtmpOutputMessage *ack = rtmp_create_output_message(); rtmp_allocate_output_message_content(ack, 16); int i = 0; unsigned char *msg = ack->message; msg[i++] = 0x02; msg[i++] = 0x00;msg[i++] = 0x00;msg[i++] = 0x00; int_to_byte_array(4, msg, i, 3);i += 3; msg[i++] = 0x03; msg[i++] = 0x00; msg[i++] = 0x00; msg[i++] = 0x00; msg[i++] = 0x00; // msg[i++] = 0x03; // msg[i++] = 0x00;msg[i++] = 0x00;msg[i++] = 0x04; // msg[i++] = 0x00;msg[i++] = 0x00;msg[i++] = 0x00;msg[i++] = 0x00; // msg[i++] = 0x00;msg[i++] = 0x00;msg[i++] = 0x00; int_to_byte_array(state->rtmp->total_read, msg, i, 4);i += 4; List_push(state->outputs, ack); assert(state->write_event); event_add(state->write_event, NULL); state->rtmp->last_total_read = state->rtmp->total_read; } } if (result == 0) { free_fd_state(state); } else if (result < 0) { if (errno == EAGAIN) // XXXX use evutil macro return; perror("recv"); free_fd_state(state); } error: free_fd_state(state); return; }
void compile_object(compiler_wrapper *cw, ast_node *n) { ast_object_decl_node *node = (ast_object_decl_node *)n; if(!node->refname) return compile_object_simple(cw, node); arraylist name_list = cw->used_names; int i; for(i = 0; i < name_list.count; i++) { name_wrapper *w = arr_get(&cw->used_names, i); if(strcmp(w->name, node->refname)) continue; switch_to_close(cw, node->refname, w->idx); } int ct = 0; ast_node *list = node->payload; arraylist names = arr_create(20); for(; list; list = list->next) { arr_append(&names, ((ast_value_node *)list)->value.s); list = list->next; compile(cw, list); ct++; } char *nsid = malloc(strlen(node->refname) + 1); strcpy(nsid, node->refname); i = find_prev_name(cw, nsid); if(i < 0) { i = (int)cw->rnames.count; arr_append(&cw->rnames, nsid); } append_op(cw, LI_LOAD_CLOSE, node->lineno); unsigned char buf[4]; int_to_byte_array(buf, i); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); int_to_byte_array(buf, ct); append_op(cw, LI_MAKE_OBJECT, node->lineno); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); for(i = ct - 1; i >= 0; i--) { char *sid = arr_get(&names, i); char *nsid = malloc(strlen(sid) + 1); strcpy(nsid, sid); int i = find_prev_name(cw, nsid); if(i < 0) { i = (int)cw->rnames.count; arr_append(&cw->rnames, nsid); } unsigned char buf[4]; int_to_byte_array(buf, i); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); } arr_free(&names); }
void compile_loop(compiler_wrapper *cw, ast_node *root) { ast_loop_node *node = (ast_loop_node *)root; // if(node->init && node->condition && !node->onloop) // return compile_iter_loop(cw, root); int tagOut = next_if_tag(cw); // Prepare the exit tag int tagLoop = next_if_tag(cw); // Prepare the continue tag if(node->init) // If we have a for loop, compile the init { char save = cw->save_val; cw->save_val = 0; compile(cw, node->init); if(!cw->save_val) append_op(cw, LI_POP, node->lineno); cw->save_val = save; } int start = (int)cw->rops.count; // The start location (for loop jumps) compile(cw, node->condition); // Append the tag for the unknown end location append_op(cw, LI_JUMP_FALSE, node->lineno); append_op(cw, tagOut, node->lineno); append_op(cw, -1, node->lineno); // Note that we use for bytes to represent jump locations. append_op(cw, -1, node->lineno); // This allows us to index locations beyond 255 in the append_op(cw, -1, node->lineno); // interpreter. lky_object *wrapLoop = lobjb_build_int(tagLoop); lky_object *wrapOut = lobjb_build_int(tagOut); pool_add(&ast_memory_pool, wrapLoop); pool_add(&ast_memory_pool, wrapOut); arr_append(&cw->loop_start_stack, wrapLoop); arr_append(&cw->loop_end_stack, wrapOut); compile_compound(cw, node->payload->next); arr_remove(&cw->loop_start_stack, NULL, cw->loop_start_stack.count - 1); arr_remove(&cw->loop_end_stack, NULL, cw->loop_end_stack.count - 1); append_op(cw, tagLoop, node->lineno); if(node->onloop) // If a for loop, compile the onloop. { char save = cw->save_val; cw->save_val = 0; compile(cw, node->onloop); if(!cw->save_val) append_op(cw, LI_POP, node->lineno); cw->save_val = save; } append_op(cw, LI_JUMP, node->lineno); // Add the jump to the start location unsigned char buf[4]; int_to_byte_array(buf, start); append_op(cw, buf[0], node->lineno); append_op(cw, buf[1], node->lineno); append_op(cw, buf[2], node->lineno); append_op(cw, buf[3], node->lineno); append_op(cw, tagOut, node->lineno); cw->save_val = 1; }
void append_var_info(compiler_wrapper *cw, char *ch, char load, int lineno) { char needs_close = cw->repl; char already_defined = 0; arraylist list = cw->used_names; int i; for(i = 0; i < list.count; i++) { name_wrapper *w = arr_get(&cw->used_names, i); if(strcmp(w->name, ch)) continue; if(w->owner != cw) { switch_to_close(w->owner, ch, w->idx); needs_close = 1; } else { needs_close = is_close(cw, w->idx); already_defined = 1; } } if(!needs_close && !already_defined && load) needs_close = 1; if(needs_close) { lky_instruction istr = load ? LI_LOAD_CLOSE : LI_SAVE_CLOSE; char *nsid = malloc(strlen(ch) + 1); strcpy(nsid, ch); int i = find_prev_name(cw, nsid); if(i < 0) { i = (int)cw->rnames.count; arr_append(&cw->rnames, nsid); } append_op(cw, istr, lineno); unsigned char buf[4]; int_to_byte_array(buf, i); append_op(cw, buf[0], lineno); append_op(cw, buf[1], lineno); append_op(cw, buf[2], lineno); append_op(cw, buf[3], lineno); return; } lky_instruction istr = load ? LI_LOAD_LOCAL : LI_SAVE_LOCAL; hm_error_t err; int idx = 0; lky_object_builtin *o = hm_get(&cw->saved_locals, ch, &err); if(err == HM_KEY_NOT_FOUND) { idx = get_next_local(cw); lky_object *obj = lobjb_build_int(idx); pool_add(&ast_memory_pool, obj); hm_put(&cw->saved_locals, ch, obj); } else idx = OBJ_NUM_UNWRAP(o); append_op(cw, istr, lineno); unsigned char buf[4]; int_to_byte_array(buf, idx); append_op(cw, buf[0], lineno); append_op(cw, buf[1], lineno); append_op(cw, buf[2], lineno); append_op(cw, buf[3], lineno); name_wrapper *wrap = malloc(sizeof(name_wrapper)); pool_add(&ast_memory_pool, wrap); wrap->idx = cw->rops.count - 5; wrap->name = ch; wrap->owner = cw; arr_append(&cw->used_names, wrap); }