char *find_bootstrap_file() { static char *places[] = {"/etc/ngs/bootstrap.ngs", "/var/lib/ngs/bootstrap.ngs", "/usr/share/ngs/bootstrap.ngs", NULL}; char *fname; char *home_dir; int len; char fmt[] = "%s/.bootstrap.ngs"; fname = getenv("NGS_BOOTSTRAP"); if(fname) { return fname; } home_dir = getenv("HOME"); if(home_dir) { len = snprintf(NULL, 0, fmt, home_dir) + 1; fname = NGS_MALLOC(len); snprintf(fname, len, fmt, home_dir); // printf("HOME fname: %s\n", fname); if(access(fname, F_OK) != -1) { return fname; } } for(len=0; places[len]; len++) { if(access(places[len], F_OK) != -1) { return places[len]; } } return NULL; }
VALUE make_normal_type_constructor(VALUE normal_type) { VALUE ret; OBJECT *normal_type_constructor; normal_type_constructor = NGS_MALLOC(sizeof(*normal_type_constructor)); assert(normal_type_constructor); SET_OBJ(ret, normal_type_constructor); OBJ_TYPE_NUM(ret) = T_UTCTR; NORMAL_TYPE_CONSTRUCTOR_TYPE(ret) = normal_type; return ret; }
void register_local_var(COMPILATION_CONTEXT *ctx, char *name) { SYMBOL_TABLE *s; HASH_FIND(hh, LOCALS, name, strlen(name), s); if(s) { return; } assert(N_LOCALS < MAX_LOCALS); s = NGS_MALLOC(sizeof(*s)); s->name = ngs_strdup(name); s->index = N_LOCALS++; HASH_ADD_KEYPTR(hh, LOCALS, s->name, strlen(s->name), s); register_local_identifier(ctx, s->name); }
VALUE make_normal_type_instance(VALUE normal_type) { VALUE ret; USER_TYPE_INSTANCE_OBJECT *normal_type_instance; normal_type_instance = NGS_MALLOC(sizeof(*normal_type_instance)); assert(normal_type_instance); SET_OBJ(ret, normal_type_instance); OBJ_TYPE(ret) = normal_type; OBJ_DATA(ret) = make_array(0); return ret; }
VALUE make_hash(size_t start_buckets) { VALUE ret; HASH_OBJECT *hash; hash = NGS_MALLOC(sizeof(*hash)); assert(hash); SET_OBJ(ret, hash); OBJ_TYPE_NUM(ret) = T_HASH; if(start_buckets) { OBJ_DATA_PTR(ret) = NGS_MALLOC(start_buckets * sizeof(HASH_OBJECT_ENTRY *)); memset(OBJ_DATA_PTR(ret), 0, start_buckets * sizeof(HASH_OBJECT_ENTRY *)); // XXX check if needed } else { OBJ_DATA_PTR(ret) = NULL; } HASH_BUCKETS_N(ret) = start_buckets; HASH_HEAD(ret) = NULL; HASH_TAIL(ret) = NULL; OBJ_LEN(ret) = 0; return ret; }
// TODO: consider allocating power-of-two length VALUE make_var_len_obj(uintptr_t type, const size_t item_size, const size_t len) { VALUE v; VAR_LEN_OBJECT *vlo; vlo = NGS_MALLOC(sizeof(*vlo)); assert(vlo); vlo->base.type.num = type; vlo->len = len; vlo->allocated = len; vlo->item_size = item_size; if(len) { vlo->base.val.ptr = NGS_MALLOC(item_size*len); assert(vlo->base.val.ptr); } else { vlo->base.val.ptr = NULL; } SET_OBJ(v, vlo); return v; }
VALUE make_normal_type(VALUE name) { VALUE ret; NGS_TYPE *t; t = NGS_MALLOC(sizeof(*t)); assert(t); SET_OBJ(ret, t); OBJ_TYPE_NUM(ret) = T_TYPE; NGS_TYPE_NAME(ret) = name; NGS_TYPE_FIELDS(ret) = make_hash(8); // Hash: name->index NGS_TYPE_CONSTRUCTORS(ret) = make_array(1); NGS_TYPE_PARENTS(ret) = make_array(0); VALUE ctr = make_normal_type_constructor(ret); ARRAY_ITEMS(NGS_TYPE_CONSTRUCTORS(ret))[0] = ctr; return ret; }
SYMBOL_TABLE *get_symbol_table_entry(SYMBOL_TABLE **st, char *name, int create_if_not_exists, int *created) { SYMBOL_TABLE *s; *created = 0; HASH_FIND(hh, *st, name, strlen(name), s); // printf("SYMBOL TABLE QUERY %s (len %zu) %p\n", name, strlen(name), *st); if(s) { // printf("SYMBOL TABLE LOOKUP OK %s -> %p\n", name, s); return s; } if(!create_if_not_exists) { return NULL; } s = NGS_MALLOC(sizeof(*s)); s->name = ngs_strdup(name); s->is_predefinded_global = 0; // HASH_ADD_STR(*st, name /* field */, s); HASH_ADD_KEYPTR(hh, *st, s->name, strlen(s->name), s); *created = 1; // printf("SYMBOL TABLE ADD OK %s -> %p\n", name, *st); return s; }
// TODO: maybe do it at parse time? That might be more complex but probably faster // TODO: refactor for code deduplication void register_local_vars(COMPILATION_CONTEXT *ctx, ast_node *node) { SYMBOL_TABLE *s; ast_node *ptr, *ptr2; switch(node->type) { case FUNC_NODE: if(node->first_child->next_sibling->next_sibling->next_sibling) { // Function has a name HASH_FIND(hh, IDENTIFIERS_SCOPES, node->first_child->next_sibling->next_sibling->next_sibling->name, strlen(node->first_child->next_sibling->next_sibling->next_sibling->name), s); if(!s) { register_local_var(ctx, node->first_child->next_sibling->next_sibling->next_sibling->name); } } return; case LOCAL_NODE: for(ptr=node->first_child; ptr; ptr=ptr->next_sibling) { switch(ptr->type) { case IDENTIFIER_NODE: register_local_var(ctx, ptr->name); break; case ASSIGNMENT_NODE: assert(ptr->first_child->type == IDENTIFIER_NODE); register_local_var(ctx, ptr->first_child->name); for(ptr2=ptr->first_child->next_sibling; ptr2; ptr2=ptr2->next_sibling) { register_local_vars(ctx, ptr2); } break; default: assert(0 == "Unexpected node type under LOCAL_NODE"); } } break; case UPVAR_NODE: for(ptr=node->first_child; ptr; ptr=ptr->next_sibling) { switch(ptr->type) { case IDENTIFIER_NODE: { // TEMP IDENTIFIER_INFO identifier_info; identifier_info = resolve_identifier(ctx, ptr->name); assert(identifier_info.type == UPVAR_IDENTIFIER); } register_upvar_identifier(ctx, ptr->name); break; case ASSIGNMENT_NODE: assert(ptr->first_child->type == IDENTIFIER_NODE); { // TEMP IDENTIFIER_INFO identifier_info; identifier_info = resolve_identifier(ctx, ptr->first_child->name); assert(identifier_info.type == UPVAR_IDENTIFIER); } register_upvar_identifier(ctx, ptr->first_child->name); for(ptr2=ptr->first_child->next_sibling; ptr2; ptr2=ptr2->next_sibling) { register_local_vars(ctx, ptr2); } break; default: assert(0 == "Unexpected node type under UPVAR_NODE"); } } break; case GLOBAL_NODE: for(ptr=node->first_child; ptr; ptr=ptr->next_sibling) { switch(ptr->type) { case IDENTIFIER_NODE: { // TEMP IDENTIFIER_INFO identifier_info; identifier_info = resolve_identifier(ctx, ptr->name); assert(identifier_info.type == GLOBAL_IDENTIFIER || identifier_info.type == NO_IDENTIFIER); } register_global_identifier(ctx, ptr->name); break; case ASSIGNMENT_NODE: assert(ptr->first_child->type == IDENTIFIER_NODE); { // TEMP IDENTIFIER_INFO identifier_info; identifier_info = resolve_identifier(ctx, ptr->first_child->name); assert(identifier_info.type == GLOBAL_IDENTIFIER || identifier_info.type == NO_IDENTIFIER); } register_global_identifier(ctx, ptr->first_child->name); for(ptr2=ptr->first_child->next_sibling; ptr2; ptr2=ptr2->next_sibling) { register_local_vars(ctx, ptr2); } break; default: assert(0 == "Unexpected node type under GLOBAL_NODE"); } } break; case ASSIGNMENT_NODE: if(node->first_child->type == IDENTIFIER_NODE) { HASH_FIND(hh, IDENTIFIERS_SCOPES, node->first_child->name, strlen(node->first_child->name), s); if(!s) { IDENTIFIER_INFO identifier_info; identifier_info = resolve_identifier(ctx, node->first_child->name); if(identifier_info.type == UPVAR_IDENTIFIER) { s = NGS_MALLOC(sizeof(*s)); s->name = ngs_strdup(node->first_child->name); s->is_predefinded_global = 0; s->index = UPVAR_IDENTIFIER; HASH_ADD_KEYPTR(hh, IDENTIFIERS_SCOPES, s->name, strlen(s->name), s); } } if(!s) { register_local_var(ctx, node->first_child->name); } } for(ptr=node->first_child->next_sibling; ptr; ptr=ptr->next_sibling) { register_local_vars(ctx, ptr); } break; } for(ptr=node->first_child; ptr; ptr=ptr->next_sibling) { register_local_vars(ctx, ptr); } }