From a6fe656f21863d578c1c408f158ed5bc567a8f23 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 29 Jul 2018 20:56:09 +0100 Subject: [PATCH] foreign import x {"foo.lib", "bar.lib"} --- core/mem/mem.odin | 4 +++ src/checker.cpp | 40 +++++++++++++++-------------- src/entity.cpp | 6 ++--- src/ir.cpp | 30 ++++++++++++---------- src/main.cpp | 3 +-- src/parser.cpp | 65 ++++++++++++++++++++++++++++++++++++----------- src/parser.hpp | 4 +-- 7 files changed, 97 insertions(+), 55 deletions(-) diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 7c4d05e00..f8261c026 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -69,6 +69,10 @@ compare_byte_ptrs :: proc "contextless" (a, b: ^byte, n: int) -> int { return 0; } +compare_ptrs :: inline proc "contextless" (a, b: rawptr, n: int) -> int { + return compare_byte_ptrs((^byte)(a), (^byte)(b), n); +} + ptr_offset :: proc "contextless" (ptr: $P/^$T, n: int) -> P { new := int(uintptr(ptr)) + size_of(T)*n; return P(uintptr(new)); diff --git a/src/checker.cpp b/src/checker.cpp index 6bd10fb3b..acd23f3c0 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2615,37 +2615,39 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { Scope *parent_scope = ctx->scope; GB_ASSERT(parent_scope->flags&ScopeFlag_File); - String fullpath = fl->fullpath; + GB_ASSERT(fl->fullpaths.count > 0); + String fullpath = fl->fullpaths[0]; String library_name = path_to_entity_name(fl->library_name.string, fullpath); if (is_blank_ident(library_name)) { error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); return; } - if (fl->collection_name != "system") { - char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1); - defer (gb_free(heap_allocator(), c_str)); - gb_memmove(c_str, fullpath.text, fullpath.len); - c_str[fullpath.len] = '\0'; + // if (fl->collection_name != "system") { + // char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1); + // defer (gb_free(heap_allocator(), c_str)); + // gb_memmove(c_str, fullpath.text, fullpath.len); + // c_str[fullpath.len] = '\0'; - gbFile f = {}; - gbFileError file_err = gb_file_open(&f, c_str); - defer (gb_file_close(&f)); + // gbFile f = {}; + // gbFileError file_err = gb_file_open(&f, c_str); + // defer (gb_file_close(&f)); - switch (file_err) { - case gbFileError_Invalid: - error(decl, "Invalid file or cannot be found ('%.*s')", LIT(fullpath)); - return; - case gbFileError_NotExists: - error(decl, "File cannot be found ('%.*s')", LIT(fullpath)); - return; - } - } + // switch (file_err) { + // case gbFileError_Invalid: + // error(decl, "Invalid file or cannot be found ('%.*s')", LIT(fullpath)); + // return; + // case gbFileError_NotExists: + // error(decl, "File cannot be found ('%.*s')", LIT(fullpath)); + // return; + // } + // } GB_ASSERT(fl->library_name.pos.line != 0); fl->library_name.string = library_name; + Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid, - fl->fullpath, library_name); + fl->fullpaths, library_name); add_entity(ctx->checker, parent_scope, nullptr, e); } diff --git a/src/entity.cpp b/src/entity.cpp index 37bafc7d3..fa76026ff 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -124,7 +124,7 @@ struct Entity { Scope *scope; } ImportName; struct { - String path; + Array paths; String name; } LibraryName; i32 Nil; @@ -278,9 +278,9 @@ Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type, } Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type, - String path, String name) { + Array paths, String name) { Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type); - entity->LibraryName.path = path; + entity->LibraryName.paths = paths; entity->LibraryName.name = name; entity->state = EntityState_Resolved; // TODO(bill): Is this correct? return entity; diff --git a/src/ir.cpp b/src/ir.cpp index 036727326..5c58b1a2b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1332,22 +1332,24 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) { GB_ASSERT(e->kind == Entity_LibraryName); GB_ASSERT(e->flags & EntityFlag_Used); - String library_path = e->LibraryName.path; - if (library_path.len == 0) { - return; - } - - for_array(path_index, m->foreign_library_paths) { - String path = m->foreign_library_paths[path_index]; -#if defined(GB_SYSTEM_WINDOWS) - if (str_eq_ignore_case(path, library_path)) { -#else - if (str_eq(path, library_path)) { -#endif - return; + for_array(i, e->LibraryName.paths) { + String library_path = e->LibraryName.paths[i]; + if (library_path.len == 0) { + continue; } + + for_array(path_index, m->foreign_library_paths) { + String path = m->foreign_library_paths[path_index]; + #if defined(GB_SYSTEM_WINDOWS) + if (str_eq_ignore_case(path, library_path)) { + #else + if (str_eq(path, library_path)) { + #endif + continue; + } + } + array_add(&m->foreign_library_paths, library_path); } - array_add(&m->foreign_library_paths, library_path); } diff --git a/src/main.cpp b/src/main.cpp index d266bff09..0f63c0089 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -253,7 +253,6 @@ bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None); - GB_ASSERT(args.count >= 3); Array flag_args = array_slice(args, 3, args.count); @@ -877,9 +876,9 @@ int main(int arg_count, char **arg_ptr) { gbString lib_str = gb_string_make(heap_allocator(), ""); defer (gb_string_free(lib_str)); char lib_str_buf[1024] = {0}; + for_array(i, ir_gen.module.foreign_library_paths) { String lib = ir_gen.module.foreign_library_paths[i]; - // gb_printf_err("Linking lib: %.*s\n", LIT(lib)); isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), " \"%.*s\"", LIT(lib)); lib_str = gb_string_appendc(lib_str, lib_str_buf); diff --git a/src/parser.cpp b/src/parser.cpp index 9d8e90347..c57fe7365 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -999,11 +999,11 @@ Ast *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath, Toke return result; } -Ast *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name, +Ast *ast_foreign_import_decl(AstFile *f, Token token, Array filepaths, Token library_name, CommentGroup *docs, CommentGroup *comment) { Ast *result = alloc_ast_node(f, Ast_ForeignImportDecl); result->ForeignImportDecl.token = token; - result->ForeignImportDecl.filepath = filepath; + result->ForeignImportDecl.filepaths = filepaths; result->ForeignImportDecl.library_name = library_name; result->ForeignImportDecl.docs = docs; result->ForeignImportDecl.comment = comment; @@ -3491,15 +3491,38 @@ Ast *parse_foreign_decl(AstFile *f) { break; } if (is_blank_ident(lib_name)) { - syntax_error(lib_name, "Illegal foreign_library name: '_'"); + syntax_error(lib_name, "Illegal foreign import name: '_'"); } - Token file_path = expect_token(f, Token_String); - Ast *s = nullptr; - if (f->curr_proc != nullptr) { - syntax_error(lib_name, "You cannot use foreign_library within a procedure. This must be done at the file scope"); - s = ast_bad_decl(f, lib_name, file_path); + Array filepaths = {}; + if (allow_token(f, Token_OpenBrace)) { + array_init(&filepaths, heap_allocator()); + + while (f->curr_token.kind != Token_CloseBrace && + f->curr_token.kind != Token_EOF) { + + Token path = expect_token(f, Token_String); + array_add(&filepaths, path); + + if (!allow_token(f, Token_Comma)) { + break; + } + } + expect_token(f, Token_CloseBrace); } else { - s = ast_foreign_import_decl(f, token, file_path, lib_name, docs, f->line_comment); + filepaths = array_make(heap_allocator(), 0, 1); + Token path = expect_token(f, Token_String); + array_add(&filepaths, path); + } + + Ast *s = nullptr; + if (filepaths.count == 0) { + syntax_error(lib_name, "foreign import without any paths"); + s = ast_bad_decl(f, lib_name, f->curr_token); + } else if (f->curr_proc != nullptr) { + syntax_error(lib_name, "You cannot use foreign import within a procedure. This must be done at the file scope"); + s = ast_bad_decl(f, lib_name, filepaths[0]); + } else { + s = ast_foreign_import_decl(f, token, filepaths, lib_name, docs, f->line_comment); } expect_semicolon(f, s); return s; @@ -4129,22 +4152,34 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array } else if (node->kind == Ast_ForeignImportDecl) { ast_node(fl, ForeignImportDecl, node); - String file_str = fl->filepath.string; - fl->fullpath = file_str; + fl->fullpaths.allocator = heap_allocator(); + array_reserve(&fl->fullpaths, fl->filepaths.count); + + for_array(fp_idx, fl->filepaths) { + String file_str = fl->filepaths[fp_idx].string; + String fullpath = file_str; - if (fl->collection_name != "system") { String foreign_path = {}; bool ok = determine_path_from_string(p, node, base_dir, file_str, &foreign_path); if (!ok) { - decls[i] = ast_bad_decl(f, fl->filepath, fl->filepath); - continue; + decls[i] = ast_bad_decl(f, fl->filepaths[fp_idx], fl->filepaths[fl->filepaths.count-1]); + goto end; } - fl->fullpath = foreign_path; + fullpath = foreign_path; + array_add(&fl->fullpaths, fullpath); } + if (fl->fullpaths.count == 0) { + error(decls[i], "No foreign paths found"); + decls[i] = ast_bad_decl(f, fl->filepaths[0], fl->filepaths[fl->filepaths.count-1]); + goto end; + } + } else if (node->kind == Ast_WhenStmt) { ast_node(ws, WhenStmt, node); parse_setup_file_when_stmt(p, f, base_dir, ws); } + + end:; } } diff --git a/src/parser.hpp b/src/parser.hpp index d542a8b7a..1020f784f 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -391,10 +391,10 @@ AST_KIND(_DeclBegin, "", bool) \ }) \ AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \ Token token; \ - Token filepath; \ + Array filepaths; \ Token library_name; \ String collection_name; \ - String fullpath; \ + Array fullpaths; \ CommentGroup *docs; \ CommentGroup *comment; \ }) \