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); }
int main(int argc, char **argv) { ast_node *tree = NULL; VM vm; CTX ctx; char *bytecode; size_t len; IP ip; VALUE closure, result; int parse_ok; char *bootstrap_file_name; char *source_file_name; METHOD_RESULT mr; // Silence GCC -Wunused-function if(0) { yymatchDot(NULL); yyAccept(NULL, 0); } NGS_GC_INIT(); // (causes warning) // NGS_GC_THR_INIT(); yycontext yyctx; memset(&yyctx, 0, sizeof(yycontext)); yyctx.fail_pos = -1; yyctx.fail_rule = "(unknown)"; yyctx.lines = 0; yyctx.lines_postions[0] = 0; bootstrap_file_name = find_bootstrap_file(); if(!bootstrap_file_name) { fprintf(stderr, "Cold not find bootstrap file\n"); exit(100); } if(!strcmp(bootstrap_file_name, "-")) { source_file_name = ngs_strdup("<stdin>"); yyctx.input_file = stdin; } else { source_file_name = bootstrap_file_name; yyctx.input_file = fopen(bootstrap_file_name, "r"); } if(!yyctx.input_file) { fprintf(stderr, "Error while opening bootstrap file '%s': %d - %s\n", bootstrap_file_name, errno, strerror(errno)); exit(101); } parse_ok = yyparse(&yyctx); // printf("parse_ok %d\n", parse_ok); if(!parse_ok) { fprintf(stderr, "NGS: Failed to parse at position %d (%s), rule %s. Exiting.\n", yyctx.fail_pos, sprintf_position(&yyctx, yyctx.fail_pos), yyctx.fail_rule); exit(2); } tree = yyctx.__; IF_DEBUG(COMPILER, print_ast(tree, 0);)
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); } }