diff options
Diffstat (limited to 'src/lib/module.c')
| -rw-r--r-- | src/lib/module.c | 195 |
1 files changed, 171 insertions, 24 deletions
diff --git a/src/lib/module.c b/src/lib/module.c index 51bbfdd..4243b77 100644 --- a/src/lib/module.c +++ b/src/lib/module.c @@ -18,16 +18,103 @@ */ #include "aplwc_internal.h" +static struct module_member * +add_member(struct aplwc *aplwc, struct aplwc_module *module, symbol_t name, struct module_member *real_member, int export) +{ + struct module_member *m; + MEMPTRS(aplwc, 2); + MEMPTR(0, module); + MEMPTR(1, real_member); + + for(m = module->members; m; m = m->link){ + if(m->name == name){ + if(real_member) + assert(m->real_member == NULL || m->real_member == real_member); + m->real_member = real_member; + m->exported |= export; + goto end; + } + } + + if((m = memory_alloc_module_member(aplwc)) == NULL) + goto end; + + m->exported = export; + m->name = name; + m->real_member = real_member; + m->link = module->members; + module->members = m; +end: + MEMPTRS_EXIT(aplwc); + return m; +} static int -read_keyword_decl(struct aplwc_module *module, size_t offset) +read_keyword_decl(struct aplwc *aplwc, struct aplwc_module *module, size_t offset) { int len; + size_t max; + struct module_member *m; - for(len = 1; (offset + len) < module->tokens->length; len++) - if(module->tokens->tokens[offset+len].tag == TOKEN_TAG_NEWLINE) - break; + MEMPTRS(aplwc, 2); + MEMPTR(0, module); + + m = NULL; + MEMPTR(1, m); + +#define t(n) module->tokens->tokens[offset+(n)] + + max = module->tokens->length - offset; + + assert(t(0).tag == TOKEN_TAG_KEYWORD); + switch(t(0).data.keyword){ + case KW_MODULE: + if((max < 1) || (t(1).tag != TOKEN_TAG_IDENTIFIER)) + goto fail; + len = 1; + break; + case KW_SYMBOL: + if((max < 1) || (t(1).tag != TOKEN_TAG_IDENTIFIER)) + goto fail; + if((max < 2) || (t(2).tag != TOKEN_TAG_UNKNOWN_SYM)) + goto fail; + len = 2; + + if((m = add_member(aplwc, module, t(1).data.symbol, NULL, 0)) == NULL) + goto fail; + if(add_member(aplwc, module, t(2).data.symbol, m, 0) == NULL) + goto fail; + break; + case KW_EXPORT: + for(len = 1; (size_t)len < max; len++){ + switch(t(len).tag){ + case TOKEN_TAG_UNKNOWN_SYM: + case TOKEN_TAG_IDENTIFIER: + if(add_member(aplwc, module, t(len).data.symbol, NULL, 1) == NULL) + goto fail; + break; + case TOKEN_TAG_NEWLINE: + goto end; + default: +fail: + len = -1; + goto end; + } + } + break; + default: + assert(0); + return -1; + } + + if((len >= 0) && (max > (size_t)len)) + if(t(len+1).tag != TOKEN_TAG_NEWLINE) + goto fail; + len++; /* For the keyword itself */ +end: + MEMPTRS_EXIT(aplwc); return len; +#undef t } static int @@ -46,14 +133,14 @@ read_function_decl(struct aplwc_module *module, size_t offset) } static int -read_decl(struct aplwc_module *module, size_t offset) +read_decl(struct aplwc *aplwc, struct aplwc_module *module, size_t offset) { switch(module->tokens->tokens[offset].tag){ case TOKEN_TAG_COMMENT: case TOKEN_TAG_NEWLINE: return 0; case TOKEN_TAG_KEYWORD: - return read_keyword_decl(module, offset); + return read_keyword_decl(aplwc, module, offset); case TOKEN_TAG_DEL: return read_function_decl(module, offset); default: @@ -62,49 +149,109 @@ read_decl(struct aplwc_module *module, size_t offset) } static enum aplwc_rc -read_decls(struct aplwc_module *module) +read_decls(struct aplwc *aplwc, struct aplwc_module *module) { size_t offset; int skip; + enum aplwc_rc rc; + MEMPTRS(aplwc, 1); + MEMPTR(0, module); + + rc = APLWC_OK; for(offset = 0; offset < module->tokens->length; offset++){ - skip = read_decl(module, offset); - if(skip == -1) - return APLWC_INVALID_SYNTAX; + skip = read_decl(aplwc, module, offset); + if(skip == -1){ + rc = APLWC_INVALID_SYNTAX; + goto end; + } offset += skip; } - return APLWC_OK; + +end: + MEMPTRS_EXIT(aplwc); + return rc; +} + +static struct aplwc_module * +module_lookup(struct aplwc *aplwc, struct string *name) +{ + struct aplwc_module *m; + + for(m = aplwc->modules; m; m = m->link){ + if(string_compare(m->name, name) == 0) + break; + } + + return m; +} + +static enum aplwc_rc +resolve_imports(struct aplwc *aplwc, struct aplwc_module *module) +{ + struct aplwc_module *imported; + struct string *name; + struct module_member *m; + enum aplwc_rc rc; + + MEMPTRS(aplwc, 1); + MEMPTR(0, module); + + rc = APLWC_OK; + if((name = chars_to_string(aplwc, "Boot", -1)) == NULL){ + rc = aplwc->last_error; + goto end; + } + + if((imported = module_lookup(aplwc, name)) == NULL) + goto end; /* only because it is Boot for now... */ + + for(m = imported->members; m; m = m->link){ + if(m->exported == 0) + continue; + if(add_member(aplwc, module, m->name, m, 0) == NULL){ + rc = aplwc->last_error; + goto end; + } + } +end: + MEMPTRS_EXIT(aplwc); + return rc; } enum aplwc_rc load_module(struct aplwc *aplwc, struct string *name, struct token_list *tokens) { - enum aplwc_rc rc; struct aplwc_module *module; - MEMPTRS(aplwc, 2); + MEMPTRS(aplwc, 3); MEMPTR(0, name); MEMPTR(1, tokens); - module = memory_alloc_aplwc_module(aplwc); - if(module == NULL){ - rc = aplwc_last_error(aplwc); + if((module = memory_alloc_aplwc_module(aplwc)) == NULL) goto end; - } + MEMPTR(2, module); module->name = name; module->tokens = tokens; + module->imports = NULL; + module->members = NULL; module->link = NULL; - rc = read_decls(module); - if(rc == APLWC_OK){ - module->link = aplwc->modules; - aplwc->modules = module; - }else - aplwc->last_error = rc; + if((aplwc->last_error = read_decls(aplwc, module)) != APLWC_OK) + goto end; + + if((aplwc->last_error = resolve_imports(aplwc, module)) != APLWC_OK) + goto end; + + if((aplwc->last_error = check_tokens(module, tokens)) != APLWC_OK) + goto end; + + module->link = aplwc->modules; + aplwc->modules = module; end: MEMPTRS_EXIT(aplwc); - return rc; + return aplwc->last_error; } |