mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-01 12:18:15 +00:00
Merge pull request #2597 from odin-lang/ordered-named-arguments
Allowing for Positional and Named Arguments in Procedure Calls
This commit is contained in:
@@ -1118,7 +1118,7 @@ expand_macro :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> bool {
|
|||||||
|
|
||||||
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
|
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
|
||||||
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
|
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
|
||||||
tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
|
tpath := filepath.join({cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
|
||||||
if os.exists(tpath) {
|
if os.exists(tpath) {
|
||||||
return strings.clone(tpath), true
|
return strings.clone(tpath), true
|
||||||
}
|
}
|
||||||
@@ -1136,7 +1136,7 @@ search_include_paths :: proc(cpp: ^Preprocessor, filename: string) -> (path: str
|
|||||||
}
|
}
|
||||||
|
|
||||||
for include_path in cpp.include_paths {
|
for include_path in cpp.include_paths {
|
||||||
tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator)
|
tpath := filepath.join({include_path, filename}, allocator=context.temp_allocator)
|
||||||
if os.exists(tpath) {
|
if os.exists(tpath) {
|
||||||
path, ok = strings.clone(tpath), true
|
path, ok = strings.clone(tpath), true
|
||||||
cpp.filepath_cache[filename] = path
|
cpp.filepath_cache[filename] = path
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
|
|||||||
|
|
||||||
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
|
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
|
||||||
|
|
||||||
zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size)
|
zlib_error := zlib.inflate_raw(z, expected_output_size=expected_output_size)
|
||||||
if zlib_error != nil {
|
if zlib_error != nil {
|
||||||
return zlib_error
|
return zlib_error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse ZLIB stream without header.
|
// Parse ZLIB stream without header.
|
||||||
inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return
|
inflate_raw(ctx, expected_output_size=expected_output_size) or_return
|
||||||
|
|
||||||
if !raw {
|
if !raw {
|
||||||
compress.discard_to_next_byte_lsb(ctx)
|
compress.discard_to_next_byte_lsb(ctx)
|
||||||
@@ -665,7 +665,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
|
|||||||
ctx.input_data = input
|
ctx.input_data = input
|
||||||
ctx.output = buf
|
ctx.output = buf
|
||||||
|
|
||||||
return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size)
|
return inflate_from_context(&ctx, raw=raw, expected_output_size=expected_output_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
|
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
|
||||||
@@ -674,7 +674,7 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
|
|||||||
ctx.input_data = input
|
ctx.input_data = input
|
||||||
ctx.output = buf
|
ctx.output = buf
|
||||||
|
|
||||||
return inflate_raw(z=&ctx, expected_output_size=expected_output_size)
|
return inflate_raw(&ctx, expected_output_size=expected_output_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
inflate :: proc{inflate_from_context, inflate_from_byte_array}
|
inflate :: proc{inflate_from_context, inflate_from_byte_array}
|
||||||
|
|||||||
+9
-9
@@ -123,7 +123,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
|
|||||||
aprint :: proc(args: ..any, sep := " ") -> string {
|
aprint :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.builder_init(&str)
|
strings.builder_init(&str)
|
||||||
sbprint(buf=&str, args=args, sep=sep)
|
sbprint(&str, ..args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
// Creates a formatted string with a newline character at the end
|
// Creates a formatted string with a newline character at the end
|
||||||
@@ -139,7 +139,7 @@ aprint :: proc(args: ..any, sep := " ") -> string {
|
|||||||
aprintln :: proc(args: ..any, sep := " ") -> string {
|
aprintln :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.builder_init(&str)
|
strings.builder_init(&str)
|
||||||
sbprintln(buf=&str, args=args, sep=sep)
|
sbprintln(&str, ..args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
// Creates a formatted string using a format string and arguments
|
// Creates a formatted string using a format string and arguments
|
||||||
@@ -171,7 +171,7 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
|
|||||||
tprint :: proc(args: ..any, sep := " ") -> string {
|
tprint :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.builder_init(&str, context.temp_allocator)
|
strings.builder_init(&str, context.temp_allocator)
|
||||||
sbprint(buf=&str, args=args, sep=sep)
|
sbprint(&str, ..args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
// Creates a formatted string with a newline character at the end
|
// Creates a formatted string with a newline character at the end
|
||||||
@@ -187,7 +187,7 @@ tprint :: proc(args: ..any, sep := " ") -> string {
|
|||||||
tprintln :: proc(args: ..any, sep := " ") -> string {
|
tprintln :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.builder_init(&str, context.temp_allocator)
|
strings.builder_init(&str, context.temp_allocator)
|
||||||
sbprintln(buf=&str, args=args, sep=sep)
|
sbprintln(&str, ..args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
// Creates a formatted string using a format string and arguments
|
// Creates a formatted string using a format string and arguments
|
||||||
@@ -217,7 +217,7 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
|
|||||||
//
|
//
|
||||||
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
||||||
sb := strings.builder_from_bytes(buf[0:len(buf)])
|
sb := strings.builder_from_bytes(buf[0:len(buf)])
|
||||||
return sbprint(buf=&sb, args=args, sep=sep)
|
return sbprint(&sb, ..args, sep=sep)
|
||||||
}
|
}
|
||||||
// Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer.
|
// Creates a formatted string using a supplied buffer as the backing array, appends newline. Writes into the buffer.
|
||||||
//
|
//
|
||||||
@@ -230,7 +230,7 @@ bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
|||||||
//
|
//
|
||||||
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
||||||
sb := strings.builder_from_bytes(buf[0:len(buf)])
|
sb := strings.builder_from_bytes(buf[0:len(buf)])
|
||||||
return sbprintln(buf=&sb, args=args, sep=sep)
|
return sbprintln(&sb, ..args, sep=sep)
|
||||||
}
|
}
|
||||||
// Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer.
|
// Creates a formatted string using a supplied buffer as the backing array. Writes into the buffer.
|
||||||
//
|
//
|
||||||
@@ -327,7 +327,7 @@ ctprintf :: proc(format: string, args: ..any) -> cstring {
|
|||||||
// Returns: A formatted string
|
// Returns: A formatted string
|
||||||
//
|
//
|
||||||
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
||||||
wprint(w=strings.to_writer(buf), args=args, sep=sep)
|
wprint(strings.to_writer(buf), ..args, sep=sep)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
// Formats and writes to a strings.Builder buffer using the default print settings
|
// Formats and writes to a strings.Builder buffer using the default print settings
|
||||||
@@ -340,7 +340,7 @@ sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
|||||||
// Returns: The resulting formatted string
|
// Returns: The resulting formatted string
|
||||||
//
|
//
|
||||||
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
||||||
wprintln(w=strings.to_writer(buf), args=args, sep=sep)
|
wprintln(strings.to_writer(buf), ..args, sep=sep)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
// Formats and writes to a strings.Builder buffer according to the specified format string
|
// Formats and writes to a strings.Builder buffer according to the specified format string
|
||||||
@@ -353,7 +353,7 @@ sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
|||||||
// Returns: The resulting formatted string
|
// Returns: The resulting formatted string
|
||||||
//
|
//
|
||||||
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
|
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
|
||||||
wprintf(w=strings.to_writer(buf), fmt=fmt, args=args)
|
wprintf(strings.to_writer(buf), fmt, ..args)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
// Formats and writes to an io.Writer using the default print settings
|
// Formats and writes to an io.Writer using the default print settings
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
|||||||
|
|
||||||
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
|
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
|
||||||
w := bufio.writer_to_writer(&b)
|
w := bufio.writer_to_writer(&b)
|
||||||
return wprint(w=w, args=args, sep=sep)
|
return wprint(w, ..args, sep=sep)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fprintln formats using the default print settings and writes to fd
|
// fprintln formats using the default print settings and writes to fd
|
||||||
@@ -26,7 +26,7 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
|||||||
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
|
bufio.writer_init_with_buf(&b, {os.stream_from_handle(fd)}, buf[:])
|
||||||
|
|
||||||
w := bufio.writer_to_writer(&b)
|
w := bufio.writer_to_writer(&b)
|
||||||
return wprintln(w=w, args=args, sep=sep)
|
return wprintln(w, ..args, sep=sep)
|
||||||
}
|
}
|
||||||
// fprintf formats according to the specified format string and writes to fd
|
// fprintf formats according to the specified format string and writes to fd
|
||||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||||
@@ -61,15 +61,15 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print formats using the default print settings and writes to os.stdout
|
// print formats using the default print settings and writes to os.stdout
|
||||||
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
|
print :: proc(args: ..any, sep := " ") -> int { return fprint(os.stdout, ..args, sep=sep) }
|
||||||
// println formats using the default print settings and writes to os.stdout
|
// println formats using the default print settings and writes to os.stdout
|
||||||
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
|
println :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stdout, ..args, sep=sep) }
|
||||||
// printf formats according to the specified format string and writes to os.stdout
|
// printf formats according to the specified format string and writes to os.stdout
|
||||||
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
||||||
|
|
||||||
// eprint formats using the default print settings and writes to os.stderr
|
// eprint formats using the default print settings and writes to os.stderr
|
||||||
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
|
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(os.stderr, ..args, sep=sep) }
|
||||||
// eprintln formats using the default print settings and writes to os.stderr
|
// eprintln formats using the default print settings and writes to os.stderr
|
||||||
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
|
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(os.stderr, ..args, sep=sep) }
|
||||||
// eprintf formats according to the specified format string and writes to os.stderr
|
// eprintf formats according to the specified format string and writes to os.stderr
|
||||||
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
|
|||||||
case .tEXt:
|
case .tEXt:
|
||||||
ok = true
|
ok = true
|
||||||
|
|
||||||
fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator)
|
fields := bytes.split(c.data, sep=[]u8{0}, allocator=context.temp_allocator)
|
||||||
if len(fields) == 2 {
|
if len(fields) == 2 {
|
||||||
res.keyword = strings.clone(string(fields[0]))
|
res.keyword = strings.clone(string(fields[0]))
|
||||||
res.text = strings.clone(string(fields[1]))
|
res.text = strings.clone(string(fields[1]))
|
||||||
@@ -110,7 +110,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
|
|||||||
case .zTXt:
|
case .zTXt:
|
||||||
ok = true
|
ok = true
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
||||||
if len(fields) != 3 || len(fields[1]) != 0 {
|
if len(fields) != 3 || len(fields[1]) != 0 {
|
||||||
// Compression method must be 0=Deflate, which thanks to the split above turns
|
// Compression method must be 0=Deflate, which thanks to the split above turns
|
||||||
// into an empty slice
|
// into an empty slice
|
||||||
@@ -199,7 +199,7 @@ text_destroy :: proc(text: Text) {
|
|||||||
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
|
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
||||||
|
|
||||||
if len(fields[0]) < 1 || len(fields[0]) > 79 {
|
if len(fields[0]) < 1 || len(fields[0]) > 79 {
|
||||||
// Invalid profile name
|
// Invalid profile name
|
||||||
@@ -263,7 +263,7 @@ splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
|
|||||||
}
|
}
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
|
||||||
if len(fields) != 2 {
|
if len(fields) != 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -76,43 +76,43 @@ nil_logger :: proc() -> Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
debugf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
||||||
logf(level=.Debug, fmt_str=fmt_str, args=args, location=location)
|
logf(.Debug, fmt_str, ..args, location=location)
|
||||||
}
|
}
|
||||||
infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
infof :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
||||||
logf(level=.Info, fmt_str=fmt_str, args=args, location=location)
|
logf(.Info, fmt_str, ..args, location=location)
|
||||||
}
|
}
|
||||||
warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
warnf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
||||||
logf(level=.Warning, fmt_str=fmt_str, args=args, location=location)
|
logf(.Warning, fmt_str, ..args, location=location)
|
||||||
}
|
}
|
||||||
errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
errorf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
||||||
logf(level=.Error, fmt_str=fmt_str, args=args, location=location)
|
logf(.Error, fmt_str, ..args, location=location)
|
||||||
}
|
}
|
||||||
fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
fatalf :: proc(fmt_str: string, args: ..any, location := #caller_location) {
|
||||||
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location)
|
logf(.Fatal, fmt_str, ..args, location=location)
|
||||||
}
|
}
|
||||||
|
|
||||||
debug :: proc(args: ..any, sep := " ", location := #caller_location) {
|
debug :: proc(args: ..any, sep := " ", location := #caller_location) {
|
||||||
log(level=.Debug, args=args, sep=sep, location=location)
|
log(.Debug, ..args, sep=sep, location=location)
|
||||||
}
|
}
|
||||||
info :: proc(args: ..any, sep := " ", location := #caller_location) {
|
info :: proc(args: ..any, sep := " ", location := #caller_location) {
|
||||||
log(level=.Info, args=args, sep=sep, location=location)
|
log(.Info, ..args, sep=sep, location=location)
|
||||||
}
|
}
|
||||||
warn :: proc(args: ..any, sep := " ", location := #caller_location) {
|
warn :: proc(args: ..any, sep := " ", location := #caller_location) {
|
||||||
log(level=.Warning, args=args, sep=sep, location=location)
|
log(.Warning, ..args, sep=sep, location=location)
|
||||||
}
|
}
|
||||||
error :: proc(args: ..any, sep := " ", location := #caller_location) {
|
error :: proc(args: ..any, sep := " ", location := #caller_location) {
|
||||||
log(level=.Error, args=args, sep=sep, location=location)
|
log(.Error, ..args, sep=sep, location=location)
|
||||||
}
|
}
|
||||||
fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
|
fatal :: proc(args: ..any, sep := " ", location := #caller_location) {
|
||||||
log(level=.Fatal, args=args, sep=sep, location=location)
|
log(.Fatal, ..args, sep=sep, location=location)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic :: proc(args: ..any, location := #caller_location) -> ! {
|
panic :: proc(args: ..any, location := #caller_location) -> ! {
|
||||||
log(level=.Fatal, args=args, location=location)
|
log(.Fatal, ..args, location=location)
|
||||||
runtime.panic("log.panic", location)
|
runtime.panic("log.panic", location)
|
||||||
}
|
}
|
||||||
panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
|
panicf :: proc(fmt_str: string, args: ..any, location := #caller_location) -> ! {
|
||||||
logf(level=.Fatal, fmt_str=fmt_str, args=args, location=location)
|
logf(.Fatal, fmt_str, ..args, location=location)
|
||||||
runtime.panic("log.panicf", location)
|
runtime.panic("log.panicf", location)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ log :: proc(level: Level, args: ..any, sep := " ", location := #caller_location)
|
|||||||
if level < logger.lowest_level {
|
if level < logger.lowest_level {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
str := fmt.tprint(args=args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
|
str := fmt.tprint(..args, sep=sep) //NOTE(Hoej): While tprint isn't thread-safe, no logging is.
|
||||||
logger.procedure(logger.data, level, str, logger.options, location)
|
logger.procedure(logger.data, level, str, logger.options, location)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-27
@@ -38,60 +38,60 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
|
|||||||
switch mode {
|
switch mode {
|
||||||
case .Alloc:
|
case .Alloc:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)",
|
"%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)",
|
||||||
args = {la.prefix, padding, size, alignment},
|
la.prefix, padding, size, alignment,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
case .Alloc_Non_Zeroed:
|
case .Alloc_Non_Zeroed:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)",
|
"%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)",
|
||||||
args = {la.prefix, padding, size, alignment},
|
la.prefix, padding, size, alignment,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
case .Free:
|
case .Free:
|
||||||
if old_size != 0 {
|
if old_size != 0 {
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)",
|
"%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)",
|
||||||
args = {la.prefix, padding, old_memory, old_size},
|
la.prefix, padding, old_memory, old_size,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)",
|
"%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)",
|
||||||
args = {la.prefix, padding, old_memory},
|
la.prefix, padding, old_memory,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case .Free_All:
|
case .Free_All:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s<<< ALLOCATOR(mode=.Free_All)",
|
"%s%s<<< ALLOCATOR(mode=.Free_All)",
|
||||||
args = {la.prefix, padding},
|
la.prefix, padding,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
case .Resize:
|
case .Resize:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)",
|
"%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)",
|
||||||
args = {la.prefix, padding, old_memory, old_size, size, alignment},
|
la.prefix, padding, old_memory, old_size, size, alignment,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
case .Query_Features:
|
case .Query_Features:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%ALLOCATOR(mode=.Query_Features)",
|
"%s%ALLOCATOR(mode=.Query_Features)",
|
||||||
args = {la.prefix, padding},
|
la.prefix, padding,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
case .Query_Info:
|
case .Query_Info:
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%ALLOCATOR(mode=.Query_Info)",
|
"%s%ALLOCATOR(mode=.Query_Info)",
|
||||||
args = {la.prefix, padding},
|
la.prefix, padding,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -103,9 +103,9 @@ log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
|
|||||||
defer la.locked = false
|
defer la.locked = false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logf(
|
logf(
|
||||||
level=la.level,
|
la.level,
|
||||||
fmt_str = "%s%ALLOCATOR ERROR=%v",
|
"%s%ALLOCATOR ERROR=%v",
|
||||||
args = {la.prefix, padding, error},
|
la.prefix, padding, error,
|
||||||
location = location,
|
location = location,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ internal_int_write_to_ascii_file :: proc(a: ^Int, filename: string, radix := i8(
|
|||||||
len = l,
|
len = l,
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := os.write_entire_file(name=filename, data=data, truncate=true)
|
ok := os.write_entire_file(filename, data, truncate=true)
|
||||||
return nil if ok else .Cannot_Write_File
|
return nil if ok else .Cannot_Write_File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
|||||||
if arena.minimum_block_size == 0 {
|
if arena.minimum_block_size == 0 {
|
||||||
arena.minimum_block_size = DEFAULT_ARENA_STATIC_RESERVE_SIZE
|
arena.minimum_block_size = DEFAULT_ARENA_STATIC_RESERVE_SIZE
|
||||||
}
|
}
|
||||||
arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
|
arena_init_static(arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case .Buffer:
|
case .Buffer:
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_locatio
|
|||||||
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
||||||
@builtin
|
@builtin
|
||||||
pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
||||||
assert(len(array) > 0, "", loc)
|
assert(len(array) > 0, loc=loc)
|
||||||
res = array[len(array)-1]
|
res = array[len(array)-1]
|
||||||
(^Raw_Dynamic_Array)(array).len -= 1
|
(^Raw_Dynamic_Array)(array).len -= 1
|
||||||
return res
|
return res
|
||||||
@@ -136,7 +136,7 @@ pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check
|
|||||||
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic.
|
||||||
@builtin
|
@builtin
|
||||||
pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check {
|
||||||
assert(len(array) > 0, "", loc)
|
assert(len(array) > 0, loc=loc)
|
||||||
res = array[0]
|
res = array[0]
|
||||||
if len(array) > 1 {
|
if len(array) > 1 {
|
||||||
copy(array[0:], array[1:])
|
copy(array[0:], array[1:])
|
||||||
@@ -424,7 +424,7 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
|
|||||||
a := (^Raw_Dynamic_Array)(array)
|
a := (^Raw_Dynamic_Array)(array)
|
||||||
when size_of(E) != 0 {
|
when size_of(E) != 0 {
|
||||||
data := ([^]E)(a.data)
|
data := ([^]E)(a.data)
|
||||||
assert(condition=data != nil, loc=loc)
|
assert(data != nil, loc=loc)
|
||||||
data[a.len] = arg
|
data[a.len] = arg
|
||||||
}
|
}
|
||||||
a.len += 1
|
a.len += 1
|
||||||
@@ -459,7 +459,7 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
|
|||||||
a := (^Raw_Dynamic_Array)(array)
|
a := (^Raw_Dynamic_Array)(array)
|
||||||
when size_of(E) != 0 {
|
when size_of(E) != 0 {
|
||||||
data := ([^]E)(a.data)
|
data := ([^]E)(a.data)
|
||||||
assert(condition=data != nil, loc=loc)
|
assert(data != nil, loc=loc)
|
||||||
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
|
intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len)
|
||||||
}
|
}
|
||||||
a.len += arg_len
|
a.len += arg_len
|
||||||
@@ -472,7 +472,7 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
|
|||||||
@builtin
|
@builtin
|
||||||
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
args := transmute([]E)arg
|
args := transmute([]E)arg
|
||||||
return append_elems(array=array, args=args, loc=loc)
|
return append_elems(array, ..args, loc=loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -481,7 +481,7 @@ append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #ca
|
|||||||
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||||
n_arg: int
|
n_arg: int
|
||||||
for arg in args {
|
for arg in args {
|
||||||
n_arg, err = append(array = array, args = transmute([]E)(arg), loc = loc)
|
n_arg, err = append(array, ..transmute([]E)(arg), loc=loc)
|
||||||
n += n_arg
|
n += n_arg
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
|
handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Index ")
|
print_string(" Index ")
|
||||||
print_i64(i64(index))
|
print_i64(i64(index))
|
||||||
@@ -83,7 +83,7 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
|
handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Invalid dynamic array indices ")
|
print_string(" Invalid dynamic array indices ")
|
||||||
print_i64(i64(low))
|
print_i64(i64(low))
|
||||||
@@ -104,7 +104,7 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
|
handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Matrix indices [")
|
print_string(" Matrix indices [")
|
||||||
print_i64(i64(row_index))
|
print_i64(i64(row_index))
|
||||||
@@ -128,7 +128,7 @@ when ODIN_NO_RTTI {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32) {
|
handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Invalid type assertion\n")
|
print_string(" Invalid type assertion\n")
|
||||||
type_assertion_trap()
|
type_assertion_trap()
|
||||||
@@ -141,7 +141,7 @@ when ODIN_NO_RTTI {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32) {
|
handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Invalid type assertion\n")
|
print_string(" Invalid type assertion\n")
|
||||||
type_assertion_trap()
|
type_assertion_trap()
|
||||||
@@ -154,7 +154,7 @@ when ODIN_NO_RTTI {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) {
|
handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) -> ! {
|
||||||
print_caller_location(Source_Code_Location{file, line, column, ""})
|
print_caller_location(Source_Code_Location{file, line, column, ""})
|
||||||
print_string(" Invalid type assertion from ")
|
print_string(" Invalid type assertion from ")
|
||||||
print_typeid(from)
|
print_typeid(from)
|
||||||
@@ -199,7 +199,7 @@ when ODIN_NO_RTTI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
|
handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! {
|
||||||
|
|
||||||
actual := variant_type(from, from_data)
|
actual := variant_type(from, from_data)
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) {
|
handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) -> ! {
|
||||||
print_caller_location(loc)
|
print_caller_location(loc)
|
||||||
print_string(" Invalid slice length for make: ")
|
print_string(" Invalid slice length for make: ")
|
||||||
print_i64(i64(len))
|
print_i64(i64(len))
|
||||||
@@ -240,7 +240,7 @@ make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) {
|
handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) -> ! {
|
||||||
print_caller_location(loc)
|
print_caller_location(loc)
|
||||||
print_string(" Invalid dynamic array parameters for make: ")
|
print_string(" Invalid dynamic array parameters for make: ")
|
||||||
print_i64(i64(len))
|
print_i64(i64(len))
|
||||||
@@ -257,7 +257,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
@(cold)
|
@(cold)
|
||||||
handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) {
|
handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) -> ! {
|
||||||
print_caller_location(loc)
|
print_caller_location(loc)
|
||||||
print_string(" Invalid map capacity for make: ")
|
print_string(" Invalid map capacity for make: ")
|
||||||
print_i64(i64(cap))
|
print_i64(i64(cap))
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ run_internal_test :: proc(t: ^T, it: Internal_Test) {
|
|||||||
global_exception_handler = win32.AddVectoredExceptionHandler(0, exception_handler_proc)
|
global_exception_handler = win32.AddVectoredExceptionHandler(0, exception_handler_proc)
|
||||||
|
|
||||||
context.assertion_failure_proc = proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! {
|
context.assertion_failure_proc = proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! {
|
||||||
errorf(t=global_current_t, format="%s %s", args={prefix, message}, loc=loc)
|
errorf(global_current_t, "%s %s", prefix, message, loc=loc)
|
||||||
intrinsics.trap()
|
intrinsics.trap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,15 +46,15 @@ errorf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fail :: proc(t: ^T, loc := #caller_location) {
|
fail :: proc(t: ^T, loc := #caller_location) {
|
||||||
error(t=t, args={"FAIL"}, loc=loc)
|
error(t, "FAIL", loc=loc)
|
||||||
t.error_count += 1
|
t.error_count += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fail_now :: proc(t: ^T, msg := "", loc := #caller_location) {
|
fail_now :: proc(t: ^T, msg := "", loc := #caller_location) {
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
error(t=t, args={"FAIL:", msg}, loc=loc)
|
error(t, "FAIL:", msg, loc=loc)
|
||||||
} else {
|
} else {
|
||||||
error(t=t, args={"FAIL"}, loc=loc)
|
error(t, "FAIL", loc=loc)
|
||||||
}
|
}
|
||||||
t.error_count += 1
|
t.error_count += 1
|
||||||
if t._fail_now != nil {
|
if t._fail_now != nil {
|
||||||
@@ -84,14 +84,14 @@ cleanup :: proc(t: ^T, procedure: proc(rawptr), user_data: rawptr) {
|
|||||||
|
|
||||||
expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bool {
|
expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bool {
|
||||||
if !ok {
|
if !ok {
|
||||||
error(t=t, args={msg}, loc=loc)
|
error(t, msg, loc=loc)
|
||||||
}
|
}
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> bool where intrinsics.type_is_comparable(T) {
|
expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> bool where intrinsics.type_is_comparable(T) {
|
||||||
ok := value == expected
|
ok := value == expected
|
||||||
if !ok {
|
if !ok {
|
||||||
errorf(t=t, format="expected %v, got %v", args={expected, value}, loc=loc)
|
errorf(t, "expected %v, got %v", expected, value, loc=loc)
|
||||||
}
|
}
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ set_cell_alignment :: proc(tbl: ^Table, row, col: int, alignment: Cell_Alignment
|
|||||||
|
|
||||||
format :: proc(tbl: ^Table, _fmt: string, args: ..any, loc := #caller_location) -> string {
|
format :: proc(tbl: ^Table, _fmt: string, args: ..any, loc := #caller_location) -> string {
|
||||||
context.allocator = tbl.format_allocator
|
context.allocator = tbl.format_allocator
|
||||||
return fmt.aprintf(fmt = _fmt, args = args)
|
return fmt.aprintf(_fmt, ..args)
|
||||||
}
|
}
|
||||||
|
|
||||||
header :: proc(tbl: ^Table, values: ..any, loc := #caller_location) {
|
header :: proc(tbl: ^Table, values: ..any, loc := #caller_location) {
|
||||||
|
|||||||
@@ -1175,13 +1175,13 @@ threading_example :: proc() {
|
|||||||
N :: 3
|
N :: 3
|
||||||
|
|
||||||
pool: thread.Pool
|
pool: thread.Pool
|
||||||
thread.pool_init(pool=&pool, thread_count=N, allocator=context.allocator)
|
thread.pool_init(&pool, allocator=context.allocator, thread_count=N)
|
||||||
defer thread.pool_destroy(&pool)
|
defer thread.pool_destroy(&pool)
|
||||||
|
|
||||||
|
|
||||||
for i in 0..<30 {
|
for i in 0..<30 {
|
||||||
// be mindful of the allocator used for tasks. The allocator needs to be thread safe, or be owned by the task for exclusive use
|
// be mindful of the allocator used for tasks. The allocator needs to be thread safe, or be owned by the task for exclusive use
|
||||||
thread.pool_add_task(pool=&pool, procedure=task_proc, data=nil, user_index=i, allocator=context.allocator)
|
thread.pool_add_task(&pool, allocator=context.allocator, procedure=task_proc, data=nil, user_index=i)
|
||||||
}
|
}
|
||||||
|
|
||||||
thread.pool_start(&pool)
|
thread.pool_start(&pool)
|
||||||
|
|||||||
+3
-1
@@ -80,7 +80,9 @@ gb_internal Slice<T> slice_make(gbAllocator const &allocator, isize count) {
|
|||||||
GB_ASSERT(count >= 0);
|
GB_ASSERT(count >= 0);
|
||||||
Slice<T> s = {};
|
Slice<T> s = {};
|
||||||
s.data = gb_alloc_array(allocator, T, count);
|
s.data = gb_alloc_array(allocator, T, count);
|
||||||
GB_ASSERT(s.data != nullptr);
|
if (count > 0) {
|
||||||
|
GB_ASSERT(s.data != nullptr);
|
||||||
|
}
|
||||||
s.count = count;
|
s.count = count;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
+1021
-908
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -2207,7 +2207,13 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) {
|
|||||||
} else if (operands.count != result_count) {
|
} else if (operands.count != result_count) {
|
||||||
// Ignore error message as it has most likely already been reported
|
// Ignore error message as it has most likely already been reported
|
||||||
if (all_operands_valid(operands)) {
|
if (all_operands_valid(operands)) {
|
||||||
error(node, "Expected %td return values, got %td", result_count, operands.count);
|
if (operands.count == 1) {
|
||||||
|
gbString t = type_to_string(operands[0].type);
|
||||||
|
error(node, "Expected %td return values, got %td (%s)", result_count, operands.count, t);
|
||||||
|
gb_string_free(t);
|
||||||
|
} else {
|
||||||
|
error(node, "Expected %td return values, got %td", result_count, operands.count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (isize i = 0; i < result_count; i++) {
|
for (isize i = 0; i < result_count; i++) {
|
||||||
|
|||||||
+2
-3
@@ -1416,7 +1416,7 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> *operands) {
|
gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is_variadic_, isize *variadic_index_, bool *success_, isize *specialization_count_, Array<Operand> const *operands) {
|
||||||
if (_params == nullptr) {
|
if (_params == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1664,7 +1664,6 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
|
|||||||
ExactValue poly_const = {};
|
ExactValue poly_const = {};
|
||||||
|
|
||||||
if (operands != nullptr && variables.count < operands->count) {
|
if (operands != nullptr && variables.count < operands->count) {
|
||||||
|
|
||||||
Operand op = (*operands)[variables.count];
|
Operand op = (*operands)[variables.count];
|
||||||
if (op.expr == nullptr) {
|
if (op.expr == nullptr) {
|
||||||
// NOTE(bill): 2019-03-30
|
// NOTE(bill): 2019-03-30
|
||||||
@@ -1967,7 +1966,7 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res
|
|||||||
|
|
||||||
|
|
||||||
// NOTE(bill): 'operands' is for generating non generic procedure type
|
// NOTE(bill): 'operands' is for generating non generic procedure type
|
||||||
gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array<Operand> *operands) {
|
gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array<Operand> const *operands) {
|
||||||
ast_node(pt, ProcType, proc_type_node);
|
ast_node(pt, ProcType, proc_type_node);
|
||||||
|
|
||||||
if (ctx->polymorphic_scope == nullptr && ctx->allow_polymorphic_types) {
|
if (ctx->polymorphic_scope == nullptr && ctx->allow_polymorphic_types) {
|
||||||
|
|||||||
+19
-12
@@ -265,7 +265,8 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
|
|||||||
defer (gb_string_free(the_line));
|
defer (gb_string_free(the_line));
|
||||||
|
|
||||||
if (the_line != nullptr) {
|
if (the_line != nullptr) {
|
||||||
String line = make_string(cast(u8 const *)the_line, gb_string_length(the_line));
|
char const *line_text = the_line;
|
||||||
|
isize line_len = gb_string_length(the_line);
|
||||||
|
|
||||||
// TODO(bill): This assumes ASCII
|
// TODO(bill): This assumes ASCII
|
||||||
|
|
||||||
@@ -285,21 +286,27 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
|
|||||||
|
|
||||||
isize squiggle_extra = 0;
|
isize squiggle_extra = 0;
|
||||||
|
|
||||||
if (line.len > MAX_LINE_LENGTH_PADDED) {
|
if (line_len > MAX_LINE_LENGTH_PADDED) {
|
||||||
i32 left = MAX_TAB_WIDTH;
|
i32 left = MAX_TAB_WIDTH;
|
||||||
line.text += offset-left;
|
if (offset > 0) {
|
||||||
line.len -= offset-left;
|
line_text += offset-left;
|
||||||
offset = left+MAX_TAB_WIDTH/2;
|
line_len -= offset-left;
|
||||||
if (line.len > MAX_LINE_LENGTH_PADDED) {
|
offset = left+MAX_TAB_WIDTH/2;
|
||||||
line.len = MAX_LINE_LENGTH_PADDED;
|
}
|
||||||
if (error_length > line.len-left) {
|
if (line_len > MAX_LINE_LENGTH_PADDED) {
|
||||||
error_length = cast(i32)line.len - left;
|
line_len = MAX_LINE_LENGTH_PADDED;
|
||||||
|
if (error_length > line_len-left) {
|
||||||
|
error_length = cast(i32)line_len - left;
|
||||||
squiggle_extra = 1;
|
squiggle_extra = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error_out("... %.*s ...", LIT(line));
|
if (offset > 0) {
|
||||||
|
error_out("... %.*s ...", cast(i32)line_len, line_text);
|
||||||
|
} else {
|
||||||
|
error_out("%.*s ...", cast(i32)line_len, line_text);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error_out("%.*s", LIT(line));
|
error_out("%.*s", cast(i32)line_len, line_text);
|
||||||
}
|
}
|
||||||
error_out("\n\t");
|
error_out("\n\t");
|
||||||
|
|
||||||
@@ -312,7 +319,7 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
|
|||||||
error_out("^");
|
error_out("^");
|
||||||
if (end.file_id == pos.file_id) {
|
if (end.file_id == pos.file_id) {
|
||||||
if (end.line > pos.line) {
|
if (end.line > pos.line) {
|
||||||
for (i32 i = offset; i < line.len; i++) {
|
for (i32 i = offset; i < line_len; i++) {
|
||||||
error_out("~");
|
error_out("~");
|
||||||
}
|
}
|
||||||
} else if (end.line == pos.line && end.column > pos.column) {
|
} else if (end.line == pos.line && end.column > pos.column) {
|
||||||
|
|||||||
+33
-6
@@ -3299,12 +3299,39 @@ void const *gb_memrchr(void const *data, u8 c, isize n) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
gb_inline void *gb_alloc_align (gbAllocator a, isize size, isize alignment) { return a.proc(a.data, gbAllocation_Alloc, size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
gb_inline void *gb_alloc_align (gbAllocator a, isize size, isize alignment) {
|
||||||
gb_inline void *gb_alloc (gbAllocator a, isize size) { return gb_alloc_align(a, size, GB_DEFAULT_MEMORY_ALIGNMENT); }
|
if (size == 0) {
|
||||||
gb_inline void gb_free (gbAllocator a, void *ptr) { if (ptr != NULL) a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
return NULL;
|
||||||
gb_inline void gb_free_all (gbAllocator a) { a.proc(a.data, gbAllocation_FreeAll, 0, 0, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
}
|
||||||
gb_inline void *gb_resize (gbAllocator a, void *ptr, isize old_size, isize new_size) { return gb_resize_align(a, ptr, old_size, new_size, GB_DEFAULT_MEMORY_ALIGNMENT); }
|
return a.proc(a.data, gbAllocation_Alloc, size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
gb_inline void *gb_resize_align(gbAllocator a, void *ptr, isize old_size, isize new_size, isize alignment) { return a.proc(a.data, gbAllocation_Resize, new_size, alignment, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS); }
|
}
|
||||||
|
gb_inline void *gb_alloc(gbAllocator a, isize size) {
|
||||||
|
return gb_alloc_align(a, size, GB_DEFAULT_MEMORY_ALIGNMENT);
|
||||||
|
}
|
||||||
|
gb_inline void gb_free(gbAllocator a, void *ptr) {
|
||||||
|
if (ptr != NULL) {
|
||||||
|
a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gb_inline void gb_free_all(gbAllocator a) {
|
||||||
|
a.proc(a.data, gbAllocation_FreeAll, 0, 0, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
|
}
|
||||||
|
gb_inline void *gb_resize(gbAllocator a, void *ptr, isize old_size, isize new_size) {
|
||||||
|
return gb_resize_align(a, ptr, old_size, new_size, GB_DEFAULT_MEMORY_ALIGNMENT);
|
||||||
|
}
|
||||||
|
gb_inline void *gb_resize_align(gbAllocator a, void *ptr, isize old_size, isize new_size, isize alignment) {
|
||||||
|
if (new_size == 0) {
|
||||||
|
if (ptr != NULL) {
|
||||||
|
return a.proc(a.data, gbAllocation_Free, 0, 0, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
} else if (ptr == NULL) {
|
||||||
|
return a.proc(a.data, gbAllocation_Alloc, new_size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
|
} else if (old_size == new_size && ((uintptr)ptr % (uintptr)alignment) == 0) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
return a.proc(a.data, gbAllocation_Resize, new_size, alignment, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS);
|
||||||
|
}
|
||||||
|
|
||||||
gb_inline void *gb_alloc_copy (gbAllocator a, void const *src, isize size) {
|
gb_inline void *gb_alloc_copy (gbAllocator a, void const *src, isize size) {
|
||||||
return gb_memcopy(gb_alloc(a, size), src, size);
|
return gb_memcopy(gb_alloc(a, size), src, size);
|
||||||
|
|||||||
+142
-226
@@ -1160,7 +1160,13 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity **found = map_get(&p->module->procedure_values, value.value);
|
LLVMValueRef the_proc_value = value.value;
|
||||||
|
|
||||||
|
if (LLVMIsAConstantExpr(the_proc_value)) {
|
||||||
|
// NOTE(bill): it's a bit cast
|
||||||
|
the_proc_value = LLVMGetOperand(the_proc_value, 0);
|
||||||
|
}
|
||||||
|
Entity **found = map_get(&p->module->procedure_values, the_proc_value);
|
||||||
if (found != nullptr) {
|
if (found != nullptr) {
|
||||||
Entity *e = *found;
|
Entity *e = *found;
|
||||||
if (e != nullptr && entity_has_deferred_procedure(e)) {
|
if (e != nullptr && entity_has_deferred_procedure(e)) {
|
||||||
@@ -3145,6 +3151,18 @@ gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gb_internal void lb_add_values_to_array(lbProcedure *p, Array<lbValue> *args, lbValue value) {
|
||||||
|
if (is_type_tuple(value.type)) {
|
||||||
|
for_array(i, value.type->Tuple.variables) {
|
||||||
|
lbValue sub_value = lb_emit_struct_ev(p, value, cast(i32)i);
|
||||||
|
array_add(args, sub_value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
array_add(args, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
||||||
lbModule *m = p->module;
|
lbModule *m = p->module;
|
||||||
|
|
||||||
@@ -3219,245 +3237,143 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) {
|
|||||||
GB_ASSERT(proc_type_->kind == Type_Proc);
|
GB_ASSERT(proc_type_->kind == Type_Proc);
|
||||||
TypeProc *pt = &proc_type_->Proc;
|
TypeProc *pt = &proc_type_->Proc;
|
||||||
|
|
||||||
if (is_call_expr_field_value(ce)) {
|
GB_ASSERT(ce->split_args != nullptr);
|
||||||
auto args = array_make<lbValue>(permanent_allocator(), pt->param_count);
|
|
||||||
|
|
||||||
for_array(arg_index, ce->args) {
|
auto args = array_make<lbValue>(permanent_allocator(), 0, pt->param_count);
|
||||||
Ast *arg = ce->args[arg_index];
|
|
||||||
ast_node(fv, FieldValue, arg);
|
|
||||||
GB_ASSERT(fv->field->kind == Ast_Ident);
|
|
||||||
String name = fv->field->Ident.token.string;
|
|
||||||
isize index = lookup_procedure_parameter(pt, name);
|
|
||||||
GB_ASSERT(index >= 0);
|
|
||||||
TypeAndValue tav = type_and_value_of_expr(fv->value);
|
|
||||||
if (tav.mode == Addressing_Type) {
|
|
||||||
args[index] = lb_const_nil(m, tav.type);
|
|
||||||
} else {
|
|
||||||
args[index] = lb_build_expr(p, fv->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TypeTuple *params = &pt->params->Tuple;
|
|
||||||
for (isize i = 0; i < args.count; i++) {
|
|
||||||
Entity *e = params->variables[i];
|
|
||||||
if (e->kind == Entity_TypeName) {
|
|
||||||
args[i] = lb_const_nil(m, e->type);
|
|
||||||
} else if (e->kind == Entity_Constant) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
|
||||||
if (args[i].value == nullptr) {
|
|
||||||
args[i] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
|
|
||||||
} else if (is_type_typeid(e->type) && !is_type_typeid(args[i].type)) {
|
|
||||||
args[i] = lb_typeid(p->module, args[i].type);
|
|
||||||
} else {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (isize i = 0; i < args.count; i++) {
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
Entity *e = params->variables[i];
|
|
||||||
if (args[i].type == nullptr) {
|
|
||||||
continue;
|
|
||||||
} else if (is_type_untyped_uninit(args[i].type)) {
|
|
||||||
args[i] = lb_const_undef(m, e->type);
|
|
||||||
} else if (is_type_untyped_nil(args[i].type)) {
|
|
||||||
args[i] = lb_const_nil(m, e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lb_emit_call(p, value, args, ce->inlining);
|
|
||||||
}
|
|
||||||
|
|
||||||
isize arg_index = 0;
|
|
||||||
|
|
||||||
isize arg_count = 0;
|
|
||||||
for_array(i, ce->args) {
|
|
||||||
Ast *arg = ce->args[i];
|
|
||||||
TypeAndValue tav = type_and_value_of_expr(arg);
|
|
||||||
GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s %d", expr_to_string(arg), expr_to_string(expr), tav.mode);
|
|
||||||
GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
|
|
||||||
Type *at = tav.type;
|
|
||||||
if (is_type_tuple(at)) {
|
|
||||||
arg_count += at->Tuple.variables.count;
|
|
||||||
} else {
|
|
||||||
arg_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isize param_count = 0;
|
|
||||||
if (pt->params) {
|
|
||||||
GB_ASSERT(pt->params->kind == Type_Tuple);
|
|
||||||
param_count = pt->params->Tuple.variables.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto args = array_make<lbValue>(permanent_allocator(), cast(isize)gb_max(param_count, arg_count));
|
|
||||||
isize variadic_index = pt->variadic_index;
|
|
||||||
bool variadic = pt->variadic && variadic_index >= 0;
|
|
||||||
bool vari_expand = ce->ellipsis.pos.line != 0;
|
|
||||||
bool is_c_vararg = pt->c_vararg;
|
bool is_c_vararg = pt->c_vararg;
|
||||||
|
|
||||||
String proc_name = {};
|
for_array(i, ce->split_args->positional) {
|
||||||
if (p->entity != nullptr) {
|
Entity *e = pt->params->Tuple.variables[i];
|
||||||
proc_name = p->entity->token.string;
|
if (e->kind == Entity_TypeName) {
|
||||||
|
array_add(&args, lb_const_nil(p->module, e->type));
|
||||||
|
continue;
|
||||||
|
} else if (e->kind == Entity_Constant) {
|
||||||
|
array_add(&args, lb_const_value(p->module, e->type, e->Constant.value));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
|
if (pt->variadic && pt->variadic_index == i) {
|
||||||
|
lbValue variadic_args = lb_const_nil(p->module, e->type);
|
||||||
|
auto variadic = slice(ce->split_args->positional, pt->variadic_index, ce->split_args->positional.count);
|
||||||
|
if (variadic.count != 0) {
|
||||||
|
// variadic call argument generation
|
||||||
|
Type *slice_type = e->type;
|
||||||
|
GB_ASSERT(slice_type->kind == Type_Slice);
|
||||||
|
|
||||||
|
if (is_c_vararg) {
|
||||||
|
GB_ASSERT(!vari_expand);
|
||||||
|
|
||||||
|
Type *elem_type = slice_type->Slice.elem;
|
||||||
|
|
||||||
|
for (Ast *var_arg : variadic) {
|
||||||
|
lbValue arg = lb_build_expr(p, var_arg);
|
||||||
|
if (is_type_any(elem_type)) {
|
||||||
|
array_add(&args, lb_emit_conv(p, arg, default_type(arg.type)));
|
||||||
|
} else {
|
||||||
|
array_add(&args, lb_emit_conv(p, arg, elem_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (vari_expand) {
|
||||||
|
GB_ASSERT(variadic.count == 1);
|
||||||
|
variadic_args = lb_build_expr(p, variadic[0]);
|
||||||
|
variadic_args = lb_emit_conv(p, variadic_args, slice_type);
|
||||||
|
} else {
|
||||||
|
Type *elem_type = slice_type->Slice.elem;
|
||||||
|
|
||||||
|
auto var_args = array_make<lbValue>(heap_allocator(), 0, variadic.count);
|
||||||
|
defer (array_free(&var_args));
|
||||||
|
for (Ast *var_arg : variadic) {
|
||||||
|
lbValue v = lb_build_expr(p, var_arg);
|
||||||
|
lb_add_values_to_array(p, &var_args, v);
|
||||||
|
}
|
||||||
|
isize slice_len = var_args.count;
|
||||||
|
if (slice_len > 0) {
|
||||||
|
lbAddr slice = lb_add_local_generated(p, slice_type, true);
|
||||||
|
lbAddr base_array = lb_add_local_generated(p, alloc_type_array(elem_type, slice_len), true);
|
||||||
|
|
||||||
|
for (isize i = 0; i < var_args.count; i++) {
|
||||||
|
lbValue addr = lb_emit_array_epi(p, base_array.addr, cast(i32)i);
|
||||||
|
lbValue var_arg = var_args[i];
|
||||||
|
var_arg = lb_emit_conv(p, var_arg, elem_type);
|
||||||
|
lb_emit_store(p, addr, var_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbValue base_elem = lb_emit_array_epi(p, base_array.addr, 0);
|
||||||
|
lbValue len = lb_const_int(p->module, t_int, slice_len);
|
||||||
|
lb_fill_slice(p, slice, base_elem, len);
|
||||||
|
|
||||||
|
variadic_args = lb_addr_load(p, slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_add(&args, variadic_args);
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lbValue value = lb_build_expr(p, ce->split_args->positional[i]);
|
||||||
|
lb_add_values_to_array(p, &args, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_c_vararg) {
|
||||||
|
array_resize(&args, pt->param_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Ast *arg : ce->split_args->named) {
|
||||||
|
ast_node(fv, FieldValue, arg);
|
||||||
|
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||||
|
String name = fv->field->Ident.token.string;
|
||||||
|
gb_unused(name);
|
||||||
|
isize param_index = lookup_procedure_parameter(pt, name);
|
||||||
|
GB_ASSERT(param_index >= 0);
|
||||||
|
|
||||||
|
lbValue value = lb_build_expr(p, fv->value);
|
||||||
|
GB_ASSERT(!is_type_tuple(value.type));
|
||||||
|
args[param_index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
TokenPos pos = ast_token(ce->proc).pos;
|
TokenPos pos = ast_token(ce->proc).pos;
|
||||||
|
|
||||||
TypeTuple *param_tuple = nullptr;
|
|
||||||
if (pt->params) {
|
|
||||||
GB_ASSERT(pt->params->kind == Type_Tuple);
|
|
||||||
param_tuple = &pt->params->Tuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
if (pt->params != nullptr) {
|
||||||
Ast *arg = ce->args[i];
|
GB_ASSERT(args.count >= pt->params->Tuple.variables.count);
|
||||||
TypeAndValue arg_tv = type_and_value_of_expr(arg);
|
for_array(arg_index, pt->params->Tuple.variables) {
|
||||||
if (arg_tv.mode == Addressing_Type) {
|
Entity *e = pt->params->Tuple.variables[arg_index];
|
||||||
args[arg_index++] = lb_const_nil(m, arg_tv.type);
|
if (pt->variadic && arg_index == pt->variadic_index) {
|
||||||
} else {
|
if (!is_c_vararg && args[arg_index].value == 0) {
|
||||||
lbValue a = lb_build_expr(p, arg);
|
args[arg_index] = lb_const_nil(p->module, e->type);
|
||||||
Type *at = a.type;
|
|
||||||
if (at->kind == Type_Tuple) {
|
|
||||||
lbTupleFix *tf = map_get(&p->tuple_fix_map, a.value);
|
|
||||||
if (tf) {
|
|
||||||
for_array(j, tf->values) {
|
|
||||||
args[arg_index++] = tf->values[j];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for_array(j, at->Tuple.variables) {
|
|
||||||
lbValue v = lb_emit_struct_ev(p, a, cast(i32)j);
|
|
||||||
args[arg_index++] = v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
args[arg_index++] = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (param_count > 0) {
|
|
||||||
GB_ASSERT_MSG(pt->params != nullptr, "%s %td", expr_to_string(expr), pt->param_count);
|
|
||||||
GB_ASSERT(param_count < 1000000);
|
|
||||||
|
|
||||||
if (arg_count < param_count) {
|
|
||||||
isize end = cast(isize)param_count;
|
|
||||||
if (variadic) {
|
|
||||||
end = variadic_index;
|
|
||||||
}
|
|
||||||
while (arg_index < end) {
|
|
||||||
Entity *e = param_tuple->variables[arg_index];
|
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
|
||||||
args[arg_index++] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_c_vararg) {
|
|
||||||
GB_ASSERT(variadic);
|
|
||||||
GB_ASSERT(!vari_expand);
|
|
||||||
isize i = 0;
|
|
||||||
for (; i < variadic_index; i++) {
|
|
||||||
Entity *e = param_tuple->variables[i];
|
|
||||||
if (e->kind == Entity_Variable) {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Type *variadic_type = param_tuple->variables[i]->type;
|
|
||||||
GB_ASSERT(is_type_slice(variadic_type));
|
|
||||||
variadic_type = base_type(variadic_type)->Slice.elem;
|
|
||||||
if (!is_type_any(variadic_type)) {
|
|
||||||
for (; i < arg_count; i++) {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], variadic_type);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (; i < arg_count; i++) {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], default_type(args[i].type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (variadic) {
|
|
||||||
isize i = 0;
|
|
||||||
for (; i < variadic_index; i++) {
|
|
||||||
Entity *e = param_tuple->variables[i];
|
|
||||||
if (e->kind == Entity_Variable) {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!vari_expand) {
|
|
||||||
Type *variadic_type = param_tuple->variables[i]->type;
|
|
||||||
GB_ASSERT(is_type_slice(variadic_type));
|
|
||||||
variadic_type = base_type(variadic_type)->Slice.elem;
|
|
||||||
for (; i < arg_count; i++) {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], variadic_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (isize i = 0; i < param_count; i++) {
|
|
||||||
Entity *e = param_tuple->variables[i];
|
|
||||||
if (e->kind == Entity_Variable) {
|
|
||||||
if (args[i].value == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
GB_ASSERT_MSG(args[i].value != nullptr, "%.*s", LIT(e->token.string));
|
|
||||||
if (is_type_typeid(e->type) && !is_type_typeid(args[i].type)) {
|
|
||||||
GB_ASSERT(LLVMIsNull(args[i].value));
|
|
||||||
args[i] = lb_typeid(p->module, args[i].type);
|
|
||||||
} else {
|
|
||||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variadic && !vari_expand && !is_c_vararg) {
|
|
||||||
// variadic call argument generation
|
|
||||||
Type *slice_type = param_tuple->variables[variadic_index]->type;
|
|
||||||
Type *elem_type = base_type(slice_type)->Slice.elem;
|
|
||||||
lbAddr slice = lb_add_local_generated(p, slice_type, true);
|
|
||||||
isize slice_len = arg_count+1 - (variadic_index+1);
|
|
||||||
|
|
||||||
if (slice_len > 0) {
|
|
||||||
lbAddr base_array = lb_add_local_generated(p, alloc_type_array(elem_type, slice_len), true);
|
|
||||||
|
|
||||||
for (isize i = variadic_index, j = 0; i < arg_count; i++, j++) {
|
|
||||||
lbValue addr = lb_emit_array_epi(p, base_array.addr, cast(i32)j);
|
|
||||||
lb_emit_store(p, addr, args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
lbValue base_elem = lb_emit_array_epi(p, base_array.addr, 0);
|
|
||||||
lbValue len = lb_const_int(m, t_int, slice_len);
|
|
||||||
lb_fill_slice(p, slice, base_elem, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
arg_count = param_count;
|
|
||||||
args[variadic_index] = lb_addr_load(p, slice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variadic && variadic_index+1 < param_count) {
|
|
||||||
for (isize i = variadic_index+1; i < param_count; i++) {
|
|
||||||
Entity *e = param_tuple->variables[i];
|
|
||||||
args[i] = lb_handle_param_value(p, e->type, e->Variable.param_value, ast_token(expr).pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isize final_count = param_count;
|
|
||||||
if (is_c_vararg) {
|
|
||||||
final_count = arg_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param_tuple != nullptr) {
|
|
||||||
for (isize i = 0; i < gb_min(args.count, param_tuple->variables.count); i++) {
|
|
||||||
Entity *e = param_tuple->variables[i];
|
|
||||||
if (args[i].type == nullptr) {
|
|
||||||
continue;
|
continue;
|
||||||
} else if (is_type_untyped_uninit(args[i].type)) {
|
}
|
||||||
args[i] = lb_const_undef(m, e->type);
|
|
||||||
} else if (is_type_untyped_nil(args[i].type)) {
|
lbValue arg = args[arg_index];
|
||||||
args[i] = lb_const_nil(m, e->type);
|
if (arg.value == nullptr) {
|
||||||
|
switch (e->kind) {
|
||||||
|
case Entity_TypeName:
|
||||||
|
args[arg_index] = lb_const_nil(p->module, e->type);
|
||||||
|
break;
|
||||||
|
case Entity_Variable:
|
||||||
|
args[arg_index] = lb_handle_param_value(p, e->type, e->Variable.param_value, pos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entity_Constant:
|
||||||
|
args[arg_index] = lb_const_value(p->module, e->type, e->Constant.value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GB_PANIC("Unknown entity kind %.*s\n", LIT(entity_strings[e->kind]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args[arg_index] = lb_emit_conv(p, arg, e->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isize final_count = is_c_vararg ? args.count : pt->param_count;
|
||||||
auto call_args = array_slice(args, 0, final_count);
|
auto call_args = array_slice(args, 0, final_count);
|
||||||
return lb_emit_call(p, value, call_args, ce->inlining);
|
return lb_emit_call(p, value, call_args, ce->inlining);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -2752,9 +2752,9 @@ gb_internal Ast *parse_call_expr(AstFile *f, Ast *operand) {
|
|||||||
|
|
||||||
open_paren = expect_token(f, Token_OpenParen);
|
open_paren = expect_token(f, Token_OpenParen);
|
||||||
|
|
||||||
|
bool seen_ellipsis = false;
|
||||||
while (f->curr_token.kind != Token_CloseParen &&
|
while (f->curr_token.kind != Token_CloseParen &&
|
||||||
f->curr_token.kind != Token_EOF &&
|
f->curr_token.kind != Token_EOF) {
|
||||||
ellipsis.pos.line == 0) {
|
|
||||||
if (f->curr_token.kind == Token_Comma) {
|
if (f->curr_token.kind == Token_Comma) {
|
||||||
syntax_error(f->curr_token, "Expected an expression not ,");
|
syntax_error(f->curr_token, "Expected an expression not ,");
|
||||||
} else if (f->curr_token.kind == Token_Eq) {
|
} else if (f->curr_token.kind == Token_Eq) {
|
||||||
@@ -2777,11 +2777,15 @@ gb_internal Ast *parse_call_expr(AstFile *f, Ast *operand) {
|
|||||||
|
|
||||||
Ast *value = parse_value(f);
|
Ast *value = parse_value(f);
|
||||||
arg = ast_field_value(f, arg, value, eq);
|
arg = ast_field_value(f, arg, value, eq);
|
||||||
|
} else if (seen_ellipsis) {
|
||||||
|
syntax_error(arg, "Positional arguments are not allowed after '..'");
|
||||||
}
|
}
|
||||||
array_add(&args, arg);
|
array_add(&args, arg);
|
||||||
|
|
||||||
|
if (ellipsis.pos.line != 0) {
|
||||||
|
seen_ellipsis = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!allow_field_separator(f)) {
|
if (!allow_field_separator(f)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,6 +367,11 @@ gb_global char const *union_type_kind_strings[UnionType_COUNT] = {
|
|||||||
"#shared_nil",
|
"#shared_nil",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstSplitArgs {
|
||||||
|
Slice<Ast *> positional;
|
||||||
|
Slice<Ast *> named;
|
||||||
|
};
|
||||||
|
|
||||||
#define AST_KINDS \
|
#define AST_KINDS \
|
||||||
AST_KIND(Ident, "identifier", struct { \
|
AST_KIND(Ident, "identifier", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
@@ -442,6 +447,7 @@ AST_KIND(_ExprBegin, "", bool) \
|
|||||||
ProcInlining inlining; \
|
ProcInlining inlining; \
|
||||||
bool optional_ok_one; \
|
bool optional_ok_one; \
|
||||||
bool was_selector; \
|
bool was_selector; \
|
||||||
|
AstSplitArgs *split_args; \
|
||||||
}) \
|
}) \
|
||||||
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
|
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
|
||||||
AST_KIND(EnumFieldValue, "enum field value", struct { \
|
AST_KIND(EnumFieldValue, "enum field value", struct { \
|
||||||
|
|||||||
+8
-4
@@ -37,11 +37,15 @@ gb_internal Token ast_token(Ast *node) {
|
|||||||
return ast_token(node->ImplicitSelectorExpr.selector);
|
return ast_token(node->ImplicitSelectorExpr.selector);
|
||||||
}
|
}
|
||||||
return node->ImplicitSelectorExpr.token;
|
return node->ImplicitSelectorExpr.token;
|
||||||
case Ast_IndexExpr: return node->IndexExpr.open;
|
case Ast_IndexExpr: return ast_token(node->IndexExpr.expr);
|
||||||
case Ast_MatrixIndexExpr: return node->MatrixIndexExpr.open;
|
case Ast_MatrixIndexExpr: return ast_token(node->MatrixIndexExpr.expr);
|
||||||
case Ast_SliceExpr: return node->SliceExpr.open;
|
case Ast_SliceExpr: return ast_token(node->SliceExpr.expr);
|
||||||
case Ast_Ellipsis: return node->Ellipsis.token;
|
case Ast_Ellipsis: return node->Ellipsis.token;
|
||||||
case Ast_FieldValue: return node->FieldValue.eq;
|
case Ast_FieldValue:
|
||||||
|
if (node->FieldValue.field) {
|
||||||
|
return ast_token(node->FieldValue.field);
|
||||||
|
}
|
||||||
|
return node->FieldValue.eq;
|
||||||
case Ast_EnumFieldValue: return ast_token(node->EnumFieldValue.name);
|
case Ast_EnumFieldValue: return ast_token(node->EnumFieldValue.name);
|
||||||
case Ast_DerefExpr: return node->DerefExpr.op;
|
case Ast_DerefExpr: return node->DerefExpr.op;
|
||||||
case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
|
case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
|
||||||
|
|||||||
+16
-8
@@ -2108,8 +2108,12 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) {
|
|||||||
return is_type_polymorphic(t->Matrix.elem, or_specialized);
|
return is_type_polymorphic(t->Matrix.elem, or_specialized);
|
||||||
|
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
for_array(i, t->Tuple.variables) {
|
for (Entity *e : t->Tuple.variables) {
|
||||||
if (is_type_polymorphic(t->Tuple.variables[i]->type, or_specialized)) {
|
if (e->kind == Entity_Constant) {
|
||||||
|
if (e->Constant.value.kind != ExactValue_Invalid) {
|
||||||
|
return or_specialized;
|
||||||
|
}
|
||||||
|
} else if (is_type_polymorphic(e->type, or_specialized)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2119,7 +2123,6 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) {
|
|||||||
if (t->Proc.is_polymorphic) {
|
if (t->Proc.is_polymorphic) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
if (t->Proc.param_count > 0 &&
|
if (t->Proc.param_count > 0 &&
|
||||||
is_type_polymorphic(t->Proc.params, or_specialized)) {
|
is_type_polymorphic(t->Proc.params, or_specialized)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -2128,7 +2131,6 @@ gb_internal bool is_type_polymorphic(Type *t, bool or_specialized=false) {
|
|||||||
is_type_polymorphic(t->Proc.results, or_specialized)) {
|
is_type_polymorphic(t->Proc.results, or_specialized)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Enum:
|
case Type_Enum:
|
||||||
@@ -3326,6 +3328,9 @@ gb_internal bool are_struct_fields_reordered(Type *type) {
|
|||||||
type = base_type(type);
|
type = base_type(type);
|
||||||
GB_ASSERT(type->kind == Type_Struct);
|
GB_ASSERT(type->kind == Type_Struct);
|
||||||
type_set_offsets(type);
|
type_set_offsets(type);
|
||||||
|
if (type->Struct.fields.count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
GB_ASSERT(type->Struct.offsets != nullptr);
|
GB_ASSERT(type->Struct.offsets != nullptr);
|
||||||
|
|
||||||
i64 prev_offset = 0;
|
i64 prev_offset = 0;
|
||||||
@@ -3344,6 +3349,9 @@ gb_internal Slice<i32> struct_fields_index_by_increasing_offset(gbAllocator allo
|
|||||||
type = base_type(type);
|
type = base_type(type);
|
||||||
GB_ASSERT(type->kind == Type_Struct);
|
GB_ASSERT(type->kind == Type_Struct);
|
||||||
type_set_offsets(type);
|
type_set_offsets(type);
|
||||||
|
if (type->Struct.fields.count == 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
GB_ASSERT(type->Struct.offsets != nullptr);
|
GB_ASSERT(type->Struct.offsets != nullptr);
|
||||||
|
|
||||||
auto indices = slice_make<i32>(allocator, type->Struct.fields.count);
|
auto indices = slice_make<i32>(allocator, type->Struct.fields.count);
|
||||||
@@ -4273,6 +4281,10 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
|
|||||||
if (var == nullptr) {
|
if (var == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (comma_index++ > 0) {
|
||||||
|
str = gb_string_appendc(str, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
String name = var->token.string;
|
String name = var->token.string;
|
||||||
if (var->kind == Entity_Constant) {
|
if (var->kind == Entity_Constant) {
|
||||||
str = gb_string_appendc(str, "$");
|
str = gb_string_appendc(str, "$");
|
||||||
@@ -4289,10 +4301,6 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comma_index++ > 0) {
|
|
||||||
str = gb_string_appendc(str, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var->kind == Entity_Variable) {
|
if (var->kind == Entity_Variable) {
|
||||||
if (var->flags&EntityFlag_CVarArg) {
|
if (var->flags&EntityFlag_CVarArg) {
|
||||||
str = gb_string_appendc(str, "#c_vararg ");
|
str = gb_string_appendc(str, "#c_vararg ");
|
||||||
|
|||||||
Reference in New Issue
Block a user