int test(){ int ret = 0; write_cstr(1, ">>> test >>>\n"); struct arr *a = arr_alloc(4); arr_insert(a, 0, "this", 4); ret |= test_print_eq(a, "this", "arr 0"); arr_insert(a, a->c, " is", 3); test_print_eq(a, "this is", "arr 0.1"); arr_insert(a, 0, "hi ", 3); test_print_eq(a, "hi this is", "arr 0.2"); arr_insert(a, 0, "this is a big string being added. ", strlen("this is a big string being added. ")); test_print_eq(a, "this is a big string being added. hi this is", "arr 1"); struct arr *b = arr_alloc(4); arr_insert(b, 0, "starting:", strlen("starting:")); test_print_eq(b, "starting:", "arr 2"); arr_append_int_str(b, 3); test_print_eq(b, "starting:3", "arr 3"); arr_append_int_str(b, 40012); ret |= test_print_eq(b, "starting:340012", "arr 4"); struct arr *c = arr_alloc(4); arr_append(c, "h"); arr_append(c, "i"); test_print_eq(c, "hi", "arr 5"); write(1, "\n", 1); return ret; }
// Helper function to add an instruction/tag to // the running operations list. This should be // the only function that appends to that list. void append_op(compiler_wrapper *cw, long ins, long lineno) { lky_object *obj = lobjb_build_int(ins); lky_object *idx = lobjb_build_int(lineno); pool_add(&ast_memory_pool, obj); arr_append(&cw->rops, obj); arr_append(&cw->rindices, idx); }
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); }
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); }
lky_object *stlcon_ord(lky_func_bundle *bundle) { lky_object_seq *args = BUW_ARGS(bundle); lky_object *from = (lky_object *)args->value; char *str = lobjb_stringify(from, BUW_INTERP(bundle)); lky_object *ret = NULL; size_t len = strlen(str); if(len == 1) ret = lobjb_build_int(str[0]); else { arraylist list = arr_create(len + 1); char *tmp = str; while(*tmp) arr_append(&list, lobjb_build_int(*tmp++)); ret = stlarr_cinit(list); } free(str); return ret; }
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_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); } }
// 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); }
EagleComplexType *ett_interface_type(char *name) { EagleComplexType *et = hst_get(&type_named_table, name, NULL, NULL); if(et) return et; EagleInterfaceType *ett = malloc(sizeof(EagleInterfaceType)); ett->names = arr_create(3); arr_append(&ett->names, name); ett->type = ETInterface; pool_add(&list_mempool, &ett->names); pool_add(&type_mempool, ett); return (EagleComplexType *)ett; }
// 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); }
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 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); }
void ty_add_interface_method(char *name, char *method, EagleComplexType *ty) { Arraylist *names = hst_get(&interface_table, name, NULL, NULL); arr_append(names, method); ty_add_method(name, method, ty); }
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 ett_composite_interface(EagleComplexType *ett, char *name) { EagleInterfaceType *ei = (EagleInterfaceType *)ett; arr_append(&ei->names, name); }
void ett_struct_add(EagleComplexType *ett, EagleComplexType *ty, char *name) { EagleStructType *e = (EagleStructType *)ett; arr_append(&e->types, ty); arr_append(&e->names, name); }
void vs_add_deferment(VarScopeStack *vs, AST *ast) { VarScope *s = vs->scope; arr_append(&s->deferments, ast); }