mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -481,7 +481,9 @@ Raw_Soa_Pointer :: struct {
|
|||||||
Linux,
|
Linux,
|
||||||
Essence,
|
Essence,
|
||||||
FreeBSD,
|
FreeBSD,
|
||||||
|
Haiku,
|
||||||
OpenBSD,
|
OpenBSD,
|
||||||
|
NetBSD,
|
||||||
WASI,
|
WASI,
|
||||||
JS,
|
JS,
|
||||||
Freestanding,
|
Freestanding,
|
||||||
@@ -508,6 +510,7 @@ Odin_Arch_Type :: type_of(ODIN_ARCH)
|
|||||||
Odin_Build_Mode_Type :: enum int {
|
Odin_Build_Mode_Type :: enum int {
|
||||||
Executable,
|
Executable,
|
||||||
Dynamic,
|
Dynamic,
|
||||||
|
Static,
|
||||||
Object,
|
Object,
|
||||||
Assembly,
|
Assembly,
|
||||||
LLVM_IR,
|
LLVM_IR,
|
||||||
|
|||||||
+9
-3
@@ -45,7 +45,13 @@ if [ -z "$LLVM_CONFIG" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
: ${CXX=$($LLVM_CONFIG --bindir)/clang++}
|
if [ -x "$(which clang++)" ]; then
|
||||||
|
: ${CXX="clang++"}
|
||||||
|
elif [ -x "$($LLVM_CONFIG --bindir)/clang++" ]; then
|
||||||
|
: ${CXX=$($LLVM_CONFIG --bindir)/clang++}
|
||||||
|
else
|
||||||
|
error "No clang++ command found. Set CXX to proceed."
|
||||||
|
fi
|
||||||
|
|
||||||
LLVM_VERSION="$($LLVM_CONFIG --version)"
|
LLVM_VERSION="$($LLVM_CONFIG --version)"
|
||||||
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
|
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
|
||||||
@@ -65,8 +71,8 @@ Darwin)
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
darwin_sysroot=
|
darwin_sysroot=
|
||||||
if [ $(which xcode-select) ]; then
|
if [ $(which xcrun) ]; then
|
||||||
darwin_sysroot="--sysroot $(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
|
darwin_sysroot="--sysroot $(xcrun --sdk macosx --show-sdk-path)"
|
||||||
elif [[ -e "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ]]; then
|
elif [[ -e "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ]]; then
|
||||||
darwin_sysroot="--sysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
|
darwin_sysroot="--sysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ create_file_logger :: proc(h: os.Handle, lowest := Level.Debug, opt := Default_F
|
|||||||
return Logger{file_console_logger_proc, data, lowest, opt}
|
return Logger{file_console_logger_proc, data, lowest, opt}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_file_logger :: proc(log: ^Logger) {
|
destroy_file_logger :: proc(log: Logger) {
|
||||||
data := cast(^File_Console_Logger_Data)log.data
|
data := cast(^File_Console_Logger_Data)log.data
|
||||||
if data.file_handle != os.INVALID_HANDLE {
|
if data.file_handle != os.INVALID_HANDLE {
|
||||||
os.close(data.file_handle)
|
os.close(data.file_handle)
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ create_multi_logger :: proc(logs: ..Logger) -> Logger {
|
|||||||
return Logger{multi_logger_proc, data, Level.Debug, nil}
|
return Logger{multi_logger_proc, data, Level.Debug, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_multi_logger :: proc(log : ^Logger) {
|
destroy_multi_logger :: proc(log: Logger) {
|
||||||
data := (^Multi_Logger_Data)(log.data)
|
data := (^Multi_Logger_Data)(log.data)
|
||||||
delete(data.loggers)
|
delete(data.loggers)
|
||||||
free(log.data)
|
free(data)
|
||||||
log^ = nil_logger()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string,
|
multi_logger_proc :: proc(logger_data: rawptr, level: Level, text: string,
|
||||||
|
|||||||
@@ -1188,9 +1188,6 @@ internal_random_prime :: proc(a: ^Int, size_in_bits: int, trials: int, flags :=
|
|||||||
flags := flags
|
flags := flags
|
||||||
trials := trials
|
trials := trials
|
||||||
|
|
||||||
t := &Int{}
|
|
||||||
defer internal_destroy(t)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sanity check the input.
|
Sanity check the input.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ roll_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
pitch_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
|
pitch_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
|
||||||
y := 2 * (q.y*q.z + q.w*q.w)
|
y := 2 * (q.y*q.z + q.w*q.x)
|
||||||
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
||||||
|
|
||||||
if abs(x) <= F16_EPSILON && abs(y) <= F16_EPSILON {
|
if abs(x) <= F16_EPSILON && abs(y) <= F16_EPSILON {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ roll_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
pitch_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
|
pitch_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
|
||||||
y := 2 * (q.y*q.z + q.w*q.w)
|
y := 2 * (q.y*q.z + q.w*q.x)
|
||||||
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
||||||
|
|
||||||
if abs(x) <= F32_EPSILON && abs(y) <= F32_EPSILON {
|
if abs(x) <= F32_EPSILON && abs(y) <= F32_EPSILON {
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ roll_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
pitch_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
|
pitch_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
|
||||||
y := 2 * (q.y*q.z + q.w*q.w)
|
y := 2 * (q.y*q.z + q.w*q.x)
|
||||||
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
|
||||||
|
|
||||||
if abs(x) <= F64_EPSILON && abs(y) <= F64_EPSILON {
|
if abs(x) <= F64_EPSILON && abs(y) <= F64_EPSILON {
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ Foreign_Import_Decl :: struct {
|
|||||||
import_tok: tokenizer.Token,
|
import_tok: tokenizer.Token,
|
||||||
name: ^Ident,
|
name: ^Ident,
|
||||||
collection_name: string,
|
collection_name: string,
|
||||||
fullpaths: []string,
|
fullpaths: []^Expr,
|
||||||
comment: ^Comment_Group,
|
comment: ^Comment_Group,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1190,12 +1190,12 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl {
|
|||||||
error(p, name.pos, "illegal foreign import name: '_'")
|
error(p, name.pos, "illegal foreign import name: '_'")
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpaths: [dynamic]string
|
fullpaths: [dynamic]^ast.Expr
|
||||||
if allow_token(p, .Open_Brace) {
|
if allow_token(p, .Open_Brace) {
|
||||||
for p.curr_tok.kind != .Close_Brace &&
|
for p.curr_tok.kind != .Close_Brace &&
|
||||||
p.curr_tok.kind != .EOF {
|
p.curr_tok.kind != .EOF {
|
||||||
path := expect_token(p, .String)
|
path := parse_expr(p, false)
|
||||||
append(&fullpaths, path.text)
|
append(&fullpaths, path)
|
||||||
|
|
||||||
allow_token(p, .Comma) or_break
|
allow_token(p, .Comma) or_break
|
||||||
}
|
}
|
||||||
@@ -1203,7 +1203,9 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl {
|
|||||||
} else {
|
} else {
|
||||||
path := expect_token(p, .String)
|
path := expect_token(p, .String)
|
||||||
reserve(&fullpaths, 1)
|
reserve(&fullpaths, 1)
|
||||||
append(&fullpaths, path.text)
|
bl := ast.new(ast.Basic_Lit, path.pos, end_pos(path))
|
||||||
|
bl.tok = tok
|
||||||
|
append(&fullpaths, bl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(fullpaths) == 0 {
|
if len(fullpaths) == 0 {
|
||||||
|
|||||||
@@ -448,14 +448,14 @@ foreign libc {
|
|||||||
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
|
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
|
||||||
@(link_name="pread") _unix_pread :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
@(link_name="pread") _unix_pread :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
||||||
@(link_name="pwrite") _unix_pwrite :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
@(link_name="pwrite") _unix_pwrite :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
|
||||||
@(link_name="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: int) -> int ---
|
@(link_name="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: c.int) -> int ---
|
||||||
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
||||||
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
|
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
|
||||||
@(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
@(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
||||||
@(link_name="lstat64") _unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
@(link_name="lstat64") _unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
||||||
@(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
@(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
||||||
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
||||||
@(link_name="access") _unix_access :: proc(path: cstring, mask: int) -> int ---
|
@(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
|
||||||
@(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int ---
|
@(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int ---
|
||||||
|
|
||||||
@(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir ---
|
@(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir ---
|
||||||
@@ -639,7 +639,7 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
|||||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||||
assert(fd != -1)
|
assert(fd != -1)
|
||||||
|
|
||||||
final_offset := i64(_unix_lseek(fd, int(offset), whence))
|
final_offset := i64(_unix_lseek(fd, int(offset), c.int(whence)))
|
||||||
if final_offset == -1 {
|
if final_offset == -1 {
|
||||||
return 0, 1
|
return 0, 1
|
||||||
}
|
}
|
||||||
@@ -892,7 +892,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
|
|||||||
access :: proc(path: string, mask: int) -> bool {
|
access :: proc(path: string, mask: int) -> bool {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
return _unix_access(cstr, mask) == 0
|
return _unix_access(cstr, c.int(mask)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
flush :: proc(fd: Handle) -> Errno {
|
flush :: proc(fd: Handle) -> Errno {
|
||||||
|
|||||||
+118
-49
@@ -1403,6 +1403,65 @@ gb_internal LoadDirectiveResult check_load_directory_directive(CheckerContext *c
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal bool check_hash_kind(CheckerContext *c, Ast *call, String const &hash_kind, u8 const *data, isize data_size, u64 *hash_value) {
|
||||||
|
ast_node(ce, CallExpr, call);
|
||||||
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
|
String name = bd->name.string;
|
||||||
|
GB_ASSERT(name == "load_hash" || name == "hash");
|
||||||
|
|
||||||
|
String supported_hashes[] = {
|
||||||
|
str_lit("adler32"),
|
||||||
|
str_lit("crc32"),
|
||||||
|
str_lit("crc64"),
|
||||||
|
str_lit("fnv32"),
|
||||||
|
str_lit("fnv64"),
|
||||||
|
str_lit("fnv32a"),
|
||||||
|
str_lit("fnv64a"),
|
||||||
|
str_lit("murmur32"),
|
||||||
|
str_lit("murmur64"),
|
||||||
|
};
|
||||||
|
|
||||||
|
bool hash_found = false;
|
||||||
|
for (isize i = 0; i < gb_count_of(supported_hashes); i++) {
|
||||||
|
if (supported_hashes[i] == hash_kind) {
|
||||||
|
hash_found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hash_found) {
|
||||||
|
ERROR_BLOCK();
|
||||||
|
error(ce->proc, "Invalid hash kind passed to `#%.*s`, got: %.*s", LIT(name), LIT(hash_kind));
|
||||||
|
error_line("\tAvailable hash kinds:\n");
|
||||||
|
for (isize i = 0; i < gb_count_of(supported_hashes); i++) {
|
||||||
|
error_line("\t%.*s\n", LIT(supported_hashes[i]));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash_kind == "adler32") {
|
||||||
|
*hash_value = gb_adler32(data, data_size);
|
||||||
|
} else if (hash_kind == "crc32") {
|
||||||
|
*hash_value = gb_crc32(data, data_size);
|
||||||
|
} else if (hash_kind == "crc64") {
|
||||||
|
*hash_value = gb_crc64(data, data_size);
|
||||||
|
} else if (hash_kind == "fnv32") {
|
||||||
|
*hash_value = gb_fnv32(data, data_size);
|
||||||
|
} else if (hash_kind == "fnv64") {
|
||||||
|
*hash_value = gb_fnv64(data, data_size);
|
||||||
|
} else if (hash_kind == "fnv32a") {
|
||||||
|
*hash_value = fnv32a(data, data_size);
|
||||||
|
} else if (hash_kind == "fnv64a") {
|
||||||
|
*hash_value = fnv64a(data, data_size);
|
||||||
|
} else if (hash_kind == "murmur32") {
|
||||||
|
*hash_value = gb_murmur32(data, data_size);
|
||||||
|
} else if (hash_kind == "murmur64") {
|
||||||
|
*hash_value = gb_murmur64(data, data_size);
|
||||||
|
} else {
|
||||||
|
compiler_error("unhandled hash kind: %.*s", LIT(hash_kind));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *operand, Ast *call, Type *type_hint) {
|
gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *operand, Ast *call, Type *type_hint) {
|
||||||
@@ -1480,35 +1539,6 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
|
|||||||
String original_string = o.value.value_string;
|
String original_string = o.value.value_string;
|
||||||
String hash_kind = o_hash.value.value_string;
|
String hash_kind = o_hash.value.value_string;
|
||||||
|
|
||||||
String supported_hashes[] = {
|
|
||||||
str_lit("adler32"),
|
|
||||||
str_lit("crc32"),
|
|
||||||
str_lit("crc64"),
|
|
||||||
str_lit("fnv32"),
|
|
||||||
str_lit("fnv64"),
|
|
||||||
str_lit("fnv32a"),
|
|
||||||
str_lit("fnv64a"),
|
|
||||||
str_lit("murmur32"),
|
|
||||||
str_lit("murmur64"),
|
|
||||||
};
|
|
||||||
|
|
||||||
bool hash_found = false;
|
|
||||||
for (isize i = 0; i < gb_count_of(supported_hashes); i++) {
|
|
||||||
if (supported_hashes[i] == hash_kind) {
|
|
||||||
hash_found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hash_found) {
|
|
||||||
ERROR_BLOCK();
|
|
||||||
error(ce->proc, "Invalid hash kind passed to `#load_hash`, got: %.*s", LIT(hash_kind));
|
|
||||||
error_line("\tAvailable hash kinds:\n");
|
|
||||||
for (isize i = 0; i < gb_count_of(supported_hashes); i++) {
|
|
||||||
error_line("\t%.*s\n", LIT(supported_hashes[i]));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadFileCache *cache = nullptr;
|
LoadFileCache *cache = nullptr;
|
||||||
if (cache_load_file_directive(c, call, original_string, true, &cache)) {
|
if (cache_load_file_directive(c, call, original_string, true, &cache)) {
|
||||||
MUTEX_GUARD(&c->info->load_file_mutex);
|
MUTEX_GUARD(&c->info->load_file_mutex);
|
||||||
@@ -1520,26 +1550,9 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
|
|||||||
} else {
|
} else {
|
||||||
u8 *data = cache->data.text;
|
u8 *data = cache->data.text;
|
||||||
isize file_size = cache->data.len;
|
isize file_size = cache->data.len;
|
||||||
if (hash_kind == "adler32") {
|
|
||||||
hash_value = gb_adler32(data, file_size);
|
if (!check_hash_kind(c, call, hash_kind, data, file_size, &hash_value)) {
|
||||||
} else if (hash_kind == "crc32") {
|
return false;
|
||||||
hash_value = gb_crc32(data, file_size);
|
|
||||||
} else if (hash_kind == "crc64") {
|
|
||||||
hash_value = gb_crc64(data, file_size);
|
|
||||||
} else if (hash_kind == "fnv32") {
|
|
||||||
hash_value = gb_fnv32(data, file_size);
|
|
||||||
} else if (hash_kind == "fnv64") {
|
|
||||||
hash_value = gb_fnv64(data, file_size);
|
|
||||||
} else if (hash_kind == "fnv32a") {
|
|
||||||
hash_value = fnv32a(data, file_size);
|
|
||||||
} else if (hash_kind == "fnv64a") {
|
|
||||||
hash_value = fnv64a(data, file_size);
|
|
||||||
} else if (hash_kind == "murmur32") {
|
|
||||||
hash_value = gb_murmur32(data, file_size);
|
|
||||||
} else if (hash_kind == "murmur64") {
|
|
||||||
hash_value = gb_murmur64(data, file_size);
|
|
||||||
} else {
|
|
||||||
compiler_error("unhandled hash kind: %.*s", LIT(hash_kind));
|
|
||||||
}
|
}
|
||||||
string_map_set(&cache->hashes, hash_kind, hash_value);
|
string_map_set(&cache->hashes, hash_kind, hash_value);
|
||||||
}
|
}
|
||||||
@@ -1550,6 +1563,62 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
} else if (name == "hash") {
|
||||||
|
if (ce->args.count != 2) {
|
||||||
|
if (ce->args.count == 0) {
|
||||||
|
error(ce->close, "'#hash' expects 2 argument, got 0");
|
||||||
|
} else {
|
||||||
|
error(ce->args[0], "'#hash' expects 2 argument, got %td", ce->args.count);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast *arg0 = ce->args[0];
|
||||||
|
Ast *arg1 = ce->args[1];
|
||||||
|
Operand o = {};
|
||||||
|
check_expr(c, &o, arg0);
|
||||||
|
if (o.mode != Addressing_Constant) {
|
||||||
|
error(arg0, "'#hash' expected a constant string argument");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_type_string(o.type)) {
|
||||||
|
gbString str = type_to_string(o.type);
|
||||||
|
error(arg0, "'#hash' expected a constant string, got %s", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand o_hash = {};
|
||||||
|
check_expr(c, &o_hash, arg1);
|
||||||
|
if (o_hash.mode != Addressing_Constant) {
|
||||||
|
error(arg1, "'#hash' expected a constant string argument");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_type_string(o_hash.type)) {
|
||||||
|
gbString str = type_to_string(o.type);
|
||||||
|
error(arg1, "'#hash' expected a constant string, got %s", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gbAllocator a = heap_allocator();
|
||||||
|
|
||||||
|
GB_ASSERT(o.value.kind == ExactValue_String);
|
||||||
|
GB_ASSERT(o_hash.value.kind == ExactValue_String);
|
||||||
|
|
||||||
|
String original_string = o.value.value_string;
|
||||||
|
String hash_kind = o_hash.value.value_string;
|
||||||
|
|
||||||
|
// TODO: Cache hash values based off of string constant and hash kind?
|
||||||
|
u64 hash_value = 0;
|
||||||
|
if (check_hash_kind(c, call, hash_kind, original_string.text, original_string.len, &hash_value)) {
|
||||||
|
operand->type = t_untyped_integer;
|
||||||
|
operand->mode = Addressing_Constant;
|
||||||
|
operand->value = exact_value_u64(hash_value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
} else if (name == "assert") {
|
} else if (name == "assert") {
|
||||||
if (ce->args.count != 1 && ce->args.count != 2) {
|
if (ce->args.count != 1 && ce->args.count != 2) {
|
||||||
error(call, "'#assert' expects either 1 or 2 arguments, got %td", ce->args.count);
|
error(call, "'#assert' expects either 1 or 2 arguments, got %td", ce->args.count);
|
||||||
|
|||||||
+2
-1
@@ -7416,7 +7416,8 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
|
|||||||
name == "config" ||
|
name == "config" ||
|
||||||
name == "load" ||
|
name == "load" ||
|
||||||
name == "load_directory" ||
|
name == "load_directory" ||
|
||||||
name == "load_hash"
|
name == "load_hash" ||
|
||||||
|
name == "hash"
|
||||||
) {
|
) {
|
||||||
operand->mode = Addressing_Builtin;
|
operand->mode = Addressing_Builtin;
|
||||||
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
||||||
|
|||||||
+92
-47
@@ -1283,6 +1283,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
|
|||||||
mpsc_init(&i->definition_queue, a); //); // 1<<20);
|
mpsc_init(&i->definition_queue, a); //); // 1<<20);
|
||||||
mpsc_init(&i->required_global_variable_queue, a); // 1<<10);
|
mpsc_init(&i->required_global_variable_queue, a); // 1<<10);
|
||||||
mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10);
|
mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10);
|
||||||
|
mpsc_init(&i->foreign_imports_to_check_fullpaths, a); // 1<<10);
|
||||||
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
|
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
|
||||||
|
|
||||||
string_map_init(&i->load_directory_cache);
|
string_map_init(&i->load_directory_cache);
|
||||||
@@ -1307,6 +1308,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
|
|||||||
mpsc_destroy(&i->definition_queue);
|
mpsc_destroy(&i->definition_queue);
|
||||||
mpsc_destroy(&i->required_global_variable_queue);
|
mpsc_destroy(&i->required_global_variable_queue);
|
||||||
mpsc_destroy(&i->required_foreign_imports_through_force_queue);
|
mpsc_destroy(&i->required_foreign_imports_through_force_queue);
|
||||||
|
mpsc_destroy(&i->foreign_imports_to_check_fullpaths);
|
||||||
|
|
||||||
map_destroy(&i->objc_msgSend_types);
|
map_destroy(&i->objc_msgSend_types);
|
||||||
string_map_destroy(&i->load_file_cache);
|
string_map_destroy(&i->load_file_cache);
|
||||||
@@ -4874,6 +4876,83 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal void check_foreign_import_fullpaths(Checker *c) {
|
||||||
|
CheckerContext ctx = make_checker_context(c);
|
||||||
|
|
||||||
|
UntypedExprInfoMap untyped = {};
|
||||||
|
defer (map_destroy(&untyped));
|
||||||
|
|
||||||
|
for (Entity *e = nullptr; mpsc_dequeue(&c->info.foreign_imports_to_check_fullpaths, &e); /**/) {
|
||||||
|
GB_ASSERT(e != nullptr);
|
||||||
|
GB_ASSERT(e->kind == Entity_LibraryName);
|
||||||
|
Ast *decl = e->LibraryName.decl;
|
||||||
|
ast_node(fl, ForeignImportDecl, decl);
|
||||||
|
|
||||||
|
AstFile *f = decl->file();
|
||||||
|
|
||||||
|
reset_checker_context(&ctx, f, &untyped);
|
||||||
|
ctx.collect_delayed_decls = false;
|
||||||
|
|
||||||
|
GB_ASSERT(ctx.scope == e->scope);
|
||||||
|
|
||||||
|
if (fl->fullpaths.count == 0) {
|
||||||
|
String base_dir = dir_from_path(decl->file()->fullpath);
|
||||||
|
|
||||||
|
auto fullpaths = array_make<String>(permanent_allocator(), 0, fl->filepaths.count);
|
||||||
|
|
||||||
|
for (Ast *fp_node : fl->filepaths) {
|
||||||
|
Operand op = {};
|
||||||
|
check_expr(&ctx, &op, fp_node);
|
||||||
|
if (op.mode != Addressing_Constant && op.value.kind != ExactValue_String) {
|
||||||
|
gbString s = expr_to_string(op.expr);
|
||||||
|
error(fp_node, "Expected a constant string value, got '%s'", s);
|
||||||
|
gb_string_free(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!is_type_string(op.type)) {
|
||||||
|
gbString s = type_to_string(op.type);
|
||||||
|
error(fp_node, "Expected a constant string value, got value of type '%s'", s);
|
||||||
|
gb_string_free(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String file_str = op.value.value_string;
|
||||||
|
file_str = string_trim_whitespace(file_str);
|
||||||
|
|
||||||
|
String fullpath = file_str;
|
||||||
|
if (allow_check_foreign_filepath()) {
|
||||||
|
String foreign_path = {};
|
||||||
|
bool ok = determine_path_from_string(nullptr, decl, base_dir, file_str, &foreign_path, /*use error not syntax_error*/true);
|
||||||
|
if (ok) {
|
||||||
|
fullpath = foreign_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_add(&fullpaths, fullpath);
|
||||||
|
}
|
||||||
|
fl->fullpaths = slice_from_array(fullpaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String const &path : fl->fullpaths) {
|
||||||
|
String ext = path_extension(path);
|
||||||
|
if (str_eq_ignore_case(ext, ".c") ||
|
||||||
|
str_eq_ignore_case(ext, ".cpp") ||
|
||||||
|
str_eq_ignore_case(ext, ".cxx") ||
|
||||||
|
str_eq_ignore_case(ext, ".h") ||
|
||||||
|
str_eq_ignore_case(ext, ".hpp") ||
|
||||||
|
str_eq_ignore_case(ext, ".hxx") ||
|
||||||
|
false
|
||||||
|
) {
|
||||||
|
error(fl->token, "With 'foreign import', you cannot import a %.*s file/directory, you must precompile the library and link against that", LIT(ext));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_untyped_expressions(ctx.info, &untyped);
|
||||||
|
|
||||||
|
e->LibraryName.paths = fl->fullpaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
||||||
if (decl->state_flags & StateFlag_BeenHandled) return;
|
if (decl->state_flags & StateFlag_BeenHandled) return;
|
||||||
decl->state_flags |= StateFlag_BeenHandled;
|
decl->state_flags |= StateFlag_BeenHandled;
|
||||||
@@ -4883,59 +4962,26 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
|||||||
Scope *parent_scope = ctx->scope;
|
Scope *parent_scope = ctx->scope;
|
||||||
GB_ASSERT(parent_scope->flags&ScopeFlag_File);
|
GB_ASSERT(parent_scope->flags&ScopeFlag_File);
|
||||||
|
|
||||||
GB_ASSERT(fl->fullpaths.count > 0);
|
String library_name = fl->library_name.string;
|
||||||
String fullpath = fl->fullpaths[0];
|
if (library_name.len == 0 && fl->fullpaths.count != 0) {
|
||||||
String library_name = path_to_entity_name(fl->library_name.string, fullpath);
|
String fullpath = fl->fullpaths[0];
|
||||||
if (is_blank_ident(library_name)) {
|
library_name = path_to_entity_name(fl->library_name.string, fullpath);
|
||||||
error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
|
}
|
||||||
|
if (library_name.len == 0 || 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(library_name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String const &path : fl->fullpaths) {
|
|
||||||
String ext = path_extension(path);
|
|
||||||
if (str_eq_ignore_case(ext, ".c") ||
|
|
||||||
str_eq_ignore_case(ext, ".cpp") ||
|
|
||||||
str_eq_ignore_case(ext, ".cxx") ||
|
|
||||||
str_eq_ignore_case(ext, ".h") ||
|
|
||||||
str_eq_ignore_case(ext, ".hpp") ||
|
|
||||||
str_eq_ignore_case(ext, ".hxx") ||
|
|
||||||
false
|
|
||||||
) {
|
|
||||||
error(fl->token, "With 'foreign import', you cannot import a %.*s file directory, you must precompile the library and link against that", LIT(ext));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
|
|
||||||
// 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);
|
GB_ASSERT(fl->library_name.pos.line != 0);
|
||||||
fl->library_name.string = library_name;
|
fl->library_name.string = library_name;
|
||||||
|
|
||||||
Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
|
Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
|
||||||
fl->fullpaths, library_name);
|
fl->fullpaths, library_name);
|
||||||
|
e->LibraryName.decl = decl;
|
||||||
add_entity_flags_from_file(ctx, e, parent_scope);
|
add_entity_flags_from_file(ctx, e, parent_scope);
|
||||||
add_entity(ctx, parent_scope, nullptr, e);
|
add_entity(ctx, parent_scope, nullptr, e);
|
||||||
|
|
||||||
|
|
||||||
AttributeContext ac = {};
|
AttributeContext ac = {};
|
||||||
check_decl_attributes(ctx, fl->attributes, foreign_import_decl_attribute, &ac);
|
check_decl_attributes(ctx, fl->attributes, foreign_import_decl_attribute, &ac);
|
||||||
if (ac.require_declaration) {
|
if (ac.require_declaration) {
|
||||||
@@ -4950,12 +4996,8 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
|||||||
e->LibraryName.extra_linker_flags = extra_linker_flags;
|
e->LibraryName.extra_linker_flags = extra_linker_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_asm_extension(fullpath)) {
|
mpsc_enqueue(&ctx->info->foreign_imports_to_check_fullpaths, e);
|
||||||
if (build_context.metrics.arch != TargetArch_amd64 && build_context.metrics.os != TargetOs_darwin) {
|
|
||||||
error(decl, "Assembly files are not yet supported on this platform: %.*s_%.*s",
|
|
||||||
LIT(target_os_names[build_context.metrics.os]), LIT(target_arch_names[build_context.metrics.arch]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if a new package is present
|
// Returns true if a new package is present
|
||||||
@@ -6317,6 +6359,9 @@ gb_internal void check_parsed_files(Checker *c) {
|
|||||||
TIME_SECTION("check procedure bodies");
|
TIME_SECTION("check procedure bodies");
|
||||||
check_procedure_bodies(c);
|
check_procedure_bodies(c);
|
||||||
|
|
||||||
|
TIME_SECTION("check foreign import fullpaths");
|
||||||
|
check_foreign_import_fullpaths(c);
|
||||||
|
|
||||||
TIME_SECTION("add entities from procedure bodies");
|
TIME_SECTION("add entities from procedure bodies");
|
||||||
check_merge_queues_into_arrays(c);
|
check_merge_queues_into_arrays(c);
|
||||||
|
|
||||||
|
|||||||
@@ -414,6 +414,7 @@ struct CheckerInfo {
|
|||||||
MPSCQueue<Entity *> entity_queue;
|
MPSCQueue<Entity *> entity_queue;
|
||||||
MPSCQueue<Entity *> required_global_variable_queue;
|
MPSCQueue<Entity *> required_global_variable_queue;
|
||||||
MPSCQueue<Entity *> required_foreign_imports_through_force_queue;
|
MPSCQueue<Entity *> required_foreign_imports_through_force_queue;
|
||||||
|
MPSCQueue<Entity *> foreign_imports_to_check_fullpaths;
|
||||||
|
|
||||||
MPSCQueue<Ast *> intrinsics_entry_point_usage;
|
MPSCQueue<Ast *> intrinsics_entry_point_usage;
|
||||||
|
|
||||||
@@ -434,6 +435,8 @@ struct CheckerInfo {
|
|||||||
BlockingMutex load_directory_mutex;
|
BlockingMutex load_directory_mutex;
|
||||||
StringMap<LoadDirectoryCache *> load_directory_cache;
|
StringMap<LoadDirectoryCache *> load_directory_cache;
|
||||||
PtrMap<Ast *, LoadDirectoryCache *> load_directory_map; // Key: Ast_CallExpr *
|
PtrMap<Ast *, LoadDirectoryCache *> load_directory_map; // Key: Ast_CallExpr *
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheckerContext {
|
struct CheckerContext {
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ struct Entity {
|
|||||||
Scope *scope;
|
Scope *scope;
|
||||||
} ImportName;
|
} ImportName;
|
||||||
struct {
|
struct {
|
||||||
|
Ast *decl;
|
||||||
Slice<String> paths;
|
Slice<String> paths;
|
||||||
String name;
|
String name;
|
||||||
i64 priority_index;
|
i64 priority_index;
|
||||||
|
|||||||
+46
-31
@@ -1284,14 +1284,16 @@ gb_internal Ast *ast_import_decl(AstFile *f, Token token, Token relpath, Token i
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal Ast *ast_foreign_import_decl(AstFile *f, Token token, Array<Token> filepaths, Token library_name,
|
gb_internal Ast *ast_foreign_import_decl(AstFile *f, Token token, Array<Ast *> filepaths, Token library_name,
|
||||||
CommentGroup *docs, CommentGroup *comment) {
|
bool multiple_filepaths,
|
||||||
|
CommentGroup *docs, CommentGroup *comment) {
|
||||||
Ast *result = alloc_ast_node(f, Ast_ForeignImportDecl);
|
Ast *result = alloc_ast_node(f, Ast_ForeignImportDecl);
|
||||||
result->ForeignImportDecl.token = token;
|
result->ForeignImportDecl.token = token;
|
||||||
result->ForeignImportDecl.filepaths = slice_from_array(filepaths);
|
result->ForeignImportDecl.filepaths = slice_from_array(filepaths);
|
||||||
result->ForeignImportDecl.library_name = library_name;
|
result->ForeignImportDecl.library_name = library_name;
|
||||||
result->ForeignImportDecl.docs = docs;
|
result->ForeignImportDecl.docs = docs;
|
||||||
result->ForeignImportDecl.comment = comment;
|
result->ForeignImportDecl.comment = comment;
|
||||||
|
result->ForeignImportDecl.multiple_filepaths = multiple_filepaths;
|
||||||
result->ForeignImportDecl.attributes.allocator = ast_allocator(f);
|
result->ForeignImportDecl.attributes.allocator = ast_allocator(f);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -4882,14 +4884,17 @@ gb_internal Ast *parse_foreign_decl(AstFile *f) {
|
|||||||
if (is_blank_ident(lib_name)) {
|
if (is_blank_ident(lib_name)) {
|
||||||
syntax_error(lib_name, "Illegal foreign import name: '_'");
|
syntax_error(lib_name, "Illegal foreign import name: '_'");
|
||||||
}
|
}
|
||||||
Array<Token> filepaths = {};
|
bool multiple_filepaths = false;
|
||||||
|
|
||||||
|
Array<Ast *> filepaths = {};
|
||||||
if (allow_token(f, Token_OpenBrace)) {
|
if (allow_token(f, Token_OpenBrace)) {
|
||||||
|
multiple_filepaths = true;
|
||||||
array_init(&filepaths, ast_allocator(f));
|
array_init(&filepaths, ast_allocator(f));
|
||||||
|
|
||||||
while (f->curr_token.kind != Token_CloseBrace &&
|
while (f->curr_token.kind != Token_CloseBrace &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
|
|
||||||
Token path = expect_token(f, Token_String);
|
Ast *path = parse_expr(f, false);
|
||||||
array_add(&filepaths, path);
|
array_add(&filepaths, path);
|
||||||
|
|
||||||
if (!allow_field_separator(f)) {
|
if (!allow_field_separator(f)) {
|
||||||
@@ -4898,9 +4903,10 @@ gb_internal Ast *parse_foreign_decl(AstFile *f) {
|
|||||||
}
|
}
|
||||||
expect_closing_brace_of_field_list(f);
|
expect_closing_brace_of_field_list(f);
|
||||||
} else {
|
} else {
|
||||||
filepaths = array_make<Token>(ast_allocator(f), 0, 1);
|
filepaths = array_make<Ast *>(ast_allocator(f), 0, 1);
|
||||||
Token path = expect_token(f, Token_String);
|
Token path = expect_token(f, Token_String);
|
||||||
array_add(&filepaths, path);
|
Ast *lit = ast_basic_lit(f, path);
|
||||||
|
array_add(&filepaths, lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast *s = nullptr;
|
Ast *s = nullptr;
|
||||||
@@ -4909,9 +4915,9 @@ gb_internal Ast *parse_foreign_decl(AstFile *f) {
|
|||||||
s = ast_bad_decl(f, lib_name, f->curr_token);
|
s = ast_bad_decl(f, lib_name, f->curr_token);
|
||||||
} else if (f->curr_proc != nullptr) {
|
} 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");
|
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]);
|
s = ast_bad_decl(f, lib_name, ast_token(filepaths[0]));
|
||||||
} else {
|
} else {
|
||||||
s = ast_foreign_import_decl(f, token, filepaths, lib_name, docs, f->line_comment);
|
s = ast_foreign_import_decl(f, token, filepaths, lib_name, multiple_filepaths, docs, f->line_comment);
|
||||||
}
|
}
|
||||||
expect_semicolon(f);
|
expect_semicolon(f);
|
||||||
return s;
|
return s;
|
||||||
@@ -5685,9 +5691,19 @@ gb_internal bool is_package_name_reserved(String const &name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node, String base_dir, String const &original_string, String *path) {
|
gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node, String base_dir, String const &original_string, String *path, bool use_check_errors=false) {
|
||||||
GB_ASSERT(path != nullptr);
|
GB_ASSERT(path != nullptr);
|
||||||
|
|
||||||
|
void (*do_error)(Ast *, char const *, ...);
|
||||||
|
void (*do_warning)(Token const &, char const *, ...);
|
||||||
|
|
||||||
|
do_error = &syntax_error;
|
||||||
|
do_warning = &syntax_warning;
|
||||||
|
if (use_check_errors) {
|
||||||
|
do_error = &error;
|
||||||
|
do_error = &warning;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(bill): if file_mutex == nullptr, this means that the code is used within the semantics stage
|
// NOTE(bill): if file_mutex == nullptr, this means that the code is used within the semantics stage
|
||||||
|
|
||||||
String collection_name = {};
|
String collection_name = {};
|
||||||
@@ -5714,7 +5730,7 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
|||||||
|
|
||||||
String file_str = {};
|
String file_str = {};
|
||||||
if (colon_pos == 0) {
|
if (colon_pos == 0) {
|
||||||
syntax_error(node, "Expected a collection name");
|
do_error(node, "Expected a collection name");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5729,11 +5745,11 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
|||||||
if (has_windows_drive) {
|
if (has_windows_drive) {
|
||||||
String sub_file_path = substring(file_str, 3, file_str.len);
|
String sub_file_path = substring(file_str, 3, file_str.len);
|
||||||
if (!is_import_path_valid(sub_file_path)) {
|
if (!is_import_path_valid(sub_file_path)) {
|
||||||
syntax_error(node, "Invalid import path: '%.*s'", LIT(file_str));
|
do_error(node, "Invalid import path: '%.*s'", LIT(file_str));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!is_import_path_valid(file_str)) {
|
} else if (!is_import_path_valid(file_str)) {
|
||||||
syntax_error(node, "Invalid import path: '%.*s'", LIT(file_str));
|
do_error(node, "Invalid import path: '%.*s'", LIT(file_str));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5755,16 +5771,16 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
|||||||
}
|
}
|
||||||
if (replace_with_base) {
|
if (replace_with_base) {
|
||||||
if (ast_file_vet_deprecated(node->file())) {
|
if (ast_file_vet_deprecated(node->file())) {
|
||||||
syntax_error(node, "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str));
|
do_error(node, "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str));
|
||||||
} else {
|
} else {
|
||||||
syntax_warning(ast_token(node), "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str));
|
do_warning(ast_token(node), "import \"core:%.*s\" has been deprecated in favour of \"base:%.*s\"", LIT(file_str), LIT(file_str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (collection_name == "system") {
|
if (collection_name == "system") {
|
||||||
if (node->kind != Ast_ForeignImportDecl) {
|
if (node->kind != Ast_ForeignImportDecl) {
|
||||||
syntax_error(node, "The library collection 'system' is restrict for 'foreign_library'");
|
do_error(node, "The library collection 'system' is restrict for 'foreign import'");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
*path = file_str;
|
*path = file_str;
|
||||||
@@ -5772,7 +5788,7 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
|||||||
}
|
}
|
||||||
} else if (!find_library_collection_path(collection_name, &base_dir)) {
|
} else if (!find_library_collection_path(collection_name, &base_dir)) {
|
||||||
// NOTE(bill): It's a naughty name
|
// NOTE(bill): It's a naughty name
|
||||||
syntax_error(node, "Unknown library collection: '%.*s'", LIT(collection_name));
|
do_error(node, "Unknown library collection: '%.*s'", LIT(collection_name));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -5796,7 +5812,7 @@ gb_internal bool determine_path_from_string(BlockingMutex *file_mutex, Ast *node
|
|||||||
if (collection_name == "core" || collection_name == "base") {
|
if (collection_name == "core" || collection_name == "base") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
syntax_error(node, "The package '%.*s' must be imported with the 'base' library collection: 'base:%.*s'", LIT(file_str), LIT(file_str));
|
do_error(node, "The package '%.*s' must be imported with the 'base' library collection: 'base:%.*s'", LIT(file_str), LIT(file_str));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5881,30 +5897,29 @@ gb_internal void parse_setup_file_decls(Parser *p, AstFile *f, String const &bas
|
|||||||
} else if (node->kind == Ast_ForeignImportDecl) {
|
} else if (node->kind == Ast_ForeignImportDecl) {
|
||||||
ast_node(fl, ForeignImportDecl, node);
|
ast_node(fl, ForeignImportDecl, node);
|
||||||
|
|
||||||
auto fullpaths = array_make<String>(permanent_allocator(), 0, fl->filepaths.count);
|
if (fl->filepaths.count == 0) {
|
||||||
|
syntax_error(decls[i], "No foreign paths found");
|
||||||
for (Token const &fp : fl->filepaths) {
|
decls[i] = ast_bad_decl(f, ast_token(fl->filepaths[0]), ast_end_token(fl->filepaths[fl->filepaths.count-1]));
|
||||||
String file_str = string_trim_whitespace(string_value_from_token(f, fp));
|
goto end;
|
||||||
|
} else if (!fl->multiple_filepaths &&
|
||||||
|
fl->filepaths.count == 1) {
|
||||||
|
Ast *fp = fl->filepaths[0];
|
||||||
|
GB_ASSERT(fp->kind == Ast_BasicLit);
|
||||||
|
Token fp_token = fp->BasicLit.token;
|
||||||
|
String file_str = string_trim_whitespace(string_value_from_token(f, fp_token));
|
||||||
String fullpath = file_str;
|
String fullpath = file_str;
|
||||||
if (allow_check_foreign_filepath()) {
|
if (allow_check_foreign_filepath()) {
|
||||||
String foreign_path = {};
|
String foreign_path = {};
|
||||||
bool ok = determine_path_from_string(&p->file_decl_mutex, node, base_dir, file_str, &foreign_path);
|
bool ok = determine_path_from_string(&p->file_decl_mutex, node, base_dir, file_str, &foreign_path);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
decls[i] = ast_bad_decl(f, fp, fl->filepaths[fl->filepaths.count-1]);
|
decls[i] = ast_bad_decl(f, fp_token, fp_token);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
fullpath = foreign_path;
|
fullpath = foreign_path;
|
||||||
}
|
}
|
||||||
array_add(&fullpaths, fullpath);
|
fl->fullpaths = slice_make<String>(permanent_allocator(), 1);
|
||||||
|
fl->fullpaths[0] = fullpath;
|
||||||
}
|
}
|
||||||
if (fullpaths.count == 0) {
|
|
||||||
syntax_error(decls[i], "No foreign paths found");
|
|
||||||
decls[i] = ast_bad_decl(f, fl->filepaths[0], fl->filepaths[fl->filepaths.count-1]);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
fl->fullpaths = slice_from_array(fullpaths);
|
|
||||||
|
|
||||||
|
|
||||||
} else if (node->kind == Ast_WhenStmt) {
|
} else if (node->kind == Ast_WhenStmt) {
|
||||||
ast_node(ws, WhenStmt, node);
|
ast_node(ws, WhenStmt, node);
|
||||||
|
|||||||
+2
-1
@@ -631,7 +631,8 @@ AST_KIND(_DeclBegin, "", bool) \
|
|||||||
}) \
|
}) \
|
||||||
AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Slice<Token> filepaths; \
|
Slice<Ast *> filepaths; \
|
||||||
|
bool multiple_filepaths; \
|
||||||
Token library_name; \
|
Token library_name; \
|
||||||
String collection_name; \
|
String collection_name; \
|
||||||
Slice<String> fullpaths; \
|
Slice<String> fullpaths; \
|
||||||
|
|||||||
+1
-1
@@ -278,7 +278,7 @@ Token ast_end_token(Ast *node) {
|
|||||||
case Ast_ImportDecl: return node->ImportDecl.relpath;
|
case Ast_ImportDecl: return node->ImportDecl.relpath;
|
||||||
case Ast_ForeignImportDecl:
|
case Ast_ForeignImportDecl:
|
||||||
if (node->ForeignImportDecl.filepaths.count > 0) {
|
if (node->ForeignImportDecl.filepaths.count > 0) {
|
||||||
return node->ForeignImportDecl.filepaths[node->ForeignImportDecl.filepaths.count-1];
|
return ast_end_token(node->ForeignImportDecl.filepaths[node->ForeignImportDecl.filepaths.count-1]);
|
||||||
}
|
}
|
||||||
if (node->ForeignImportDecl.library_name.kind != Token_Invalid) {
|
if (node->ForeignImportDecl.library_name.kind != Token_Invalid) {
|
||||||
return node->ForeignImportDecl.library_name;
|
return node->ForeignImportDecl.library_name;
|
||||||
|
|||||||
Vendored
+6
-1
@@ -319,7 +319,12 @@ default_draw_frame :: proc(ctx: ^Context, rect: Rect, colorid: Color_Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init :: proc(ctx: ^Context, set_clipboard: proc(user_data: rawptr, text: string) -> (ok: bool), get_clipboard: proc(user_data: rawptr) -> (text: string, ok: bool), clipboard_user_data: rawptr) {
|
init :: proc(
|
||||||
|
ctx: ^Context,
|
||||||
|
set_clipboard: proc(user_data: rawptr, text: string) -> (ok: bool) = nil,
|
||||||
|
get_clipboard: proc(user_data: rawptr) -> (text: string, ok: bool) = nil,
|
||||||
|
clipboard_user_data: rawptr = nil,
|
||||||
|
) {
|
||||||
ctx^ = {} // zero memory
|
ctx^ = {} // zero memory
|
||||||
ctx.draw_frame = default_draw_frame
|
ctx.draw_frame = default_draw_frame
|
||||||
ctx._style = default_style
|
ctx._style = default_style
|
||||||
|
|||||||
Vendored
+6
-6
@@ -1443,7 +1443,12 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
wmi.storeU8(off(1), !!e.isTrusted);
|
wmi.storeU8(off(1), !!e.isTrusted);
|
||||||
|
|
||||||
let base = off(0, 8);
|
let base = off(0, 8);
|
||||||
if (e instanceof MouseEvent) {
|
if (e instanceof WheelEvent) {
|
||||||
|
wmi.storeF64(off(8), e.deltaX);
|
||||||
|
wmi.storeF64(off(8), e.deltaY);
|
||||||
|
wmi.storeF64(off(8), e.deltaZ);
|
||||||
|
wmi.storeU32(off(4), e.deltaMode);
|
||||||
|
} else if (e instanceof MouseEvent) {
|
||||||
wmi.storeI64(off(8), e.screenX);
|
wmi.storeI64(off(8), e.screenX);
|
||||||
wmi.storeI64(off(8), e.screenY);
|
wmi.storeI64(off(8), e.screenY);
|
||||||
wmi.storeI64(off(8), e.clientX);
|
wmi.storeI64(off(8), e.clientX);
|
||||||
@@ -1482,11 +1487,6 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
wmi.storeI32(off(W), e.code.length)
|
wmi.storeI32(off(W), e.code.length)
|
||||||
wmi.storeString(off(16, 1), e.key);
|
wmi.storeString(off(16, 1), e.key);
|
||||||
wmi.storeString(off(16, 1), e.code);
|
wmi.storeString(off(16, 1), e.code);
|
||||||
} else if (e instanceof WheelEvent) {
|
|
||||||
wmi.storeF64(off(8), e.deltaX);
|
|
||||||
wmi.storeF64(off(8), e.deltaY);
|
|
||||||
wmi.storeF64(off(8), e.deltaZ);
|
|
||||||
wmi.storeU32(off(4), e.deltaMode);
|
|
||||||
} else if (e.type === 'scroll') {
|
} else if (e.type === 'scroll') {
|
||||||
wmi.storeF64(off(8), window.scrollX);
|
wmi.storeF64(off(8), window.scrollX);
|
||||||
wmi.storeF64(off(8), window.scrollY);
|
wmi.storeF64(off(8), window.scrollY);
|
||||||
|
|||||||
Reference in New Issue
Block a user