Browse Source

foreign import x {"foo.lib", "bar.lib"}

gingerBill 7 years ago
parent
commit
a6fe656f21
7 changed files with 95 additions and 53 deletions
  1. 4 0
      core/mem/mem.odin
  2. 21 19
      src/checker.cpp
  3. 3 3
      src/entity.cpp
  4. 15 13
      src/ir.cpp
  5. 1 2
      src/main.cpp
  6. 49 14
      src/parser.cpp
  7. 2 2
      src/parser.hpp

+ 4 - 0
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));

+ 21 - 19
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);
 }
 

+ 3 - 3
src/entity.cpp

@@ -124,7 +124,7 @@ struct Entity {
 			Scope *scope;
 		} ImportName;
 		struct {
-			String path;
+			Array<String> 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<String> 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;

+ 15 - 13
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(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
-			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
+				continue;
+			}
 		}
+		array_add(&m->foreign_library_paths, library_path);
 	}
-	array_add(&m->foreign_library_paths, library_path);
 }
 
 

+ 1 - 2
src/main.cpp

@@ -253,7 +253,6 @@ bool parse_build_flags(Array<String> 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<String> 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);

+ 49 - 14
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<Token> 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);
+		Array<Token> 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 {
+			filepaths = array_make<Token>(heap_allocator(), 0, 1);
+			Token path = expect_token(f, Token_String);
+			array_add(&filepaths, path);
+		}
+
 		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);
+		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, file_path, lib_name, docs, f->line_comment);
+			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<Ast *>
 		} 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:;
 	}
 }
 

+ 2 - 2
src/parser.hpp

@@ -391,10 +391,10 @@ AST_KIND(_DeclBegin,      "", bool) \
 	}) \
 	AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
 		Token    token;           \
-		Token    filepath;        \
+		Array<Token> filepaths;   \
 		Token    library_name;    \
 		String   collection_name; \
-		String   fullpath;        \
+		Array<String> fullpaths;  \
 		CommentGroup *docs;       \
 		CommentGroup *comment;    \
 	}) \