diff options
| -rw-r--r-- | compile.c | 29 | ||||
| -rw-r--r-- | typecheck.c | 88 |
2 files changed, 76 insertions, 41 deletions
@@ -300,17 +300,7 @@ CORD compile_statement(env_t *env, ast_t *ast) case Declare: { auto decl = Match(ast, Declare); if (decl->value->tag == Use) { - auto use = Match(decl->value, Use); - const char *path = use->raw_path; - const char *name = file_base_name(path); - if (strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { - env->code->imports = CORD_all(env->code->imports, "#include \"", path, ".h\"\n"); - env->code->object_files = CORD_all(env->code->object_files, "'", path, ".o' "); - } else { - env->code->imports = CORD_all(env->code->imports, "#include <", path, ".h>\n"); - env->code->object_files = CORD_all(env->code->object_files, "-l", name, " "); - } - return CORD_EMPTY; + return compile_statement(env, decl->value); } else { type_t *t = get_type(env, decl->value); if (t->tag == AbortType || t->tag == VoidType) @@ -790,6 +780,19 @@ CORD compile_statement(env_t *env, ast_t *ast) return CORD_EMPTY; } case InlineCCode: return Match(ast, InlineCCode)->code; + case Use: { + auto use = Match(ast, Use); + const char *path = use->raw_path; + const char *name = file_base_name(path); + if (strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { + env->code->imports = CORD_all(env->code->imports, "#include \"", path, ".h\"\n"); + env->code->object_files = CORD_all(env->code->object_files, "'", path, ".o' "); + } else { + env->code->imports = CORD_all(env->code->imports, "#include <", path, ".h>\n"); + env->code->object_files = CORD_all(env->code->object_files, "-l", name, " "); + } + return CORD_EMPTY; + } default: return CORD_asprintf("(void)%r;", compile(env, ast)); } @@ -1854,7 +1857,7 @@ CORD compile(env_t *env, ast_t *ast) } } case InlineCCode: return Match(ast, InlineCCode)->code; - case Use: code_err(ast, "Uses are not supported yet"); + case Use: return CORD_EMPTY; case LinkerDirective: code_err(ast, "Linker directives are not supported yet"); case Extern: code_err(ast, "Externs are not supported yet"); case TableEntry: code_err(ast, "Table entries should not be compiled directly"); @@ -1864,7 +1867,7 @@ CORD compile(env_t *env, ast_t *ast) case Unknown: code_err(ast, "Unknown AST"); } code_err(ast, "Unknown AST: %W", ast); - return NULL; + return CORD_EMPTY; } void compile_namespace(env_t *env, const char *ns_name, ast_t *block) diff --git a/typecheck.c b/typecheck.c index 4fcbcf20..cba6b41c 100644 --- a/typecheck.c +++ b/typecheck.c @@ -102,6 +102,37 @@ type_t *get_math_type(env_t *env, ast_t *ast, type_t *lhs_t, type_t *rhs_t) code_err(ast, "Math operations between %T and %T are not supported", lhs_t, rhs_t); } +static env_t *load_module(env_t *env, ast_t *use_ast) +{ + auto use = Match(use_ast, Use); + const char *name = file_base_name(use->raw_path); + env_t *module_env = Table$str_get(*env->imports, name); + if (module_env) + return module_env; + + module_env = new_compilation_unit(); + module_env->file_prefix = heap_strf("%s$", name); + Table$str_set(module_env->imports, name, module_env); + const char *my_name = heap_strn(CORD_to_const_char_star(env->file_prefix), CORD_len(env->file_prefix)-1); + Table$str_set(module_env->imports, my_name, env); + + const char *resolved_path = resolve_path(use->raw_path, use_ast->file->filename, getenv("USE_PATH")); + if (!resolved_path) + code_err(use_ast, "No such file exists: \"%s\"", use->raw_path); + + file_t *f = load_file(resolved_path); + if (!f) errx(1, "No such file: %s", resolved_path); + + ast_t *ast = parse_file(f, NULL); + if (!ast) errx(1, "Could not compile!"); + + for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) { + bind_statement(module_env, stmt->ast); + } + Table$str_set(env->imports, name, module_env); + return module_env; +} + void bind_statement(env_t *env, ast_t *statement) { switch (statement->tag) { @@ -114,7 +145,10 @@ void bind_statement(env_t *env, ast_t *statement) const char *name = Match(decl->var, Var)->name; if (get_binding(env, name)) code_err(decl->var, "A %T called '%s' has already been defined", get_binding(env, name)->type, name); - bind_statement(env, decl->value); + if (decl->value->tag == Use) + (void)load_module(env, decl->value); + else + bind_statement(env, decl->value); type_t *type = get_type(env, decl->value); CORD code = CORD_cat(env->scope_prefix ? env->scope_prefix : "$", name); set_binding(env, name, new(binding_t, .type=type, .code=code)); @@ -153,7 +187,7 @@ void bind_statement(env_t *env, ast_t *statement) type->__data.StructType.opaque = false; type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); - Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name))); + Table$str_set(env->locals, def->name, new(binding_t, .type=typeinfo_type, .code=CORD_all(env->file_prefix, def->name))); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) { bind_statement(ns_env, stmt->ast); @@ -199,7 +233,7 @@ void bind_statement(env_t *env, ast_t *statement) } type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); - Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type)); + Table$str_set(env->locals, def->name, new(binding_t, .type=typeinfo_type)); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) { bind_statement(ns_env, stmt->ast); @@ -223,38 +257,36 @@ void bind_statement(env_t *env, ast_t *statement) .code="(Text_t)")); type_t *typeinfo_type = Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env); - Table$str_set(env->globals, def->name, new(binding_t, .type=typeinfo_type)); + Table$str_set(env->locals, def->name, new(binding_t, .type=typeinfo_type)); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) bind_statement(ns_env, stmt->ast); break; } case Use: { - auto use = Match(statement, Use); - const char *name = file_base_name(use->raw_path); - if (Table$str_get(*env->imports, name)) - break; - - env_t *module_env = new_compilation_unit(); - module_env->file_prefix = heap_strf("%s$", name); - Table$str_set(module_env->imports, name, module_env); - const char *my_name = heap_strn(CORD_to_const_char_star(env->file_prefix), CORD_len(env->file_prefix)-1); - Table$str_set(module_env->imports, my_name, env); - - const char *resolved_path = resolve_path(use->raw_path, statement->file->filename, getenv("USE_PATH")); - if (!resolved_path) - code_err(statement, "No such file exists: \"%s\"", use->raw_path); - - file_t *f = load_file(resolved_path); - if (!f) errx(1, "No such file: %s", resolved_path); - - ast_t *ast = parse_file(f, NULL); - if (!ast) errx(1, "Could not compile!"); - - for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) { - bind_statement(module_env, stmt->ast); + env_t *module_env = load_module(env, statement); + for (table_t *bindings = module_env->locals; bindings != module_env->globals; bindings = bindings->fallback) { + for (int64_t i = 1; i <= Table$length(*bindings); i++) { + struct {const char *name; binding_t *binding; } *entry = Table$entry(*bindings, i); + if (entry->name[0] == '_') + continue; + if (Table$str_get(*env->locals, entry->name)) + code_err(statement, "This module imports a symbol called '%s', which would clobber another variable", entry->name); + printf("Imported binding: %s\n", entry->name); + Table$str_set(env->locals, entry->name, entry->binding); + } + } + for (int64_t i = 1; i <= Table$length(*module_env->types); i++) { + struct {const char *name; type_t *type; } *entry = Table$entry(*module_env->types, i); + if (entry->name[0] == '_') + continue; + if (Table$str_get(*env->types, entry->name)) + continue; + +//code_err(statement, "This module imports a type called '%s', which would clobber another type", entry->name); + printf("Imported type: %s\n", entry->name); + Table$str_set(env->types, entry->name, entry->type); } - Table$str_set(env->imports, name, module_env); break; } case Extern: { |
