diff --git a/core/bufio/writer.odin b/core/bufio/writer.odin
index cb6b39525..f2b33d591 100644
--- a/core/bufio/writer.odin
+++ b/core/bufio/writer.odin
@@ -183,9 +183,7 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
for {
if writer_available(b) == 0 {
- if ferr := writer_flush(b); ferr != nil {
- return n, ferr;
- }
+ writer_flush(b) or_return;
}
if b.max_consecutive_empty_writes <= 0 {
b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS;
diff --git a/core/compress/zlib/zlib.odin b/core/compress/zlib/zlib.odin
index 0de9a6ec6..7a48d9440 100644
--- a/core/compress/zlib/zlib.odin
+++ b/core/compress/zlib/zlib.odin
@@ -442,24 +442,22 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
return E_General.Unknown_Compression_Method;
}
- cinfo := (cmf >> 4) & 0xf;
- if cinfo > 7 {
+ if cinfo := (cmf >> 4) & 0xf; cinfo > 7 {
return E_ZLIB.Unsupported_Window_Size;
}
flg, _ := compress.read_u8(ctx);
- fcheck := flg & 0x1f;
+ fcheck := flg & 0x1f;
fcheck_computed := (cmf << 8 | flg) & 0x1f;
if fcheck != fcheck_computed {
return E_General.Checksum_Failed;
}
- fdict := (flg >> 5) & 1;
/*
We don't handle built-in dictionaries for now.
They're application specific and PNG doesn't use them.
*/
- if fdict != 0 {
+ if fdict := (flg >> 5) & 1; fdict != 0 {
return E_ZLIB.FDICT_Unsupported;
}
@@ -473,10 +471,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
}
// Parse ZLIB stream without header.
- err = inflate_raw(z=ctx, expected_output_size=expected_output_size);
- if err != nil {
- return err;
- }
+ inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return;
if !raw {
compress.discard_to_next_byte_lsb(ctx);
@@ -527,23 +522,14 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
z_repeat: ^Huffman_Table;
z_offset: ^Huffman_Table;
codelength_ht: ^Huffman_Table;
-
- z_repeat, err = allocate_huffman_table(allocator=context.allocator);
- if err != nil {
- return err;
- }
- z_offset, err = allocate_huffman_table(allocator=context.allocator);
- if err != nil {
- return err;
- }
- codelength_ht, err = allocate_huffman_table(allocator=context.allocator);
- if err != nil {
- return err;
- }
defer free(z_repeat);
defer free(z_offset);
defer free(codelength_ht);
+ z_repeat = allocate_huffman_table(allocator=context.allocator) or_return;
+ z_offset = allocate_huffman_table(allocator=context.allocator) or_return;
+ codelength_ht = allocate_huffman_table(allocator=context.allocator) or_return;
+
final := u32(0);
type := u32(0);
@@ -560,8 +546,8 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
// Discard bits until next byte boundary
compress.discard_to_next_byte_lsb(z);
- uncompressed_len := i16(compress.read_bits_lsb(z, 16));
- length_check := i16(compress.read_bits_lsb(z, 16));
+ uncompressed_len := i16(compress.read_bits_lsb(z, 16));
+ length_check := i16(compress.read_bits_lsb(z, 16));
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check);
@@ -586,14 +572,8 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
// log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
if type == 1 {
// Use fixed code lengths.
- err = build_huffman(z_repeat, Z_FIXED_LENGTH[:]);
- if err != nil {
- return err;
- }
- err = build_huffman(z_offset, Z_FIXED_DIST[:]);
- if err != nil {
- return err;
- }
+ build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return;
+ build_huffman(z_offset, Z_FIXED_DIST[:]) or_return;
} else {
lencodes: [286+32+137]u8;
codelength_sizes: [19]u8;
@@ -611,19 +591,13 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
s := compress.read_bits_lsb(z, 3);
codelength_sizes[Z_LENGTH_DEZIGZAG[i]] = u8(s);
}
- err = build_huffman(codelength_ht, codelength_sizes[:]);
- if err != nil {
- return err;
- }
+ build_huffman(codelength_ht, codelength_sizes[:]) or_return;
n = 0;
c: u16;
for n < ntot {
- c, err = decode_huffman(z, codelength_ht);
- if err != nil {
- return err;
- }
+ c = decode_huffman(z, codelength_ht) or_return;
if c < 0 || c >= 19 {
return E_Deflate.Huffman_Bad_Code_Lengths;
@@ -664,21 +638,10 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
return E_Deflate.Huffman_Bad_Code_Lengths;
}
- err = build_huffman(z_repeat, lencodes[:hlit]);
- if err != nil {
- return err;
- }
-
- err = build_huffman(z_offset, lencodes[hlit:ntot]);
- if err != nil {
- return err;
- }
- }
- err = parse_huffman_block(z, z_repeat, z_offset);
- // log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
- if err != nil {
- return err;
+ build_huffman(z_repeat, lencodes[:hlit]) or_return;
+ build_huffman(z_offset, lencodes[hlit:ntot]) or_return;
}
+ parse_huffman_block(z, z_repeat, z_offset) or_return;
}
if final == 1 {
break;
@@ -698,9 +661,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
ctx.input_data = input;
ctx.output = buf;
- err = inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size);
-
- return err;
+ return inflate_from_context(ctx=&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) {
@@ -712,4 +673,4 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
return inflate_raw(z=&ctx, expected_output_size=expected_output_size);
}
-inflate :: proc{inflate_from_context, inflate_from_byte_array};
\ No newline at end of file
+inflate :: proc{inflate_from_context, inflate_from_byte_array};
\ No newline at end of file
diff --git a/core/encoding/csv/writer.odin b/core/encoding/csv/writer.odin
index bcb6ecc0d..2176e6781 100644
--- a/core/encoding/csv/writer.odin
+++ b/core/encoding/csv/writer.odin
@@ -64,21 +64,15 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
field := record[field_idx];
if field_idx > 0 {
- if _, err := io.write_rune(w.w, w.comma); err != nil {
- return err;
- }
+ io.write_rune(w.w, w.comma) or_return;
}
if !field_needs_quoting(w, field) {
- if _, err := io.write_string(w.w, field); err != nil {
- return err;
- }
+ io.write_string(w.w, field) or_return;
continue;
}
- if err := io.write_byte(w.w, '"'); err != nil {
- return err;
- }
+ io.write_byte(w.w, '"') or_return;
for len(field) > 0 {
i := strings.index_any(field, CHAR_SET);
@@ -86,40 +80,28 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
i = len(field);
}
- if _, err := io.write_string(w.w, field[:i]); err != nil {
- return err;
- }
+ io.write_string(w.w, field[:i]) or_return;
field = field[i:];
if len(field) > 0 {
switch field[0] {
case '\r':
if !w.use_crlf {
- if err := io.write_byte(w.w, '\r'); err != nil {
- return err;
- }
+ io.write_byte(w.w, '\r') or_return;
}
case '\n':
if w.use_crlf {
- if _, err := io.write_string(w.w, "\r\n"); err != nil {
- return err;
- }
+ io.write_string(w.w, "\r\n") or_return;
} else {
- if err := io.write_byte(w.w, '\n'); err != nil {
- return err;
- }
+ io.write_byte(w.w, '\n') or_return;
}
case '"':
- if _, err := io.write_string(w.w, `""`); err != nil {
- return err;
- }
+ io.write_string(w.w, `""`) or_return;
}
field = field[1:];
}
}
- if err := io.write_byte(w.w, '"'); err != nil {
- return err;
- }
+ io.write_byte(w.w, '"') or_return;
}
if w.use_crlf {
@@ -132,10 +114,7 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
// write_all writes multiple CSV records to w using write, and then flushes (if necessary).
write_all :: proc(w: ^Writer, records: [][]string) -> io.Error {
for record in records {
- err := write(w, record);
- if err != nil {
- return err;
- }
+ write(w, record) or_return;
}
return writer_flush(w);
}
diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin
index 991d8f4f1..0cf58dce0 100644
--- a/core/encoding/hxa/read.odin
+++ b/core/encoding/hxa/read.odin
@@ -67,17 +67,9 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
}
read_name :: proc(r: ^Reader) -> (value: string, err: Read_Error) {
- len: u8;
- data: []byte;
- len, err = read_value(r, u8);
- if err != nil {
- return;
- }
- data, err = read_array(r, byte, int(len));
- if err == nil {
- value = string(data[:len]);
- }
- return;
+ len := read_value(r, u8) or_return;
+ data := read_array(r, byte, int(len)) or_return;
+ return string(data[:len]), nil;
}
read_meta :: proc(r: ^Reader, capacity: u32le) -> (meta_data: []Meta, err: Read_Error) {
@@ -85,10 +77,9 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
count := 0;
defer meta_data = meta_data[:count];
for m in &meta_data {
- if m.name, err = read_name(r); err != nil { return };
+ m.name = read_name(r) or_return;
- type: Meta_Value_Type;
- if type, err = read_value(r, Meta_Value_Type); err != nil { return }
+ type := read_value(r, Meta_Value_Type) or_return;
if type > max(Meta_Value_Type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is ", r.filename, u8(type), u8(max(Meta_Value_Type)));
@@ -96,22 +87,15 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
err = .Invalid_Data;
return;
}
- array_length: u32le;
- if array_length, err = read_value(r, u32le); err != nil { return }
+ array_length := read_value(r, u32le) or_return;
switch type {
- case .Int64:
- if m.value, err = read_array(r, i64le, int(array_length)); err != nil { return }
- case .Double:
- if m.value, err = read_array(r, f64le, int(array_length)); err != nil { return }
- case .Node:
- if m.value, err = read_array(r, Node_Index, int(array_length)); err != nil { return }
- case .Text:
- if m.value, err = read_string(r, int(array_length)); err != nil { return }
- case .Binary:
- if m.value, err = read_array(r, byte, int(array_length)); err != nil { return }
- case .Meta:
- if m.value, err = read_meta(r, array_length); err != nil { return }
+ case .Int64: m.value = read_array(r, i64le, int(array_length)) or_return;
+ case .Double: m.value = read_array(r, f64le, int(array_length)) or_return;
+ case .Node: m.value = read_array(r, Node_Index, int(array_length)) or_return;
+ case .Text: m.value = read_string(r, int(array_length)) or_return;
+ case .Binary: m.value = read_array(r, byte, int(array_length)) or_return;
+ case .Meta: m.value = read_meta(r, array_length) or_return;
}
count += 1;
@@ -120,16 +104,14 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
}
read_layer_stack :: proc(r: ^Reader, capacity: u32le) -> (layers: Layer_Stack, err: Read_Error) {
- stack_count: u32le;
- if stack_count, err = read_value(r, u32le); err != nil { return }
+ stack_count := read_value(r, u32le) or_return;
layer_count := 0;
layers = make(Layer_Stack, stack_count);
defer layers = layers[:layer_count];
for layer in &layers {
- type: Layer_Data_Type;
- if layer.name, err = read_name(r); err != nil { return }
- if layer.components, err = read_value(r, u8); err != nil { return }
- if type, err = read_value(r, Layer_Data_Type); err != nil { return }
+ layer.name = read_name(r) or_return;
+ layer.components = read_value(r, u8) or_return;
+ type := read_value(r, Layer_Data_Type) or_return;
if type > max(type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is ", r.filename, u8(type), u8(max(Layer_Data_Type)));
@@ -140,10 +122,10 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
data_len := int(layer.components) * int(capacity);
switch type {
- case .Uint8: if layer.data, err = read_array(r, u8, data_len); err != nil { return }
- case .Int32: if layer.data, err = read_array(r, i32le, data_len); err != nil { return }
- case .Float: if layer.data, err = read_array(r, f32le, data_len); err != nil { return }
- case .Double: if layer.data, err = read_array(r, f64le, data_len); err != nil { return }
+ case .Uint8: layer.data = read_array(r, u8, data_len) or_return;
+ case .Int32: layer.data = read_array(r, i32le, data_len) or_return;
+ case .Float: layer.data = read_array(r, f32le, data_len) or_return;
+ case .Double: layer.data = read_array(r, f64le, data_len) or_return;
}
layer_count += 1;
}
@@ -177,8 +159,7 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
for node_idx in 0.. max(Node_Type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is ", r.filename, u8(type), u8(max(Node_Type)));
@@ -188,9 +169,7 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
}
node_count += 1;
- meta_data_count: u32le;
- if meta_data_count, err = read_value(r, u32le); err != nil { return }
- if node.meta_data, err = read_meta(r, meta_data_count); err != nil { return }
+ node.meta_data = read_meta(r, read_value(r, u32le) or_return) or_return;
switch type {
case .Meta_Only:
@@ -198,35 +177,35 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato
case .Geometry:
g: Node_Geometry;
- if g.vertex_count, err = read_value(r, u32le); err != nil { return }
- if g.vertex_stack, err = read_layer_stack(r, g.vertex_count); err != nil { return }
- if g.edge_corner_count, err = read_value(r, u32le); err != nil { return }
- if g.corner_stack, err = read_layer_stack(r, g.edge_corner_count); err != nil { return }
+ g.vertex_count = read_value(r, u32le) or_return;
+ g.vertex_stack = read_layer_stack(r, g.vertex_count) or_return;
+ g.edge_corner_count = read_value(r, u32le) or_return;
+ g.corner_stack = read_layer_stack(r, g.edge_corner_count) or_return;
if header.version > 2 {
- if g.edge_stack, err = read_layer_stack(r, g.edge_corner_count); err != nil { return }
+ g.edge_stack = read_layer_stack(r, g.edge_corner_count) or_return;
}
- if g.face_count, err = read_value(r, u32le); err != nil { return }
- if g.face_stack, err = read_layer_stack(r, g.face_count); err != nil { return }
+ g.face_count = read_value(r, u32le) or_return;
+ g.face_stack = read_layer_stack(r, g.face_count) or_return;
node.content = g;
case .Image:
img: Node_Image;
- if img.type, err = read_value(r, Image_Type); err != nil { return }
+ img.type = read_value(r, Image_Type) or_return;
dimensions := int(img.type);
if img.type == .Image_Cube {
dimensions = 2;
}
img.resolution = {1, 1, 1};
for d in 0.. (value: Value, err: Error) {
}
parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
- if err = expect_token(p, .Open_Bracket); err != .None {
- return;
- }
+ expect_token(p, .Open_Bracket) or_return;
array: Array;
array.allocator = p.allocator;
@@ -147,11 +145,7 @@ parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
}
for p.curr_token.kind != .Close_Bracket {
- elem, elem_err := parse_value(p);
- if elem_err != .None {
- err = elem_err;
- return;
- }
+ elem := parse_value(p) or_return;
append(&array, elem);
// Disallow trailing commas for the time being
@@ -162,10 +156,7 @@ parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
}
}
- if err = expect_token(p, .Close_Bracket); err != .None {
- return;
- }
-
+ expect_token(p, .Close_Bracket) or_return;
value = array;
return;
}
@@ -200,9 +191,7 @@ parse_object_key :: proc(p: ^Parser) -> (key: string, err: Error) {
}
parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
- if err = expect_token(p, .Open_Brace); err != .None {
- return;
- }
+ expect_token(p, .Open_Brace) or_return;
obj: Object;
obj.allocator = p.allocator;
@@ -227,11 +216,7 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
return;
}
- elem, elem_err := parse_value(p);
- if elem_err != .None {
- err = elem_err;
- return;
- }
+ elem := parse_value(p) or_return;
if key in obj {
err = .Duplicate_Object_Key;
@@ -256,10 +241,7 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
}
}
- if err = expect_token(p, .Close_Brace); err != .None {
- return;
- }
-
+ expect_token(p, .Close_Brace) or_return;
value = obj;
return;
}
diff --git a/core/image/png/png.odin b/core/image/png/png.odin
index e3a36c2fe..587fa4042 100644
--- a/core/image/png/png.odin
+++ b/core/image/png/png.odin
@@ -372,8 +372,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
defer delete(data);
if ok {
- img, err = load_from_slice(data, options, allocator);
- return;
+ return load_from_slice(data, options, allocator);
} else {
img = new(Image);
return img, E_General.File_Not_Found;
@@ -453,10 +452,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
}
seen_ihdr = true;
- header, err = read_header(ctx);
- if err != nil {
- return img, err;
- }
+ header = read_header(ctx) or_return;
if .Paletted in header.color_type {
// Color type 3
@@ -506,10 +502,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, E_PNG.PLTE_Encountered_Unexpectedly;
}
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
if c.header.length % 3 != 0 || c.header.length > 768 {
return img, E_PNG.PLTE_Invalid_Length;
@@ -540,10 +533,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
next := ch.type;
for next == .IDAT {
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
bytes.buffer_write(&idat_b, c.data);
idat_length += c.header.length;
@@ -560,19 +550,13 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
}
seen_idat = true;
case .IEND:
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
seen_iend = true;
case .bKGD:
// TODO: Make sure that 16-bit bKGD + tRNS chunks return u16 instead of u16be
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
seen_bkgd = true;
if .return_metadata in options {
append(&info.chunks, c);
@@ -604,10 +588,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])};
}
case .tRNS:
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
if .Alpha in info.header.color_type {
return img, E_PNG.TRNS_Encountered_Unexpectedly;
@@ -646,10 +627,8 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, E_PNG.PNG_Does_Not_Adhere_to_Spec;
case:
// Unhandled type
- c, err = read_chunk(ctx);
- if err != nil {
- return img, err;
- }
+ c = read_chunk(ctx) or_return;
+
if .return_metadata in options {
// NOTE: Chunk cata is currently allocated on the temp allocator.
append(&info.chunks, c);
diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin
index 81a95a215..ab686b914 100644
--- a/core/math/big/helpers.odin
+++ b/core/math/big/helpers.odin
@@ -42,7 +42,7 @@ int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator :
Check that `src` is usable and `dest` isn't immutable.
*/
assert_if_nil(dest);
- if err = #force_inline internal_error_if_immutable(dest); err != nil { return err; }
+ #force_inline internal_error_if_immutable(dest) or_return;
return #force_inline internal_int_set_from_integer(dest, src, minimize);
}
@@ -64,8 +64,8 @@ int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.alloca
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; }
- if err = #force_inline internal_error_if_immutable(dest); err != nil { return err; }
+ #force_inline internal_clear_if_uninitialized(src) or_return;
+ #force_inline internal_error_if_immutable(dest) or_return;
return #force_inline internal_int_copy(dest, src, minimize);
}
@@ -92,8 +92,8 @@ int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error)
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; }
- if err = #force_inline internal_error_if_immutable(dest); err != nil { return err; }
+ #force_inline internal_clear_if_uninitialized(src) or_return;
+ #force_inline internal_error_if_immutable(dest) or_return;
return #force_inline internal_int_abs(dest, src);
}
@@ -113,8 +113,8 @@ int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error)
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; }
- if err = #force_inline internal_error_if_immutable(dest); err != nil { return err; }
+ #force_inline internal_clear_if_uninitialized(src) or_return;
+ #force_inline internal_error_if_immutable(dest) or_return;
return #force_inline internal_int_neg(dest, src);
}
@@ -134,8 +134,8 @@ int_bitfield_extract :: proc(a: ^Int, offset, count: int, allocator := context.a
assert_if_nil(a);
context.allocator = allocator;
- if err = #force_inline internal_clear_if_uninitialized(a); err != nil { return {}, err; }
- return #force_inline internal_int_bitfield_extract(a, offset, count);
+ #force_inline internal_clear_if_uninitialized(a) or_return;
+ return #force_inline internal_int_bitfield_extract(a, offset, count);
}
/*
@@ -148,8 +148,8 @@ shrink :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
context.allocator = allocator;
- if err = #force_inline internal_clear_if_uninitialized(a); err != nil { return err; }
- return #force_inline internal_shrink(a);
+ #force_inline internal_clear_if_uninitialized(a) or_return;
+ return #force_inline internal_shrink(a);
}
int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) {
@@ -305,8 +305,8 @@ int_get :: proc(a: ^Int, $T: typeid, allocator := context.allocator) -> (res: T,
Check that `a` is usable.
*/
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return T{}, err; }
- return #force_inline internal_int_get(a, T);
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
+ return #force_inline internal_int_get(a, T);
}
get :: proc { int_get, };
@@ -315,8 +315,8 @@ int_get_float :: proc(a: ^Int, allocator := context.allocator) -> (res: f64, err
Check that `a` is usable.
*/
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; }
- return #force_inline internal_int_get_float(a);
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
+ return #force_inline internal_int_get_float(a);
}
/*
@@ -327,8 +327,8 @@ count_bits :: proc(a: ^Int, allocator := context.allocator) -> (count: int, err:
Check that `a` is usable.
*/
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; }
- return #force_inline internal_count_bits(a), nil;
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
+ return #force_inline internal_count_bits(a), nil;
}
/*
@@ -340,8 +340,8 @@ int_count_lsb :: proc(a: ^Int, allocator := context.allocator) -> (count: int, e
Check that `a` is usable.
*/
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; }
- return #force_inline internal_int_count_lsb(a);
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
+ return #force_inline internal_int_count_lsb(a);
}
platform_count_lsb :: #force_inline proc(a: $T) -> (count: int)
@@ -398,7 +398,7 @@ clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocato
assert_if_nil(..args);
for i in &args {
- if err = #force_inline internal_clear_if_uninitialized_single(i, allocator); err != nil { return nil; }
+ #force_inline internal_clear_if_uninitialized_single(i, allocator) or_return;
}
return err;
}
@@ -425,7 +425,7 @@ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err
integers := integers;
for a in &integers {
- if err = #force_inline internal_clear(a, true, allocator); err != nil { return err; }
+ #force_inline internal_clear(a, true, allocator) or_return;
}
return nil;
}
@@ -440,7 +440,7 @@ copy_digits :: proc(dest, src: ^Int, digits: int, allocator := context.allocator
Check that `src` is usable and `dest` isn't immutable.
*/
assert_if_nil(dest, src);
- if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; }
+ #force_inline internal_clear_if_uninitialized(src) or_return;
digits = min(digits, len(src.digit), len(dest.digit));
return #force_inline internal_copy_digits(dest, src, digits);
@@ -454,7 +454,7 @@ copy_digits :: proc(dest, src: ^Int, digits: int, allocator := context.allocator
*/
clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return err; }
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
for a.used > 0 && a.digit[a.used - 1] == 0 {
a.used -= 1;
@@ -472,7 +472,7 @@ clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) {
*/
int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocator) -> (size_in_bytes: int, err: Error) {
assert_if_nil(a);
- if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return {}, err; }
+ #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
size_in_bits := internal_count_bits(a);
@@ -488,9 +488,8 @@ int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocat
*/
int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
- size_in_bytes: int;
- if size_in_bytes, err = int_to_bytes_size(a, signed, allocator); err != nil { return err; }
+ size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return;
l := len(buf);
if size_in_bytes > l { return .Buffer_Overflow; }
@@ -512,9 +511,8 @@ int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := co
*/
int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
- size_in_bytes: int;
- if size_in_bytes, err = int_to_bytes_size(a, signed, allocator); err != nil { return err; }
+ size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return;
l := len(buf);
if size_in_bytes > l { return .Buffer_Overflow; }
@@ -537,18 +535,17 @@ int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := conte
*/
int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
- size_in_bytes: int;
if !signed && a.sign == .Negative { return .Invalid_Argument; }
l := len(buf);
- if size_in_bytes, err = int_to_bytes_size(a, signed, allocator); err != nil { return err; }
- if size_in_bytes > l { return .Buffer_Overflow; }
+ size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return;
+ if size_in_bytes > l { return .Buffer_Overflow; }
if a.sign == .Negative {
t := &Int{};
defer destroy(t);
- if err = internal_complement(t, a, allocator); err != nil { return err; }
+ internal_complement(t, a, allocator) or_return;
size_in_bits := internal_count_bits(t);
i := 0;
@@ -574,19 +571,18 @@ int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocato
*/
int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a);
- size_in_bytes: int;
if !signed && a.sign == .Negative { return .Invalid_Argument; }
if a.sign == .Zero_or_Positive { return int_to_bytes_big(a, buf, signed, allocator); }
l := len(buf);
- if size_in_bytes, err = int_to_bytes_size(a, signed, allocator); err != nil { return err; }
- if size_in_bytes > l { return .Buffer_Overflow; }
+ size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return;
+ if size_in_bytes > l { return .Buffer_Overflow; }
t := &Int{};
defer destroy(t);
- if err = internal_complement(t, a, allocator); err != nil { return err; }
+ internal_complement(t, a, allocator) or_return;
size_in_bits := internal_count_bits(t);
i := l - 1;
@@ -619,8 +615,8 @@ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := con
}
size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
- if err = internal_zero(a, false, allocator); err != nil { return err; }
- if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; }
+ internal_zero(a, false, allocator) or_return;
+ internal_grow(a, size_in_digits, false, allocator) or_return;
if signed {
sign = .Zero_or_Positive if buf[0] == 0 else .Negative;
@@ -628,7 +624,7 @@ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := con
}
for v in buf {
- if err = internal_shl(a, a, 8); err != nil { return err; }
+ internal_shl(a, a, 8) or_return;
a.digit[0] |= DIGIT(v);
}
a.sign = sign;
@@ -656,8 +652,8 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator
}
size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
- if err = internal_zero(a, false, allocator); err != nil { return err; }
- if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; }
+ internal_zero(a, false, allocator) or_return;
+ internal_grow(a, size_in_digits, false, allocator) or_return;
if signed {
sign = .Zero_or_Positive if buf[0] == 0 else .Negative;
@@ -665,7 +661,7 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator
}
for v in buf {
- if err = internal_shl(a, a, 8); err != nil { return err; }
+ internal_shl(a, a, 8) or_return;
if signed && sign == .Negative {
a.digit[0] |= DIGIT(255 - v);
} else {
@@ -674,7 +670,7 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator
}
a.sign = sign;
a.used = size_in_digits;
- if err = internal_clamp(a); err != nil { return err; }
+ internal_clamp(a) or_return;
if signed && sign == .Negative {
return internal_sub(a, a, 1);
@@ -702,8 +698,8 @@ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator :=
}
size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
- if err = internal_zero(a, false, allocator); err != nil { return err; }
- if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; }
+ internal_zero(a, false, allocator) or_return;
+ internal_grow(a, size_in_digits, false, allocator) or_return;
if signed {
sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative;
@@ -712,7 +708,7 @@ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator :=
}
for _, i in buf {
- if err = internal_shl(a, a, 8); err != nil { return err; }
+ internal_shl(a, a, 8) or_return;
a.digit[0] |= DIGIT(buf[l-i-1]);
}
a.sign = sign;
@@ -740,8 +736,8 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca
}
size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
- if err = internal_zero(a, false, allocator); err != nil { return err; }
- if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; }
+ internal_zero(a, false, allocator) or_return;
+ internal_grow(a, size_in_digits, false, allocator) or_return;
if signed {
sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative;
@@ -750,7 +746,7 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca
}
for _, i in buf {
- if err = internal_shl(a, a, 8); err != nil { return err; }
+ internal_shl(a, a, 8) or_return;
if signed && sign == .Negative {
a.digit[0] |= DIGIT(255 - buf[l-i-1]);
} else {
@@ -759,7 +755,7 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca
}
a.sign = sign;
a.used = size_in_digits;
- if err = internal_clamp(a); err != nil { return err; }
+ internal_clamp(a) or_return;
if signed && sign == .Negative {
return internal_sub(a, a, 1);
diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin
index ba6b04f43..2c988f91e 100644
--- a/core/math/big/internal.odin
+++ b/core/math/big/internal.odin
@@ -58,7 +58,7 @@ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocat
max_used = x.used;
old_used = dest.used;
- if err = internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)); err != nil { return err; }
+ internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)) or_return;
dest.used = max_used + 1;
/*
All parameters have been initialized.
@@ -158,7 +158,7 @@ internal_add_signed :: proc { internal_int_add_signed, };
internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
- if err = internal_grow(dest, a.used + 1); err != nil { return err; }
+ internal_grow(dest, a.used + 1) or_return;
/*
Fast paths for destination and input Int being the same.
*/
@@ -284,7 +284,7 @@ internal_int_sub_unsigned :: proc(dest, number, decrease: ^Int, allocator := con
max_used := x.used;
i: int;
- if err = grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)); err != nil { return err; }
+ grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)) or_return;
dest.used = max_used;
/*
All parameters have been initialized.
@@ -389,7 +389,7 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte
internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
- if err = internal_grow(dest, number.used + 1); err != nil { return err; }
+ internal_grow(dest, number.used + 1) or_return;
dest := dest; digit := digit;
/*
@@ -520,12 +520,12 @@ internal_int_shr1 :: proc(dest, src: ^Int) -> (err: Error) {
internal_int_shl1 :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
- if err = internal_copy(dest, src); err != nil { return err; }
+ internal_copy(dest, src) or_return;
/*
Grow `dest` to accommodate the additional bits.
*/
digits_needed := dest.used + 1;
- if err = internal_grow(dest, digits_needed); err != nil { return err; }
+ internal_grow(dest, digits_needed) or_return;
dest.used = digits_needed;
mask := (DIGIT(1) << uint(1)) - DIGIT(1);
@@ -568,15 +568,14 @@ internal_int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator :=
return #force_inline internal_int_shl1(dest, src);
}
if #force_inline platform_int_is_power_of_two(int(multiplier)) {
- ix: int;
- if ix, err = internal_log(multiplier, 2); err != nil { return err; }
+ ix := internal_log(multiplier, 2) or_return;
return internal_shl(dest, src, ix);
}
/*
Ensure `dest` is big enough to hold `src` * `multiplier`.
*/
- if err = grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)); err != nil { return err; }
+ grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)) or_return;
/*
Save the original used count.
@@ -722,7 +721,7 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a
*/
if #force_inline internal_cmp_mag(numerator, denominator) == -1 {
if remainder != nil {
- if err = internal_copy(remainder, numerator); err != nil { return err; }
+ internal_copy(remainder, numerator) or_return;
}
if quotient != nil {
internal_zero(quotient);
@@ -809,7 +808,7 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT,
*/
q := &Int{};
- if err = internal_grow(q, numerator.used); err != nil { return 0, err; }
+ internal_grow(q, numerator.used) or_return;
q.used = numerator.used;
q.sign = numerator.sign;
@@ -853,7 +852,7 @@ internal_div :: proc { internal_int_div, };
Asssumes quotient, numerator and denominator to have been initialized and not to be nil.
*/
internal_int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- if err = #force_inline internal_int_divmod(nil, remainder, numerator, denominator, allocator); err != nil { return err; }
+ #force_inline internal_int_divmod(nil, remainder, numerator, denominator, allocator) or_return;
if remainder.used == 0 || denominator.sign == remainder.sign { return nil; }
@@ -865,7 +864,7 @@ internal_mod :: proc{ internal_int_mod, };
remainder = (number + addend) % modulus.
*/
internal_int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- if err = #force_inline internal_add(remainder, number, addend, allocator); err != nil { return err; }
+ #force_inline internal_add(remainder, number, addend, allocator) or_return;
return #force_inline internal_mod(remainder, remainder, modulus, allocator);
}
internal_addmod :: proc { internal_int_addmod, };
@@ -874,7 +873,7 @@ internal_addmod :: proc { internal_int_addmod, };
remainder = (number - decrease) % modulus.
*/
internal_int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- if err = #force_inline internal_sub(remainder, number, decrease, allocator); err != nil { return err; }
+ #force_inline internal_sub(remainder, number, decrease, allocator) or_return;
return #force_inline internal_mod(remainder, remainder, modulus, allocator);
}
internal_submod :: proc { internal_int_submod, };
@@ -883,7 +882,7 @@ internal_submod :: proc { internal_int_submod, };
remainder = (number * multiplicand) % modulus.
*/
internal_int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- if err = #force_inline internal_mul(remainder, number, multiplicand, allocator); err != nil { return err; }
+ #force_inline internal_mul(remainder, number, multiplicand, allocator) or_return;
return #force_inline internal_mod(remainder, remainder, modulus, allocator);
}
internal_mulmod :: proc { internal_int_mulmod, };
@@ -892,7 +891,7 @@ internal_mulmod :: proc { internal_int_mulmod, };
remainder = (number * number) % modulus.
*/
internal_int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- if err = #force_inline internal_sqr(remainder, number, allocator); err != nil { return err; }
+ #force_inline internal_sqr(remainder, number, allocator) or_return;
return #force_inline internal_mod(remainder, remainder, modulus, allocator);
}
internal_sqrmod :: proc { internal_int_sqrmod, };
@@ -915,9 +914,11 @@ internal_int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator
return #force_inline internal_set(res, _factorial_table[n]);
}
- if err = #force_inline internal_set(res, _factorial_table[i - 1]); err != nil { return err; }
+ #force_inline internal_set(res, _factorial_table[i - 1]) or_return;
for {
- if err = #force_inline internal_mul(res, res, DIGIT(i)); err != nil || i == n { return err; }
+ if err = #force_inline internal_mul(res, res, DIGIT(i)); err != nil || i == n {
+ return err;
+ }
i += 1;
}
@@ -950,8 +951,8 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator :
/*
If the modulus is larger than the value, return the value.
*/
- err = internal_copy(remainder, numerator);
- if bits >= (numerator.used * _DIGIT_BITS) || err != nil {
+ internal_copy(remainder, numerator) or_return;
+ if bits >= (numerator.used * _DIGIT_BITS) {
return;
}
@@ -1264,7 +1265,7 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo
A zero base is a special case.
*/
if power < 0 {
- if err = internal_zero(dest); err != nil { return err; }
+ internal_zero(dest) or_return;
return .Math_Domain_Error;
}
if power == 0 { return internal_one(dest); }
@@ -1293,37 +1294,34 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo
}
g := &Int{};
- if err = internal_copy(g, base); err != nil { return err; }
+ internal_copy(g, base) or_return;
/*
Set initial result.
*/
- if err = internal_one(dest); err != nil { return err; }
+ internal_one(dest) or_return;
- loop: for power > 0 {
+ defer internal_destroy(g);
+
+ for power > 0 {
/*
If the bit is set, multiply.
*/
if power & 1 != 0 {
- if err = internal_mul(dest, g, dest); err != nil {
- break loop;
- }
+ internal_mul(dest, g, dest) or_return;
}
/*
Square.
*/
if power > 1 {
- if err = #force_inline internal_sqr(g, g); err != nil {
- break loop;
- }
+ internal_sqr(g, g) or_return;
}
/* shift to next bit */
power >>= 1;
}
- internal_destroy(g);
- return err;
+ return;
}
/*
@@ -1336,7 +1334,7 @@ internal_int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.
base_t := &Int{};
defer internal_destroy(base_t);
- if err = internal_set(base_t, base); err != nil { return err; }
+ internal_set(base_t, base) or_return;
return #force_inline internal_int_pow(dest, base_t, power);
}
@@ -1387,15 +1385,15 @@ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (e
count := #force_inline internal_count_bits(src);
a, b := count >> 1, count & 1;
- if err = internal_int_power_of_two(x, a+b, allocator); err != nil { return err; }
+ internal_int_power_of_two(x, a+b, allocator) or_return;
for {
/*
y = (x + n // x) // 2
*/
- if err = internal_div(t1, src, x); err != nil { return err; }
- if err = internal_add(t2, t1, x); err != nil { return err; }
- if err = internal_shr(y, t2, 1); err != nil { return err; }
+ internal_div(t1, src, x) or_return;
+ internal_add(t2, t1, x) or_return;
+ internal_shr(y, t2, 1) or_return;
if c := internal_cmp(y, x); c == 0 || c == 1 {
internal_swap(dest, x);
@@ -1480,33 +1478,33 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca
Start value must be larger than root.
*/
ilog2 += 2;
- if err = internal_int_power_of_two(t2, ilog2); err != nil { return err; }
+ internal_int_power_of_two(t2, ilog2) or_return;
c: int;
iterations := 0;
for {
/* t1 = t2 */
- if err = internal_copy(t1, t2); err != nil { return err; }
+ internal_copy(t1, t2) or_return;
/* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
/* t3 = t1**(b-1) */
- if err = internal_pow(t3, t1, n-1); err != nil { return err; }
+ internal_pow(t3, t1, n-1) or_return;
/* numerator */
/* t2 = t1**b */
- if err = internal_mul(t2, t1, t3); err != nil { return err; }
+ internal_mul(t2, t1, t3) or_return;
/* t2 = t1**b - a */
- if err = internal_sub(t2, t2, a); err != nil { return err; }
+ internal_sub(t2, t2, a) or_return;
/* denominator */
/* t3 = t1**(b-1) * b */
- if err = internal_mul(t3, t3, DIGIT(n)); err != nil { return err; }
+ internal_mul(t3, t3, DIGIT(n)) or_return;
/* t3 = (t1**b - a)/(b * t1**(b-1)) */
- if err = internal_div(t3, t2, t3); err != nil { return err; }
- if err = internal_sub(t2, t1, t3); err != nil { return err; }
+ internal_div(t3, t2, t3) or_return;
+ internal_sub(t2, t1, t3) or_return;
/*
Number of rounds is at most log_2(root). If it is more it
@@ -1526,14 +1524,14 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca
iterations = 0;
for {
- if err = internal_pow(t2, t1, n); err != nil { return err; }
+ internal_pow(t2, t1, n) or_return;
c = internal_cmp(t2, a);
if c == 0 {
swap(dest, t1);
return nil;
} else if c == -1 {
- if err = internal_add(t1, t1, DIGIT(1)); err != nil { return err; }
+ internal_add(t1, t1, DIGIT(1)) or_return;
} else {
break;
}
@@ -1549,11 +1547,11 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca
Correct overshoot from above or from recurrence.
*/
for {
- if err = internal_pow(t2, t1, n); err != nil { return err; }
+ internal_pow(t2, t1, n) or_return;
if internal_cmp(t2, a) != 1 { break; }
- if err = internal_sub(t1, t1, DIGIT(1)); err != nil { return err; }
+ internal_sub(t1, t1, DIGIT(1)) or_return;
iterations += 1;
if iterations == MAX_ITERATIONS_ROOT_N {
@@ -1606,12 +1604,12 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al
src := src;
- if err = internal_error_if_immutable(dest); err != nil { return err; }
+ internal_error_if_immutable(dest) or_return;
/*
Most internal procs asssume an Int to have already been initialize,
but as this is one of the procs that initializes, we have to check the following.
*/
- if err = internal_clear_if_uninitialized_single(dest); err != nil { return err; }
+ internal_clear_if_uninitialized_single(dest) or_return;
dest.flags = {}; // We're not -Inf, Inf, NaN or Immutable.
@@ -1631,7 +1629,7 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al
internal_set :: proc { internal_int_set_from_integer, internal_int_copy };
internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int) -> (err: Error) {
- if err = #force_inline internal_error_if_immutable(dest); err != nil { return err; }
+ #force_inline internal_error_if_immutable(dest) or_return;
/*
If dest == src, do nothing
@@ -1653,7 +1651,7 @@ internal_int_copy :: proc(dest, src: ^Int, minimize := false, allocator := conte
*/
if (dest == src) { return nil; }
- if err = internal_error_if_immutable(dest); err != nil { return err; }
+ internal_error_if_immutable(dest) or_return;
/*
Grow `dest` to fit `src`.
@@ -1661,7 +1659,7 @@ internal_int_copy :: proc(dest, src: ^Int, minimize := false, allocator := conte
*/
needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT);
- if err = internal_grow(dest, needed, minimize); err != nil { return err; }
+ internal_grow(dest, needed, minimize) or_return;
/*
Copy everything over and zero high digits.
@@ -1708,9 +1706,7 @@ internal_int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (er
/*
Copy `src` to `dest`
*/
- if err = internal_copy(dest, src); err != nil {
- return err;
- }
+ internal_copy(dest, src) or_return;
/*
Fix sign.
@@ -1744,7 +1740,7 @@ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (er
/*
Copy `src` to `dest`
*/
- if err = internal_copy(dest, src); err != nil { return err; }
+ internal_copy(dest, src) or_return;
/*
Fix sign.
@@ -1953,7 +1949,7 @@ internal_int_power_of_two :: proc(a: ^Int, power: int, allocator := context.allo
Grow to accomodate the single bit.
*/
a.used = (power / _DIGIT_BITS) + 1;
- if err = internal_grow(a, a.used); err != nil { return err; }
+ internal_grow(a, a.used) or_return;
/*
Zero the entirety.
*/
@@ -2061,7 +2057,7 @@ internal_int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (e
/*
Grow the destination to accomodate the result.
*/
- if err = internal_grow(dest, used); err != nil { return err; }
+ internal_grow(dest, used) or_return;
neg_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b);
@@ -2122,7 +2118,7 @@ internal_int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (er
/*
Grow the destination to accomodate the result.
*/
- if err = internal_grow(dest, used); err != nil { return err; }
+ internal_grow(dest, used) or_return;
neg_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b);
@@ -2183,7 +2179,7 @@ internal_int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (e
/*
Grow the destination to accomodate the result.
*/
- if err = internal_grow(dest, used); err != nil { return err; }
+ internal_grow(dest, used) or_return;
neg_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b);
@@ -2269,21 +2265,21 @@ internal_int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, all
bits := bits;
if bits < 0 { return .Invalid_Argument; }
- if err = internal_copy(quotient, numerator); err != nil { return err; }
+ internal_copy(quotient, numerator) or_return;
/*
Shift right by a certain bit count (store quotient and optional remainder.)
`numerator` should not be used after this.
*/
if remainder != nil {
- if err = internal_int_mod_bits(remainder, numerator, bits); err != nil { return err; }
+ internal_int_mod_bits(remainder, numerator, bits) or_return;
}
/*
Shift by as many digits in the bit count.
*/
if bits >= _DIGIT_BITS {
- if err = internal_shr_digit(quotient, bits / _DIGIT_BITS); err != nil { return err; }
+ internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return;
}
/*
@@ -2362,9 +2358,8 @@ internal_int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context
if src.sign == .Zero_or_Positive {
return internal_shr(dest, src, bits);
}
- if err = internal_int_add_digit(dest, src, DIGIT(1)); err != nil { return err; }
-
- if err = internal_shr(dest, dest, bits); err != nil { return err; }
+ internal_int_add_digit(dest, src, DIGIT(1)) or_return;
+ internal_shr(dest, dest, bits) or_return;
return internal_sub(dest, src, DIGIT(1));
}
@@ -2380,19 +2375,19 @@ internal_int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.alloca
if bits < 0 { return .Invalid_Argument; }
- if err = internal_copy(dest, src); err != nil { return err; }
+ internal_copy(dest, src) or_return;
/*
Grow `dest` to accommodate the additional bits.
*/
digits_needed := dest.used + (bits / _DIGIT_BITS) + 1;
- if err = internal_grow(dest, digits_needed); err != nil { return err; }
+ internal_grow(dest, digits_needed) or_return;
dest.used = digits_needed;
/*
Shift by as many digits in the bit count as we have.
*/
if bits >= _DIGIT_BITS {
- if err = internal_shl_digit(dest, bits / _DIGIT_BITS); err != nil { return err; }
+ internal_shl_digit(dest, bits / _DIGIT_BITS) or_return;
}
/*
@@ -2434,12 +2429,14 @@ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context
/*
No need to shift a zero.
*/
- if #force_inline internal_is_zero(quotient) { return {}; }
+ if #force_inline internal_is_zero(quotient) {
+ return nil;
+ }
/*
Resize `quotient` to accomodate extra digits.
*/
- if err = #force_inline internal_grow(quotient, quotient.used + digits); err != nil { return err; }
+ #force_inline internal_grow(quotient, quotient.used + digits) or_return;
/*
Increment the used by the shift amount then copy upwards.
@@ -2537,7 +2534,7 @@ internal_int_rand :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator :
digits += 1;
}
- if err = #force_inline internal_grow(dest, digits); err != nil { return err; }
+ #force_inline internal_grow(dest, digits) or_return;
for i := 0; i < digits; i += 1 {
dest.digit[i] = int_random_digit(r) & _MASK;
@@ -2600,7 +2597,7 @@ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator
integers := integers;
for a in &integers {
- if err = internal_clear(a); err != nil { return err; }
+ internal_clear(a) or_return;
}
return nil;
}
diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin
index 1eb26332a..42b262488 100644
--- a/core/math/big/logical.odin
+++ b/core/math/big/logical.odin
@@ -25,7 +25,7 @@ int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_int_and(dest, a, b);
}
and :: proc { int_and, };
@@ -37,7 +37,7 @@ int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error)
assert_if_nil(dest, a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_int_or(dest, a, b);
}
or :: proc { int_or, };
@@ -49,7 +49,7 @@ int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_int_xor(dest, a, b);
}
xor :: proc { int_xor, };
@@ -64,7 +64,7 @@ int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err:
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
return #force_inline internal_int_complement(dest, src);
}
complement :: proc { int_complement, };
@@ -97,7 +97,7 @@ int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato
assert_if_nil(quotient);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(quotient); err != nil { return err; }
+ internal_clear_if_uninitialized(quotient) or_return;
return #force_inline internal_int_shr_digit(quotient, digits);
}
shr_digit :: proc { int_shr_digit, };
@@ -109,7 +109,7 @@ int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocato
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
return #force_inline internal_int_shr_signed(dest, src, bits);
}
@@ -122,7 +122,7 @@ int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
return #force_inline internal_int_shl(dest, src, bits);
}
shl :: proc { int_shl, };
@@ -138,7 +138,7 @@ int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato
assert_if_nil(quotient);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(quotient); err != nil { return err; }
+ internal_clear_if_uninitialized(quotient) or_return;
return #force_inline internal_int_shl_digit(quotient, digits);
}
shl_digit :: proc { int_shl_digit, };
\ No newline at end of file
diff --git a/core/math/big/prime.odin b/core/math/big/prime.odin
index 81fa2f69b..b022870a6 100644
--- a/core/math/big/prime.odin
+++ b/core/math/big/prime.odin
@@ -19,12 +19,13 @@ int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res:
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return {}, err; }
+ internal_clear_if_uninitialized(a) or_return;
- rem: DIGIT;
for prime in _private_prime_table {
- if rem, err = #force_inline int_mod_digit(a, prime); err != nil { return false, err; }
- if rem == 0 { return true, nil; }
+ rem := #force_inline int_mod_digit(a, prime) or_return;
+ if rem == 0 {
+ return true, nil;
+ }
}
/*
Default to not divisible.
diff --git a/core/math/big/private.odin b/core/math/big/private.odin
index 6094e6baf..a99d6119f 100644
--- a/core/math/big/private.odin
+++ b/core/math/big/private.odin
@@ -42,7 +42,7 @@ _private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.all
t := &Int{};
- if err = internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)); err != nil { return err; }
+ internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)) or_return;
t.used = digits;
/*
@@ -116,7 +116,7 @@ _private_int_mul_comba :: proc(dest, a, b: ^Int, digits: int, allocator := conte
/*
Grow the destination as required.
*/
- if err = internal_grow(dest, digits); err != nil { return err; }
+ internal_grow(dest, digits) or_return;
/*
Number of output digits to produce.
@@ -198,7 +198,7 @@ _private_int_sqr :: proc(dest, src: ^Int, allocator := context.allocator) -> (er
/*
Grow `t` to maximum needed size, or `_DEFAULT_DIGIT_COUNT`, whichever is bigger.
*/
- if err = internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)); err != nil { return err; }
+ internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)) or_return;
t.used = (2 * pa) + 1;
#no_bounds_check for ix = 0; ix < pa; ix += 1 {
@@ -272,7 +272,7 @@ _private_int_sqr_comba :: proc(dest, src: ^Int, allocator := context.allocator)
Grow the destination as required.
*/
pa := uint(src.used) + uint(src.used);
- if err = internal_grow(dest, int(pa)); err != nil { return err; }
+ internal_grow(dest, int(pa)) or_return;
/*
Number of output digits to produce.
@@ -374,12 +374,12 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat
/*
Init temps.
*/
- if err = internal_grow(x0, B); err != nil { return err; }
- if err = internal_grow(x1, src.used - B); err != nil { return err; }
- if err = internal_grow(t1, src.used * 2); err != nil { return err; }
- if err = internal_grow(t2, src.used * 2); err != nil { return err; }
- if err = internal_grow(x0x0, B * 2 ); err != nil { return err; }
- if err = internal_grow(x1x1, (src.used - B) * 2); err != nil { return err; }
+ internal_grow(x0, B) or_return;
+ internal_grow(x1, src.used - B) or_return;
+ internal_grow(t1, src.used * 2) or_return;
+ internal_grow(t2, src.used * 2) or_return;
+ internal_grow(x0x0, B * 2 ) or_return;
+ internal_grow(x1x1, (src.used - B) * 2) or_return;
/*
Now shift the digits.
@@ -394,28 +394,28 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat
/*
Now calc the products x0*x0 and x1*x1.
*/
- if err = internal_sqr(x0x0, x0); err != nil { return err; }
- if err = internal_sqr(x1x1, x1); err != nil { return err; }
+ internal_sqr(x0x0, x0) or_return;
+ internal_sqr(x1x1, x1) or_return;
/*
Now calc (x1+x0)^2
*/
- if err = internal_add(t1, x0, x1); err != nil { return err; }
- if err = internal_sqr(t1, t1); err != nil { return err; }
+ internal_add(t1, x0, x1) or_return;
+ internal_sqr(t1, t1) or_return;
/*
Add x0y0
*/
- if err = internal_add(t2, x0x0, x1x1); err != nil { return err; }
- if err = internal_sub(t1, t1, t2); err != nil { return err; }
+ internal_add(t2, x0x0, x1x1) or_return;
+ internal_sub(t1, t1, t2) or_return;
/*
Shift by B.
*/
- if err = internal_shl_digit(t1, B); err != nil { return err; }
- if err = internal_shl_digit(x1x1, B * 2); err != nil { return err; }
- if err = internal_add(t1, t1, x0x0); err != nil { return err; }
- if err = internal_add(dest, t1, x1x1); err != nil { return err; }
+ internal_shl_digit(t1, B) or_return;
+ internal_shl_digit(x1x1, B * 2) or_return;
+ internal_add(t1, t1, x0x0) or_return;
+ internal_add(dest, t1, x1x1) or_return;
return #force_inline internal_clamp(dest);
}
@@ -435,7 +435,7 @@ _private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -
/*
Init temps.
*/
- if err = internal_zero(S0); err != nil { return err; }
+ internal_zero(S0) or_return;
/*
B
@@ -445,9 +445,9 @@ _private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -
/*
a = a2 * x^2 + a1 * x + a0;
*/
- if err = internal_grow(a0, B); err != nil { return err; }
- if err = internal_grow(a1, B); err != nil { return err; }
- if err = internal_grow(a2, src.used - (2 * B)); err != nil { return err; }
+ internal_grow(a0, B) or_return;
+ internal_grow(a1, B) or_return;
+ internal_grow(a2, src.used - (2 * B)) or_return;
a0.used = B;
a1.used = B;
@@ -462,67 +462,67 @@ _private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -
internal_clamp(a2);
/** S0 = a0^2; */
- if err = internal_sqr(S0, a0); err != nil { return err; }
+ internal_sqr(S0, a0) or_return;
/** \\S1 = (a2 + a1 + a0)^2 */
/** \\S2 = (a2 - a1 + a0)^2 */
/** \\S1 = a0 + a2; */
/** a0 = a0 + a2; */
- if err = internal_add(a0, a0, a2); err != nil { return err; }
+ internal_add(a0, a0, a2) or_return;
/** \\S2 = S1 - a1; */
/** b = a0 - a1; */
- if err = internal_sub(dest, a0, a1); err != nil { return err; }
+ internal_sub(dest, a0, a1) or_return;
/** \\S1 = S1 + a1; */
/** a0 = a0 + a1; */
- if err = internal_add(a0, a0, a1); err != nil { return err; }
+ internal_add(a0, a0, a1) or_return;
/** \\S1 = S1^2; */
/** a0 = a0^2; */
- if err = internal_sqr(a0, a0); err != nil { return err; }
+ internal_sqr(a0, a0) or_return;
/** \\S2 = S2^2; */
/** b = b^2; */
- if err = internal_sqr(dest, dest); err != nil { return err; }
+ internal_sqr(dest, dest) or_return;
/** \\ S3 = 2 * a1 * a2 */
/** \\S3 = a1 * a2; */
/** a1 = a1 * a2; */
- if err = internal_mul(a1, a1, a2); err != nil { return err; }
+ internal_mul(a1, a1, a2) or_return;
/** \\S3 = S3 << 1; */
/** a1 = a1 << 1; */
- if err = internal_shl(a1, a1, 1); err != nil { return err; }
+ internal_shl(a1, a1, 1) or_return;
/** \\S4 = a2^2; */
/** a2 = a2^2; */
- if err = internal_sqr(a2, a2); err != nil { return err; }
+ internal_sqr(a2, a2) or_return;
/** \\ tmp = (S1 + S2)/2 */
/** \\tmp = S1 + S2; */
/** b = a0 + b; */
- if err = internal_add(dest, a0, dest); err != nil { return err; }
+ internal_add(dest, a0, dest) or_return;
/** \\tmp = tmp >> 1; */
/** b = b >> 1; */
- if err = internal_shr(dest, dest, 1); err != nil { return err; }
+ internal_shr(dest, dest, 1) or_return;
/** \\ S1 = S1 - tmp - S3 */
/** \\S1 = S1 - tmp; */
/** a0 = a0 - b; */
- if err = internal_sub(a0, a0, dest); err != nil { return err; }
+ internal_sub(a0, a0, dest) or_return;
/** \\S1 = S1 - S3; */
/** a0 = a0 - a1; */
- if err = internal_sub(a0, a0, a1); err != nil { return err; }
+ internal_sub(a0, a0, a1) or_return;
/** \\S2 = tmp - S4 -S0 */
/** \\S2 = tmp - S4; */
/** b = b - a2; */
- if err = internal_sub(dest, dest, a2); err != nil { return err; }
+ internal_sub(dest, dest, a2) or_return;
/** \\S2 = S2 - S0; */
/** b = b - S0; */
- if err = internal_sub(dest, dest, S0); err != nil { return err; }
+ internal_sub(dest, dest, S0) or_return;
/** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
/** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
- if err = internal_shl_digit( a2, 4 * B); err != nil { return err; }
- if err = internal_shl_digit( a1, 3 * B); err != nil { return err; }
- if err = internal_shl_digit(dest, 2 * B); err != nil { return err; }
- if err = internal_shl_digit( a0, 1 * B); err != nil { return err; }
+ internal_shl_digit( a2, 4 * B) or_return;
+ internal_shl_digit( a1, 3 * B) or_return;
+ internal_shl_digit(dest, 2 * B) or_return;
+ internal_shl_digit( a0, 1 * B) or_return;
- if err = internal_add(a2, a2, a1); err != nil { return err; }
- if err = internal_add(dest, dest, a2); err != nil { return err; }
- if err = internal_add(dest, dest, a0); err != nil { return err; }
- if err = internal_add(dest, dest, S0); err != nil { return err; }
+ internal_add(a2, a2, a1) or_return;
+ internal_add(dest, dest, a2) or_return;
+ internal_add(dest, dest, a0) or_return;
+ internal_add(dest, dest, S0) or_return;
/** a^2 - P */
return #force_inline internal_clamp(dest);
@@ -540,7 +540,7 @@ _private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.alloc
b := _WORD(1) << _WORD(_DIGIT_BITS) / _WORD(3);
q := &Int{};
- if err = internal_grow(q, numerator.used); err != nil { return 0, err; }
+ internal_grow(q, numerator.used) or_return;
q.used = numerator.used;
q.sign = numerator.sign;
@@ -598,17 +598,17 @@ _private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.alloc
_private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
- if err = error_if_immutable(quotient, remainder); err != nil { return err; }
+ error_if_immutable(quotient, remainder) or_return;
q, x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
defer internal_destroy(q, x, y, t1, t2);
- if err = internal_grow(q, numerator.used + 2); err != nil { return err; }
+ internal_grow(q, numerator.used + 2) or_return;
q.used = numerator.used + 2;
- if err = internal_init_multi(t1, t2); err != nil { return err; }
- if err = internal_copy(x, numerator); err != nil { return err; }
- if err = internal_copy(y, denominator); err != nil { return err; }
+ internal_init_multi(t1, t2) or_return;
+ internal_copy(x, numerator) or_return;
+ internal_copy(y, denominator) or_return;
/*
Fix the sign.
@@ -624,8 +624,8 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
if norm < _DIGIT_BITS - 1 {
norm = (_DIGIT_BITS - 1) - norm;
- if err = internal_shl(x, x, norm); err != nil { return err; }
- if err = internal_shl(y, y, norm); err != nil { return err; }
+ internal_shl(x, x, norm) or_return;
+ internal_shl(y, y, norm) or_return;
} else {
norm = 0;
}
@@ -641,12 +641,12 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
y = y*b**{n-t}
*/
- if err = internal_shl_digit(y, n - t); err != nil { return err; }
+ internal_shl_digit(y, n - t) or_return;
c := internal_cmp(x, y);
for c != -1 {
q.digit[n - t] += 1;
- if err = internal_sub(x, x, y); err != nil { return err; }
+ internal_sub(x, x, y) or_return;
c = internal_cmp(x, y);
}
@@ -696,7 +696,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
t1.digit[0] = ((t - 1) < 0) ? 0 : y.digit[t - 1];
t1.digit[1] = y.digit[t];
t1.used = 2;
- if err = internal_mul(t1, t1, q.digit[(i - t) - 1]); err != nil { return err; }
+ internal_mul(t1, t1, q.digit[(i - t) - 1]) or_return;
/*
Find right hand.
@@ -709,23 +709,25 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
if t1_t2 := internal_cmp_mag(t1, t2); t1_t2 != 1 {
break;
}
- iter += 1; if iter > 100 { return .Max_Iterations_Reached; }
+ iter += 1; if iter > 100 {
+ return .Max_Iterations_Reached;
+ }
}
/*
Step 3.3 x = x - q{i-t-1} * y * b**{i-t-1}
*/
- if err = int_mul_digit(t1, y, q.digit[(i - t) - 1]); err != nil { return err; }
- if err = internal_shl_digit(t1, (i - t) - 1); err != nil { return err; }
- if err = internal_sub(x, x, t1); err != nil { return err; }
+ int_mul_digit(t1, y, q.digit[(i - t) - 1]) or_return;
+ internal_shl_digit(t1, (i - t) - 1) or_return;
+ internal_sub(x, x, t1) or_return;
/*
if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; }
*/
if x.sign == .Negative {
- if err = internal_copy(t1, y); err != nil { return err; }
- if err = internal_shl_digit(t1, (i - t) - 1); err != nil { return err; }
- if err = internal_add(x, x, t1); err != nil { return err; }
+ internal_copy(t1, y) or_return;
+ internal_shl_digit(t1, (i - t) - 1) or_return;
+ internal_add(x, x, t1) or_return;
q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK;
}
@@ -745,7 +747,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
}
if remainder != nil {
- if err = internal_shr(x, x, norm); err != nil { return err; }
+ internal_shr(x, x, norm) or_return;
internal_swap(x, remainder);
}
@@ -770,68 +772,72 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con
m := a.used - b.used;
k := m / 2;
- if m < MUL_KARATSUBA_CUTOFF { return _private_int_div_school(quotient, remainder, a, b); }
+ if m < MUL_KARATSUBA_CUTOFF {
+ return _private_int_div_school(quotient, remainder, a, b);
+ }
- if err = internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t); err != nil { return err; }
+ internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t) or_return;
/*
`B1` = `b` / `beta`^`k`, `B0` = `b` % `beta`^`k`
*/
- if err = internal_shrmod(B1, B0, b, k * _DIGIT_BITS); err != nil { return err; }
+ internal_shrmod(B1, B0, b, k * _DIGIT_BITS) or_return;
/*
(Q1, R1) = RecursiveDivRem(A / beta^(2k), B1)
*/
- if err = internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS); err != nil { return err; }
- if err = _private_div_recursion(Q1, R1, A1, B1); err != nil { return err; }
+ internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS) or_return;
+ _private_div_recursion(Q1, R1, A1, B1) or_return;
/*
A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k)
*/
- if err = internal_shl_digit(R1, 2 * k); err != nil { return err; }
- if err = internal_add(A1, R1, t); err != nil { return err; }
- if err = internal_mul(t, Q1, B0); err != nil { return err; }
+ internal_shl_digit(R1, 2 * k) or_return;
+ internal_add(A1, R1, t) or_return;
+ internal_mul(t, Q1, B0) or_return;
/*
While A1 < 0 do Q1 = Q1 - 1, A1 = A1 + (beta^k * B)
*/
if internal_cmp(A1, 0) == -1 {
- if internal_shl(t, b, k * _DIGIT_BITS); err != nil { return err; }
+ internal_shl(t, b, k * _DIGIT_BITS) or_return;
for {
- if err = internal_decr(Q1); err != nil { return err; }
- if err = internal_add(A1, A1, t); err != nil { return err; }
- if internal_cmp(A1, 0) != -1 { break; }
+ internal_decr(Q1) or_return;
+ internal_add(A1, A1, t) or_return;
+ if internal_cmp(A1, 0) != -1 {
+ break;
+ }
}
}
/*
(Q0, R0) = RecursiveDivRem(A1 / beta^(k), B1)
*/
- if internal_shrmod(A1, t, A1, k * _DIGIT_BITS); err != nil { return err; }
- if _private_div_recursion(Q0, R0, A1, B1); err != nil { return err; }
+ internal_shrmod(A1, t, A1, k * _DIGIT_BITS) or_return;
+ _private_div_recursion(Q0, R0, A1, B1) or_return;
/*
A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0)
*/
- if err = internal_shl_digit(R0, k); err != nil { return err; }
- if err = internal_add(A2, R0, t); err != nil { return err; }
- if err = internal_mul(t, Q0, B0); err != nil { return err; }
- if err = internal_sub(A2, A2, t); err != nil { return err; }
+ internal_shl_digit(R0, k) or_return;
+ internal_add(A2, R0, t) or_return;
+ internal_mul(t, Q0, B0) or_return;
+ internal_sub(A2, A2, t) or_return;
/*
While A2 < 0 do Q0 = Q0 - 1, A2 = A2 + B.
*/
for internal_cmp(A2, 0) == -1 {
- if err = internal_decr(Q0); err != nil { return err; }
- if err = internal_add(A2, A2, b); err != nil { return err; }
+ internal_decr(Q0) or_return;
+ internal_add(A2, A2, b) or_return;
}
/*
Return q = (Q1*beta^k) + Q0, r = A2.
*/
- if err = internal_shl_digit(Q1, k); err != nil { return err; }
- if err = internal_add(quotient, Q1, Q0); err != nil { return err; }
+ internal_shl_digit(Q1, k) or_return;
+ internal_add(quotient, Q1, Q0) or_return;
return internal_copy(remainder, A2);
}
@@ -842,7 +848,7 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator :=
A, B, Q, Q1, R, A_div, A_mod := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
defer internal_destroy(A, B, Q, Q1, R, A_div, A_mod);
- if err = internal_init_multi(A, B, Q, Q1, R, A_div, A_mod); err != nil { return err; }
+ internal_init_multi(A, B, Q, Q1, R, A_div, A_mod) or_return;
/*
Most significant bit of a limb.
@@ -859,8 +865,8 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator :=
/*
Use that sigma to normalize B.
*/
- if err = internal_shl(B, b, sigma); err != nil { return err; }
- if err = internal_shl(A, a, sigma); err != nil { return err; }
+ internal_shl(B, b, sigma) or_return;
+ internal_shl(A, a, sigma) or_return;
/*
Fix the sign.
@@ -883,20 +889,20 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator :=
(q, r) = RecursiveDivRem(A / (beta^(m-n)), B)
*/
j := (m - n) * _DIGIT_BITS;
- if err = internal_shrmod(A_div, A_mod, A, j); err != nil { return err; }
- if err = _private_div_recursion(Q1, R, A_div, B); err != nil { return err; }
+ internal_shrmod(A_div, A_mod, A, j) or_return;
+ _private_div_recursion(Q1, R, A_div, B) or_return;
/*
Q = (Q*beta!(n)) + q
*/
- if err = internal_shl(Q, Q, n * _DIGIT_BITS); err != nil { return err; }
- if err = internal_add(Q, Q, Q1); err != nil { return err; }
+ internal_shl(Q, Q, n * _DIGIT_BITS) or_return;
+ internal_add(Q, Q, Q1) or_return;
/*
A = (r * beta^(m-n)) + (A % beta^(m-n))
*/
- if err = internal_shl(R, R, (m - n) * _DIGIT_BITS); err != nil { return err; }
- if err = internal_add(A, R, A_mod); err != nil { return err; }
+ internal_shl(R, R, (m - n) * _DIGIT_BITS) or_return;
+ internal_add(A, R, A_mod) or_return;
/*
m = m - n
@@ -907,13 +913,13 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator :=
/*
(q, r) = RecursiveDivRem(A, B)
*/
- if err = _private_div_recursion(Q1, R, A, B); err != nil { return err; }
+ _private_div_recursion(Q1, R, A, B) or_return;
/*
Q = (Q * beta^m) + q, R = r
*/
- if err = internal_shl(Q, Q, m * _DIGIT_BITS); err != nil { return err; }
- if err = internal_add(Q, Q, Q1); err != nil { return err; }
+ internal_shl(Q, Q, m * _DIGIT_BITS) or_return;
+ internal_add(Q, Q, Q1) or_return;
/*
Get sign before writing to dest.
@@ -928,7 +934,7 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator :=
/*
De-normalize the remainder.
*/
- if err = internal_shrmod(R, nil, R, sigma); err != nil { return err; }
+ internal_shrmod(R, nil, R, sigma) or_return;
swap(remainder, R);
}
return nil;
@@ -942,28 +948,29 @@ _private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int
ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{};
c: int;
+ defer destroy(ta, tb, tq, q);
- goto_end: for {
- if err = internal_one(tq); err != nil { break goto_end; }
+ for {
+ internal_one(tq) or_return;
num_bits, _ := count_bits(numerator);
den_bits, _ := count_bits(denominator);
n := num_bits - den_bits;
- if err = abs(ta, numerator); err != nil { break goto_end; }
- if err = abs(tb, denominator); err != nil { break goto_end; }
- if err = shl(tb, tb, n); err != nil { break goto_end; }
- if err = shl(tq, tq, n); err != nil { break goto_end; }
+ abs(ta, numerator) or_return;
+ abs(tb, denominator) or_return;
+ shl(tb, tb, n) or_return;
+ shl(tq, tq, n) or_return;
for n >= 0 {
if c, _ = cmp_mag(ta, tb); c == 0 || c == 1 {
// ta -= tb
- if err = sub(ta, ta, tb); err != nil { break goto_end; }
+ sub(ta, ta, tb) or_return;
// q += tq
- if err = add( q, q, tq); err != nil { break goto_end; }
+ add( q, q, tq) or_return;
}
- if err = shr1(tb, tb); err != nil { break goto_end; }
- if err = shr1(tq, tq); err != nil { break goto_end; }
+ shr1(tb, tb) or_return;
+ shr1(tq, tq) or_return;
n -= 1;
}
@@ -983,9 +990,8 @@ _private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int
remainder.sign = .Zero_or_Positive if z else numerator.sign;
}
- break goto_end;
+ break;
}
- destroy(ta, tb, tq, q);
return err;
}
@@ -999,17 +1005,17 @@ _private_int_factorial_binary_split :: proc(res: ^Int, n: int, allocator := cont
inner, outer, start, stop, temp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
defer internal_destroy(inner, outer, start, stop, temp);
- if err = internal_one(inner, false, allocator); err != nil { return err; }
- if err = internal_one(outer, false, allocator); err != nil { return err; }
+ internal_one(inner, false, allocator) or_return;
+ internal_one(outer, false, allocator) or_return;
bits_used := int(_DIGIT_TYPE_BITS - intrinsics.count_leading_zeros(n));
for i := bits_used; i >= 0; i -= 1 {
start := (n >> (uint(i) + 1)) + 1 | 1;
stop := (n >> uint(i)) + 1 | 1;
- if err = _private_int_recursive_product(temp, start, stop, 0, allocator); err != nil { return err; }
- if err = internal_mul(inner, inner, temp, allocator); err != nil { return err; }
- if err = internal_mul(outer, outer, inner, allocator); err != nil { return err; }
+ _private_int_recursive_product(temp, start, stop, 0, allocator) or_return;
+ internal_mul(inner, inner, temp, allocator) or_return;
+ internal_mul(outer, outer, inner, allocator) or_return;
}
shift := n - intrinsics.count_ones(n);
@@ -1023,28 +1029,32 @@ _private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int
t1, t2 := &Int{}, &Int{};
defer internal_destroy(t1, t2);
- if level > FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS { return .Max_Iterations_Reached; }
+ if level > FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS {
+ return .Max_Iterations_Reached;
+ }
num_factors := (stop - start) >> 1;
if num_factors == 2 {
- if err = internal_set(t1, start, false, allocator); err != nil { return err; }
+ internal_set(t1, start, false, allocator) or_return;
when true {
- if err = internal_grow(t2, t1.used + 1, false, allocator); err != nil { return err; }
- if err = internal_add(t2, t1, 2, allocator); err != nil { return err; }
+ internal_grow(t2, t1.used + 1, false, allocator) or_return;
+ internal_add(t2, t1, 2, allocator) or_return;
} else {
- if err = add(t2, t1, 2); err != nil { return err; }
+ add(t2, t1, 2) or_return;
}
return internal_mul(res, t1, t2, allocator);
}
if num_factors > 1 {
mid := (start + num_factors) | 1;
- if err = _private_int_recursive_product(t1, start, mid, level + 1, allocator); err != nil { return err; }
- if err = _private_int_recursive_product(t2, mid, stop, level + 1, allocator); err != nil { return err; }
+ _private_int_recursive_product(t1, start, mid, level + 1, allocator) or_return;
+ _private_int_recursive_product(t2, mid, stop, level + 1, allocator) or_return;
return internal_mul(res, t1, t2, allocator);
}
- if num_factors == 1 { return #force_inline internal_set(res, start, true, allocator); }
+ if num_factors == 1 {
+ return #force_inline internal_set(res, start, true, allocator);
+ }
return #force_inline internal_one(res, true, allocator);
}
@@ -1067,7 +1077,9 @@ _private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int
_private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator;
- if res_gcd == nil && res_lcm == nil { return nil; }
+ if res_gcd == nil && res_lcm == nil {
+ return nil;
+ }
/*
We need a temporary because `res_gcd` is allowed to be `nil`.
@@ -1077,10 +1089,10 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
GCD(0, 0) and LCM(0, 0) are both 0.
*/
if res_gcd != nil {
- if err = internal_zero(res_gcd); err != nil { return err; }
+ internal_zero(res_gcd) or_return;
}
if res_lcm != nil {
- if err = internal_zero(res_lcm); err != nil { return err; }
+ internal_zero(res_lcm) or_return;
}
return nil;
} else if a.used == 0 {
@@ -1088,10 +1100,10 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
We can early out with GCD = B and LCM = 0
*/
if res_gcd != nil {
- if err = internal_abs(res_gcd, b); err != nil { return err; }
+ internal_abs(res_gcd, b) or_return;
}
if res_lcm != nil {
- if err = internal_zero(res_lcm); err != nil { return err; }
+ internal_zero(res_lcm) or_return;
}
return nil;
} else if b.used == 0 {
@@ -1099,10 +1111,10 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
We can early out with GCD = A and LCM = 0
*/
if res_gcd != nil {
- if err = internal_abs(res_gcd, a); err != nil { return err; }
+ internal_abs(res_gcd, a) or_return;
}
if res_lcm != nil {
- if err = internal_zero(res_lcm); err != nil { return err; }
+ internal_zero(res_lcm) or_return;
}
return nil;
}
@@ -1116,8 +1128,8 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
*/
u, v := &Int{}, &Int{};
defer internal_destroy(u, v);
- if err = internal_copy(u, a); err != nil { return err; }
- if err = internal_copy(v, b); err != nil { return err; }
+ internal_copy(u, a) or_return;
+ internal_copy(v, b) or_return;
/*
Must be positive for the remainder of the algorithm.
@@ -1135,18 +1147,18 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
/*
Divide the power of two out.
*/
- if err = internal_shr(u, u, k); err != nil { return err; }
- if err = internal_shr(v, v, k); err != nil { return err; }
+ internal_shr(u, u, k) or_return;
+ internal_shr(v, v, k) or_return;
}
/*
Divide any remaining factors of two out.
*/
if u_lsb != k {
- if err = internal_shr(u, u, u_lsb - k); err != nil { return err; }
+ internal_shr(u, u, u_lsb - k) or_return;
}
if v_lsb != k {
- if err = internal_shr(v, v, v_lsb - k); err != nil { return err; }
+ internal_shr(v, v, v_lsb - k) or_return;
}
for v.used != 0 {
@@ -1163,19 +1175,19 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
/*
Subtract smallest from largest.
*/
- if err = internal_sub(v, v, u); err != nil { return err; }
+ internal_sub(v, v, u) or_return;
/*
Divide out all factors of two.
*/
b, _ := internal_count_lsb(v);
- if err = internal_shr(v, v, b); err != nil { return err; }
+ internal_shr(v, v, b) or_return;
}
/*
Multiply by 2**k which we divided out at the beginning.
*/
- if err = internal_shl(temp_gcd_res, u, k); err != nil { return err; }
+ internal_shl(temp_gcd_res, u, k) or_return;
temp_gcd_res.sign = .Zero_or_Positive;
/*
@@ -1195,13 +1207,13 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.
/*
Store quotient in `t2` such that `t2 * b` is the LCM.
*/
- if err = internal_div(res_lcm, a, temp_gcd_res); err != nil { return err; }
+ internal_div(res_lcm, a, temp_gcd_res) or_return;
err = internal_mul(res_lcm, res_lcm, b);
} else {
/*
Store quotient in `t2` such that `t2 * a` is the LCM.
*/
- if err = internal_div(res_lcm, a, temp_gcd_res); err != nil { return err; }
+ internal_div(res_lcm, a, temp_gcd_res) or_return;
err = internal_mul(res_lcm, res_lcm, b);
}
@@ -1228,12 +1240,15 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -
if ic == -1 || ic == 0 {
return 1 if ic == 0 else 0, nil;
}
+ defer if err != nil {
+ res = -1;
+ }
- if err = internal_set(bi_base, base, true, allocator); err != nil { return -1, err; }
- if err = internal_clear(bracket_mid, false, allocator); err != nil { return -1, err; }
- if err = internal_clear(t, false, allocator); err != nil { return -1, err; }
- if err = internal_one(bracket_low, false, allocator); err != nil { return -1, err; }
- if err = internal_set(bracket_high, base, false, allocator); err != nil { return -1, err; }
+ internal_set(bi_base, base, true, allocator) or_return;
+ internal_clear(bracket_mid, false, allocator) or_return;
+ internal_clear(t, false, allocator) or_return;
+ internal_one(bracket_low, false, allocator) or_return;
+ internal_set(bracket_high, base, false, allocator) or_return;
low := 0; high := 1;
@@ -1248,20 +1263,22 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -
/*
Iterate until `a` is bracketed between low + high.
*/
- if #force_inline internal_cmp(bracket_high, a) != -1 { break; }
+ if #force_inline internal_cmp(bracket_high, a) != -1 {
+ break;
+ }
low = high;
- if err = #force_inline internal_copy(bracket_low, bracket_high); err != nil { return -1, err; }
+ #force_inline internal_copy(bracket_low, bracket_high) or_return;
high <<= 1;
- if err = #force_inline internal_sqr(bracket_high, bracket_high); err != nil { return -1, err; }
+ #force_inline internal_sqr(bracket_high, bracket_high) or_return;
}
for (high - low) > 1 {
mid := (high + low) >> 1;
- if err = #force_inline internal_pow(t, bi_base, mid - low); err != nil { return -1, err; }
+ #force_inline internal_pow(t, bi_base, mid - low) or_return;
- if err = #force_inline internal_mul(bracket_mid, bracket_low, t); err != nil { return -1, err; }
+ #force_inline internal_mul(bracket_mid, bracket_low, t) or_return;
mc := #force_inline internal_cmp(a, bracket_mid);
switch mc {
@@ -1294,31 +1311,35 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
`b` cannot be negative.
*/
- if b.sign == .Negative || internal_is_zero(b) { return .Invalid_Argument; }
+ if b.sign == .Negative || internal_is_zero(b) {
+ return .Invalid_Argument;
+ }
/*
init temps.
*/
- if err = internal_init_multi(x, y, u, v, A, B, C, D); err != nil { return err; }
+ internal_init_multi(x, y, u, v, A, B, C, D) or_return;
/*
`x` = `a` % `b`, `y` = `b`
*/
- if err = internal_mod(x, a, b); err != nil { return err; }
- if err = internal_copy(y, b); err != nil { return err; }
+ internal_mod(x, a, b) or_return;
+ internal_copy(y, b) or_return;
/*
2. [modified] if x,y are both even then return an error!
*/
- if internal_is_even(x) && internal_is_even(y) { return .Invalid_Argument; }
+ if internal_is_even(x) && internal_is_even(y) {
+ return .Invalid_Argument;
+ }
/*
3. u=x, v=y, A=1, B=0, C=0, D=1
*/
- if err = internal_copy(u, x); err != nil { return err; }
- if err = internal_copy(v, y); err != nil { return err; }
- if err = internal_one(A); err != nil { return err; }
- if err = internal_one(D); err != nil { return err; }
+ internal_copy(u, x) or_return;
+ internal_copy(v, y) or_return;
+ internal_one(A) or_return;
+ internal_one(D) or_return;
for {
/*
@@ -1328,7 +1349,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
4.1 `u` = `u` / 2
*/
- if err = internal_int_shr1(u, u); err != nil { return err; }
+ internal_int_shr1(u, u) or_return;
/*
4.2 if `A` or `B` is odd then:
@@ -1337,14 +1358,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
`A` = (`A`+`y`) / 2, `B` = (`B`-`x`) / 2
*/
- if err = internal_add(A, A, y); err != nil { return err; }
- if err = internal_add(B, B, x); err != nil { return err; }
+ internal_add(A, A, y) or_return;
+ internal_add(B, B, x) or_return;
}
/*
`A` = `A` / 2, `B` = `B` / 2
*/
- if err = internal_int_shr1(A, A); err != nil { return err; }
- if err = internal_int_shr1(B, B); err != nil { return err; }
+ internal_int_shr1(A, A) or_return;
+ internal_int_shr1(B, B) or_return;
}
/*
@@ -1354,7 +1375,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
5.1 `v` = `v` / 2
*/
- if err = internal_int_shr1(v, v); err != nil { return err; }
+ internal_int_shr1(v, v) or_return;
/*
5.2 if `C` or `D` is odd then:
@@ -1363,14 +1384,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
`C` = (`C`+`y`) / 2, `D` = (`D`-`x`) / 2
*/
- if err = internal_add(C, C, y); err != nil { return err; }
- if err = internal_add(D, D, x); err != nil { return err; }
+ internal_add(C, C, y) or_return;
+ internal_add(D, D, x) or_return;
}
/*
`C` = `C` / 2, `D` = `D` / 2
*/
- if err = internal_int_shr1(C, C); err != nil { return err; }
- if err = internal_int_shr1(D, D); err != nil { return err; }
+ internal_int_shr1(C, C) or_return;
+ internal_int_shr1(D, D) or_return;
}
/*
@@ -1380,20 +1401,22 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
`u` = `u` - `v`, `A` = `A` - `C`, `B` = `B` - `D`
*/
- if err = internal_sub(u, u, v); err != nil { return err; }
- if err = internal_sub(A, A, C); err != nil { return err; }
- if err = internal_sub(B, B, D); err != nil { return err; }
+ internal_sub(u, u, v) or_return;
+ internal_sub(A, A, C) or_return;
+ internal_sub(B, B, D) or_return;
} else {
/* v - v - u, C = C - A, D = D - B */
- if err = internal_sub(v, v, u); err != nil { return err; }
- if err = internal_sub(C, C, A); err != nil { return err; }
- if err = internal_sub(D, D, B); err != nil { return err; }
+ internal_sub(v, v, u) or_return;
+ internal_sub(C, C, A) or_return;
+ internal_sub(D, D, B) or_return;
}
/*
If not zero goto step 4
*/
- if internal_is_zero(u) { break; }
+ if internal_is_zero(u) {
+ break;
+ }
}
/*
@@ -1403,20 +1426,22 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator
/*
If `v` != `1` then there is no inverse.
*/
- if internal_cmp(v, 1) != 0 { return .Invalid_Argument; }
+ if internal_cmp(v, 1) != 0 {
+ return .Invalid_Argument;
+ }
/*
If its too low.
*/
if internal_cmp(C, 0) == -1 {
- if err = internal_add(C, C, b); err != nil { return err; }
+ internal_add(C, C, b) or_return;
}
/*
Too big.
*/
if internal_cmp(C, 0) != -1 {
- if err = internal_sub(C, C, b); err != nil { return err; }
+ internal_sub(C, C, b) or_return;
}
/*
@@ -1443,35 +1468,39 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
2. [modified] `b` must be odd.
*/
- if internal_is_even(b) { return .Invalid_Argument; }
+ if internal_is_even(b) {
+ return .Invalid_Argument;
+ }
/*
Init all our temps.
*/
- if err = internal_init_multi(x, y, u, v, B, D); err != nil { return err; }
+ internal_init_multi(x, y, u, v, B, D) or_return;
/*
`x` == modulus, `y` == value to invert.
*/
- if err = internal_copy(x, b); err != nil { return err; }
+ internal_copy(x, b) or_return;
/*
We need `y` = `|a|`.
*/
- if err = internal_mod(y, a, b); err != nil { return err; }
+ internal_mod(y, a, b) or_return;
/*
If one of `x`, `y` is zero return an error!
*/
- if internal_is_zero(x) || internal_is_zero(y) { return .Invalid_Argument; }
+ if internal_is_zero(x) || internal_is_zero(y) {
+ return .Invalid_Argument;
+ }
/*
3. `u` = `x`, `v` = `y`, `A` = 1, `B` = 0, `C` = 0, `D` = 1
*/
- if err = internal_copy(u, x); err != nil { return err; }
- if err = internal_copy(v, y); err != nil { return err; }
+ internal_copy(u, x) or_return;
+ internal_copy(v, y) or_return;
- if err = internal_one(D); err != nil { return err; }
+ internal_one(D) or_return;
for {
/*
@@ -1481,7 +1510,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
4.1 `u` = `u` / 2
*/
- if err = internal_int_shr1(u, u); err != nil { return err; }
+ internal_int_shr1(u, u) or_return;
/*
4.2 if `B` is odd then:
@@ -1490,13 +1519,13 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
`B` = (`B` - `x`) / 2
*/
- if err = internal_sub(B, B, x); err != nil { return err; }
+ internal_sub(B, B, x) or_return;
}
/*
`B` = `B` / 2
*/
- if err = internal_int_shr1(B, B); err != nil { return err; }
+ internal_int_shr1(B, B) or_return;
}
/*
@@ -1506,7 +1535,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
5.1 `v` = `v` / 2
*/
- if err = internal_int_shr1(v, v); err != nil { return err; }
+ internal_int_shr1(v, v) or_return;
/*
5.2 if `D` is odd then:
@@ -1515,12 +1544,12 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
`D` = (`D` - `x`) / 2
*/
- if err = internal_sub(D, D, x); err != nil { return err; }
+ internal_sub(D, D, x) or_return;
}
/*
`D` = `D` / 2
*/
- if err = internal_int_shr1(D, D); err != nil { return err; }
+ internal_int_shr1(D, D) or_return;
}
/*
@@ -1530,20 +1559,22 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
`u` = `u` - `v`, `B` = `B` - `D`
*/
- if err = internal_sub(u, u, v); err != nil { return err; }
- if err = internal_sub(B, B, D); err != nil { return err; }
+ internal_sub(u, u, v) or_return;
+ internal_sub(B, B, D) or_return;
} else {
/*
`v` - `v` - `u`, `D` = `D` - `B`
*/
- if err = internal_sub(v, v, u); err != nil { return err; }
- if err = internal_sub(D, D, B); err != nil { return err; }
+ internal_sub(v, v, u) or_return;
+ internal_sub(D, D, B) or_return;
}
/*
If not zero goto step 4.
*/
- if internal_is_zero(u) { break; }
+ if internal_is_zero(u) {
+ break;
+ }
}
/*
@@ -1553,21 +1584,23 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc
/*
if `v` != 1 then there is no inverse
*/
- if internal_cmp(v, 1) != 0 { return .Invalid_Argument; }
+ if internal_cmp(v, 1) != 0 {
+ return .Invalid_Argument;
+ }
/*
`b` is now the inverse.
*/
sign = a.sign;
for internal_int_is_negative(D) {
- if err = internal_add(D, D, b); err != nil { return err; }
+ internal_add(D, D, b) or_return;
}
/*
Too big.
*/
for internal_cmp_mag(D, b) != -1 {
- if err = internal_sub(D, D, b); err != nil { return err; }
+ internal_sub(D, D, b) or_return;
}
swap(dest, D);
@@ -1601,7 +1634,9 @@ _private_copy_digits :: proc(dest, src: ^Int, digits: int) -> (err: Error) {
/*
If dest == src, do nothing
*/
- if dest == src { return nil; }
+ if dest == src {
+ return nil;
+ }
digits = min(digits, len(src.digit), len(dest.digit));
mem.copy_non_overlapping(&dest.digit[0], &src.digit[0], size_of(DIGIT) * digits);
diff --git a/core/math/big/public.odin b/core/math/big/public.odin
index b7a00fbc0..7804978a5 100644
--- a/core/math/big/public.odin
+++ b/core/math/big/public.odin
@@ -24,7 +24,7 @@ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, a, b); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, a, b) or_return;
/*
All parameters have been initialized.
*/
@@ -41,11 +41,11 @@ int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato
assert_if_nil(dest, a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return err; }
+ internal_clear_if_uninitialized(a) or_return;
/*
Grow destination as required.
*/
- if err = grow(dest, a.used + 1); err != nil { return err; }
+ grow(dest, a.used + 1) or_return;
/*
All parameters have been initialized.
@@ -60,7 +60,7 @@ int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) ->
assert_if_nil(dest, number, decrease);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, number, decrease); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, number, decrease) or_return;
/*
All parameters have been initialized.
*/
@@ -77,11 +77,11 @@ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato
assert_if_nil(dest, a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return err; }
+ internal_clear_if_uninitialized(a) or_return;
/*
Grow destination as required.
*/
- if err = grow(dest, a.used + 1); err != nil { return err; }
+ grow(dest, a.used + 1) or_return;
/*
All parameters have been initialized.
@@ -97,11 +97,11 @@ int_halve :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Erro
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
/*
Grow destination as required.
*/
- if dest != src { if err = grow(dest, src.used + 1); err != nil { return err; } }
+ if dest != src { grow(dest, src.used + 1) or_return }
return #force_inline internal_int_shr1(dest, src);
}
@@ -116,11 +116,11 @@ int_double :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Err
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
/*
Grow destination as required.
*/
- if dest != src { if err = grow(dest, src.used + 1); err != nil { return err; } }
+ if dest != src { grow(dest, src.used + 1) or_return; }
return #force_inline internal_int_shl1(dest, src);
}
@@ -134,7 +134,7 @@ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.a
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(src, dest); err != nil { return err; }
+ internal_clear_if_uninitialized(src, dest) or_return;
return #force_inline internal_int_mul_digit(dest, src, multiplier);
}
@@ -146,7 +146,7 @@ int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) ->
assert_if_nil(dest, src, multiplier);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src, multiplier); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src, multiplier) or_return;
return #force_inline internal_int_mul(dest, src, multiplier);
}
@@ -166,7 +166,7 @@ int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator
Early out if neither of the results is wanted.
*/
if quotient == nil && remainder == nil { return nil; }
- if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; }
+ internal_clear_if_uninitialized(numerator, denominator) or_return;
return #force_inline internal_divmod(quotient, remainder, numerator, denominator);
}
@@ -175,7 +175,7 @@ int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocato
assert_if_nil(quotient, numerator);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(numerator); err != nil { return 0, err; }
+ internal_clear_if_uninitialized(numerator) or_return;
return #force_inline internal_divmod(quotient, numerator, denominator);
}
@@ -185,7 +185,7 @@ int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.all
assert_if_nil(quotient, numerator, denominator);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; }
+ internal_clear_if_uninitialized(numerator, denominator) or_return;
return #force_inline internal_divmod(quotient, nil, numerator, denominator);
}
@@ -194,11 +194,10 @@ int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator :
assert_if_nil(quotient, numerator);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(numerator); err != nil { return err; }
+ internal_clear_if_uninitialized(numerator) or_return;
- remainder: DIGIT;
- remainder, err = #force_inline internal_divmod(quotient, numerator, denominator);
- return err;
+ _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return;
+ return;
}
div :: proc { int_div, int_div_digit, };
@@ -211,7 +210,7 @@ int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := context.al
assert_if_nil(remainder, numerator, denominator);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; }
+ internal_clear_if_uninitialized(numerator, denominator) or_return;
return #force_inline internal_int_mod(remainder, numerator, denominator);
}
@@ -229,7 +228,7 @@ int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := contex
assert_if_nil(remainder, number, addend);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(number, addend, modulus); err != nil { return err; }
+ internal_clear_if_uninitialized(number, addend, modulus) or_return;
return #force_inline internal_addmod(remainder, number, addend, modulus);
}
@@ -242,7 +241,7 @@ int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := cont
assert_if_nil(remainder, number, decrease);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(number, decrease, modulus); err != nil { return err; }
+ internal_clear_if_uninitialized(number, decrease, modulus) or_return;
return #force_inline internal_submod(remainder, number, decrease, modulus);
}
@@ -255,7 +254,7 @@ int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator :=
assert_if_nil(remainder, number, multiplicand);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(number, multiplicand, modulus); err != nil { return err; }
+ internal_clear_if_uninitialized(number, multiplicand, modulus) or_return;
return #force_inline internal_mulmod(remainder, number, multiplicand, modulus);
}
@@ -268,7 +267,7 @@ int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.alloca
assert_if_nil(remainder, number, modulus);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(number, modulus); err != nil { return err; }
+ internal_clear_if_uninitialized(number, modulus) or_return;
return #force_inline internal_sqrmod(remainder, number, modulus);
}
@@ -312,14 +311,14 @@ int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) -
n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{};
defer internal_destroy(n_fac, k_fac, n_minus_k_fac);
- if err = #force_inline internal_int_factorial(n_minus_k_fac, n - k); err != nil { return err; }
- if err = #force_inline internal_int_factorial(k_fac, k); err != nil { return err; }
- if err = #force_inline internal_mul(k_fac, k_fac, n_minus_k_fac); err != nil { return err; }
+ #force_inline internal_int_factorial(n_minus_k_fac, n - k) or_return;
+ #force_inline internal_int_factorial(k_fac, k) or_return;
+ #force_inline internal_mul(k_fac, k_fac, n_minus_k_fac) or_return;
- if err = #force_inline internal_int_factorial(n_fac, n); err != nil { return err; }
- if err = #force_inline internal_div(res, n_fac, k_fac); err != nil { return err; }
+ #force_inline internal_int_factorial(n_fac, n) or_return;
+ #force_inline internal_div(res, n_fac, k_fac) or_return;
- return err;
+ return;
}
choose :: proc { int_choose_digit, };
@@ -331,7 +330,7 @@ int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator
assert_if_nil(a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b);
}
gcd_lcm :: proc { int_gcd_lcm, };
@@ -359,8 +358,8 @@ int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator := context
assert_if_nil(remainder, numerator);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(remainder, numerator); err != nil { return err; }
- if bits < 0 { return .Invalid_Argument; }
+ internal_clear_if_uninitialized(remainder, numerator) or_return;
+ if bits < 0 { return .Invalid_Argument; }
return #force_inline internal_int_mod_bits(remainder, numerator, bits);
}
@@ -375,7 +374,7 @@ int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: i
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return 0, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_int_log(a, base);
}
@@ -392,7 +391,7 @@ int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) ->
assert_if_nil(dest, base);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, base); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, base) or_return;
return #force_inline internal_int_pow(dest, base, power);
}
@@ -420,7 +419,7 @@ int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, src);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
return #force_inline internal_int_sqrt(dest, src);
}
@@ -446,7 +445,7 @@ int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (
/*
Initialize dest + src if needed.
*/
- if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; }
+ internal_clear_if_uninitialized(dest, src) or_return;
return #force_inline internal_int_root_n(dest, src, n);
}
@@ -466,7 +465,7 @@ int_is_zero :: proc(a: ^Int, allocator := context.allocator) -> (zero: bool, err
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_zero(a), nil;
}
@@ -475,7 +474,7 @@ int_is_positive :: proc(a: ^Int, allocator := context.allocator) -> (positive: b
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_positive(a), nil;
}
@@ -484,7 +483,7 @@ int_is_negative :: proc(a: ^Int, allocator := context.allocator) -> (negative: b
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_negative(a), nil;
}
@@ -493,7 +492,7 @@ int_is_even :: proc(a: ^Int, allocator := context.allocator) -> (even: bool, err
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_even(a), nil;
}
@@ -502,7 +501,7 @@ int_is_odd :: proc(a: ^Int, allocator := context.allocator) -> (odd: bool, err:
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_odd(a), nil;
}
@@ -515,7 +514,7 @@ int_is_power_of_two :: proc(a: ^Int, allocator := context.allocator) -> (res: bo
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return false, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_is_power_of_two(a), nil;
}
@@ -527,7 +526,7 @@ int_compare :: proc(a, b: ^Int, allocator := context.allocator) -> (comparison:
assert_if_nil(a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return 0, err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_cmp(a, b), nil;
}
@@ -540,7 +539,7 @@ int_compare_digit :: proc(a: ^Int, b: DIGIT, allocator := context.allocator) ->
assert_if_nil(a);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a); err != nil { return 0, err; }
+ internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_cmp_digit(a, b), nil;
}
@@ -553,7 +552,7 @@ int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (re
assert_if_nil(a, b);
context.allocator = allocator;
- if err = internal_clear_if_uninitialized(a, b); err != nil { return 0, err; }
+ internal_clear_if_uninitialized(a, b) or_return;
return #force_inline internal_cmp_mag(a, b), nil;
}
\ No newline at end of file
diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin
index 01c0489d8..e7eee9513 100644
--- a/core/math/big/radix.odin
+++ b/core/math/big/radix.odin
@@ -26,7 +26,7 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc
context.allocator = allocator;
a := a; radix := radix;
- if err = clear_if_uninitialized(a); err != nil { return "", err; }
+ clear_if_uninitialized(a) or_return;
/*
Radix defaults to 10.
*/
@@ -39,14 +39,9 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc
/*
Calculate the size of the buffer we need, and
- */
- size: int;
- /*
Exit if calculating the size returned an error.
*/
- if size, err = radix_size(a, radix, zero_terminate); err != nil {
- return "", err;
- }
+ size := radix_size(a, radix, zero_terminate) or_return;
/*
Allocate the buffer we need.
@@ -70,7 +65,7 @@ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocato
context.allocator = allocator;
a := a; radix := radix;
- if err = clear_if_uninitialized(a); err != nil { return "", err; }
+ clear_if_uninitialized(a) or_return;
/*
Radix defaults to 10.
*/
@@ -104,7 +99,7 @@ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocato
int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_terminate := false) -> (written: int, err: Error) {
assert_if_nil(a);
a := a; radix := radix; size := size;
- if err = clear_if_uninitialized(a); err != nil { return 0, err; }
+ clear_if_uninitialized(a) or_return;
/*
Radix defaults to 10.
*/
@@ -117,9 +112,7 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter
We weren't given a size. Let's compute it.
*/
if size == -1 {
- if size, err = radix_size(a, radix, zero_terminate); err != nil {
- return 0, err;
- }
+ size = radix_size(a, radix, zero_terminate) or_return;
}
/*
@@ -256,12 +249,14 @@ int_atoi :: proc(res: ^Int, input: string, radix: i8, allocator := context.alloc
/*
Set the integer to the default of zero.
*/
- if err = internal_zero(res); err != nil { return err; }
+ internal_zero(res) or_return;
/*
We'll interpret an empty string as zero.
*/
- if len(input) == 0 { return nil; }
+ if len(input) == 0 {
+ return nil;
+ }
/*
If the leading digit is a minus set the sign to negative.
@@ -301,8 +296,8 @@ int_atoi :: proc(res: ^Int, input: string, radix: i8, allocator := context.alloc
break;
}
- if err = internal_mul(res, res, DIGIT(radix)); err != nil { return err; }
- if err = internal_add(res, res, DIGIT(y)); err != nil { return err; }
+ internal_mul(res, res, DIGIT(radix)) or_return;
+ internal_add(res, res, DIGIT(y)) or_return;
input = input[1:];
}
@@ -333,7 +328,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con
assert_if_nil(a);
if radix < 2 || radix > 64 { return -1, .Invalid_Argument; }
- if err = clear_if_uninitialized(a); err != nil { return {}, err; }
+ clear_if_uninitialized(a) or_return;
if internal_is_zero(a) {
if zero_terminate {
@@ -352,22 +347,22 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con
digit = a.digit,
};
- if size, err = internal_log(t, DIGIT(radix)); err != nil { return {}, err; }
+ size = internal_log(t, DIGIT(radix)) or_return;
} else {
la, k := &Int{}, &Int{};
defer internal_destroy(la, k);
/* la = floor(log_2(a)) + 1 */
bit_count := internal_count_bits(a);
- if err = internal_set(la, bit_count); err != nil { return {}, err; }
+ internal_set(la, bit_count) or_return;
/* k = floor(2^29/log_2(radix)) + 1 */
lb := _log_bases;
- if err = internal_set(k, lb[radix]); err != nil { return {}, err; }
+ internal_set(k, lb[radix]) or_return;
/* n = floor((la * k) / 2^29) + 1 */
- if err = internal_mul(k, la, k); err != nil { return 0, err; }
- if err = internal_shr(k, k, _RADIX_SIZE_SCALE); err != nil { return {}, err; }
+ internal_mul(k, la, k) or_return;
+ internal_shr(k, k, _RADIX_SIZE_SCALE) or_return;
/* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */
/* n = n + 1 + EOS + sign */
@@ -440,8 +435,8 @@ _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false
temp, denominator := &Int{}, &Int{};
- if err = internal_copy(temp, a); err != nil { return 0, err; }
- if err = internal_set(denominator, radix); err != nil { return 0, err; }
+ internal_copy(temp, a) or_return;
+ internal_set(denominator, radix) or_return;
available := len(buffer);
if zero_terminate {
diff --git a/core/math/big/test.odin b/core/math/big/test.odin
index 64d822ee1..a57625d79 100644
--- a/core/math/big/test.odin
+++ b/core/math/big/test.odin
@@ -49,7 +49,7 @@ PyRes :: struct {
if bb.used == 1 {
if err = #force_inline internal_add(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; }
} else {
- if err = #force_inline internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; }
+ if err = #force_inline internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; }
}
r: cstring;
@@ -70,7 +70,7 @@ PyRes :: struct {
if bb.used == 1 {
if err = #force_inline internal_sub(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; }
} else {
- if err = #force_inline internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; }
+ if err = #force_inline internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; }
}
r: cstring;
@@ -88,7 +88,7 @@ PyRes :: struct {
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":mul:atoi(a):", err=err}; }
if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":mul:atoi(b):", err=err}; }
- if err = #force_inline internal_mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err}; }
+ if err = #force_inline internal_mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(product, 16, context.temp_allocator);
@@ -104,7 +104,7 @@ PyRes :: struct {
defer internal_destroy(aa, square);
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sqr:atoi(a):", err=err}; }
- if err = #force_inline internal_sqr(square, aa); err != nil { return PyRes{res=":sqr:sqr(square,a):", err=err}; }
+ if err = #force_inline internal_sqr(square, aa); err != nil { return PyRes{res=":sqr:sqr(square,a):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(square, 16, context.temp_allocator);
@@ -124,7 +124,7 @@ PyRes :: struct {
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":div:atoi(a):", err=err}; }
if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":div:atoi(b):", err=err}; }
- if err = #force_inline internal_div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err}; }
+ if err = #force_inline internal_div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(quotient, 16, context.temp_allocator);
@@ -145,7 +145,7 @@ PyRes :: struct {
defer internal_destroy(aa);
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err}; }
- if l, err = #force_inline internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; }
+ if l, err = #force_inline internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; }
#force_inline internal_zero(aa);
aa.digit[0] = DIGIT(l) & _MASK;
@@ -170,7 +170,7 @@ PyRes :: struct {
defer internal_destroy(dest, bb);
if err = atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", err=err}; }
- if err = #force_inline internal_pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err}; }
+ if err = #force_inline internal_pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(dest, 16, context.temp_allocator);
@@ -189,7 +189,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(src):", err=err}; }
- if err = #force_inline internal_sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err}; }
+ if err = #force_inline internal_sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -208,7 +208,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(src):", err=err}; }
- if err = #force_inline internal_root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err}; }
+ if err = #force_inline internal_root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -227,7 +227,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err}; }
- if err = #force_inline internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err}; }
+ if err = #force_inline internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -246,7 +246,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err}; }
- if err = #force_inline internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err}; }
+ if err = #force_inline internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -265,7 +265,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", err=err}; }
- if err = #force_inline internal_shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err}; }
+ if err = #force_inline internal_shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -284,7 +284,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", err=err}; }
- if err = #force_inline internal_shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err}; }
+ if err = #force_inline internal_shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -303,7 +303,7 @@ PyRes :: struct {
defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", err=err}; }
- if err = #force_inline internal_shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err}; }
+ if err = #force_inline internal_shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err}; }
r: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator);
diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin
index b213c4b74..9d41a0adc 100644
--- a/core/odin/ast/ast.odin
+++ b/core/odin/ast/ast.odin
@@ -241,15 +241,6 @@ Field_Value :: struct {
value: ^Expr,
}
-Ternary_Expr :: struct {
- using node: Expr,
- cond: ^Expr,
- op1: tokenizer.Token,
- x: ^Expr,
- op2: tokenizer.Token,
- y: ^Expr,
-}
-
Ternary_If_Expr :: struct {
using node: Expr,
x: ^Expr,
@@ -261,13 +252,26 @@ Ternary_If_Expr :: struct {
Ternary_When_Expr :: struct {
using node: Expr,
- x: ^Expr,
+ x: ^Expr,
op1: tokenizer.Token,
cond: ^Expr,
op2: tokenizer.Token,
y: ^Expr,
}
+Or_Else_Expr :: struct {
+ using node: Expr,
+ x: ^Expr,
+ token: tokenizer.Token,
+ y: ^Expr,
+}
+
+Or_Return_Expr :: struct {
+ using node: Expr,
+ expr: ^Expr,
+ token: tokenizer.Token,
+}
+
Type_Assertion :: struct {
using node: Expr,
expr: ^Expr,
@@ -542,7 +546,7 @@ Field_Flag :: enum {
No_Alias,
C_Vararg,
Auto_Cast,
- In,
+ Any_Int,
Results,
Tags,
diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin
index e9344e0b4..e80a4d05f 100644
--- a/core/odin/ast/clone.odin
+++ b/core/odin/ast/clone.odin
@@ -129,10 +129,6 @@ clone_node :: proc(node: ^Node) -> ^Node {
case Field_Value:
r.field = clone(r.field);
r.value = clone(r.value);
- case Ternary_Expr:
- r.cond = clone(r.cond);
- r.x = clone(r.x);
- r.y = clone(r.y);
case Ternary_If_Expr:
r.x = clone(r.x);
r.cond = clone(r.cond);
@@ -141,6 +137,11 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.x = clone(r.x);
r.cond = clone(r.cond);
r.y = clone(r.y);
+ case Or_Else_Expr:
+ r.x = clone(r.x);
+ r.y = clone(r.y);
+ case Or_Return_Expr:
+ r.expr = clone(r.expr);
case Type_Assertion:
r.expr = clone(r.expr);
r.type = clone(r.type);
diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin
index 9f60b7e7d..c64d4d29c 100644
--- a/core/odin/ast/walk.odin
+++ b/core/odin/ast/walk.odin
@@ -126,10 +126,6 @@ walk :: proc(v: ^Visitor, node: ^Node) {
case Field_Value:
walk(v, n.field);
walk(v, n.value);
- case Ternary_Expr:
- walk(v, n.cond);
- walk(v, n.x);
- walk(v, n.y);
case Ternary_If_Expr:
walk(v, n.x);
walk(v, n.cond);
@@ -138,6 +134,11 @@ walk :: proc(v: ^Visitor, node: ^Node) {
walk(v, n.x);
walk(v, n.cond);
walk(v, n.y);
+ case Or_Else_Expr:
+ walk(v, n.x);
+ walk(v, n.y);
+ case Or_Return_Expr:
+ walk(v, n.expr);
case Type_Assertion:
walk(v, n.expr);
if n.type != nil {
diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin
index db3d84d2b..5021ee3df 100644
--- a/core/odin/parser/parser.odin
+++ b/core/odin/parser/parser.odin
@@ -374,11 +374,14 @@ expect_token_after :: proc(p: ^Parser, kind: tokenizer.Token_Kind, msg: string)
expect_operator :: proc(p: ^Parser) -> tokenizer.Token {
prev := p.curr_tok;
- if prev.kind == .If || prev.kind == .When {
+ #partial switch prev.kind {
+ case .If, .When, .Or_Else, .Or_Return:
// okay
- } else if !tokenizer.is_operator(prev.kind) {
- g := tokenizer.token_to_string(prev);
- error(p, prev.pos, "expected an operator, got '%s'", g);
+ case:
+ if !tokenizer.is_operator(prev.kind) {
+ g := tokenizer.token_to_string(prev);
+ error(p, prev.pos, "expected an operator, got '%s'", g);
+ }
}
advance_token(p);
return prev;
@@ -1366,9 +1369,9 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
stmt := parse_stmt(p);
switch name {
case "bounds_check":
- stmt.state_flags |= {.Bounds_Check};
+ stmt.state_flags += {.Bounds_Check};
case "no_bounds_check":
- stmt.state_flags |= {.No_Bounds_Check};
+ stmt.state_flags += {.No_Bounds_Check};
}
return stmt;
case "partial":
@@ -1449,7 +1452,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
token_precedence :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> int {
#partial switch kind {
- case .Question, .If, .When:
+ case .Question, .If, .When, .Or_Else, .Or_Return:
return 1;
case .Ellipsis, .Range_Half, .Range_Full:
if !p.allow_range {
@@ -1578,8 +1581,8 @@ Field_Prefix :: enum {
Using,
No_Alias,
C_Vararg,
- In,
Auto_Cast,
+ Any_Int,
}
Field_Prefixes :: distinct bit_set[Field_Prefix];
@@ -1626,19 +1629,15 @@ convert_to_ident_list :: proc(p: ^Parser, list: []Expr_And_Flags, ignore_flags,
}
is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
- using Field_Prefix;
#partial switch p.curr_tok.kind {
case .EOF:
- return Invalid;
+ return .Invalid;
case .Using:
advance_token(p);
- return Using;
- case .In:
- advance_token(p);
- return In;
+ return .Using;
case .Auto_Cast:
advance_token(p);
- return Auto_Cast;
+ return .Auto_Cast;
case .Hash:
advance_token(p);
defer advance_token(p);
@@ -1646,14 +1645,16 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
case .Ident:
switch p.curr_tok.text {
case "no_alias":
- return No_Alias;
+ return .No_Alias;
case "c_vararg":
- return C_Vararg;
+ return .C_Vararg;
+ case "any_int":
+ return .Any_Int;
}
}
- return Unknown;
+ return .Unknown;
}
- return Invalid;
+ return .Invalid;
}
parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags {
@@ -1677,24 +1678,23 @@ parse_field_prefixes :: proc(p: ^Parser) -> ast.Field_Flags {
for kind in Field_Prefix {
count := counts[kind];
- using Field_Prefix;
switch kind {
- case Invalid, Unknown: // Ignore
- case Using:
+ case .Invalid, .Unknown: // Ignore
+ case .Using:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list"); }
- if count > 0 { flags |= {.Using}; }
- case No_Alias:
+ if count > 0 { flags += {.Using}; }
+ case .No_Alias:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list"); }
- if count > 0 { flags |= {.No_Alias}; }
- case C_Vararg:
+ if count > 0 { flags += {.No_Alias}; }
+ case .C_Vararg:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list"); }
- if count > 0 { flags |= {.C_Vararg}; }
- case In:
- if count > 1 { error(p, p.curr_tok.pos, "multiple 'in' in this field list"); }
- if count > 0 { flags |= {.In}; }
- case Auto_Cast:
+ if count > 0 { flags += {.C_Vararg}; }
+ case .Auto_Cast:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'auto_cast' in this field list"); }
- if count > 0 { flags |= {.Auto_Cast}; }
+ if count > 0 { flags += {.Auto_Cast}; }
+ case .Any_Int:
+ if count > 1 { error(p, p.curr_tok.pos, "multiple '#any_int' in this field list"); }
+ if count > 0 { flags += {.Any_Int}; }
}
}
@@ -1705,7 +1705,7 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se
flags = set_flags;
if name_count > 1 && .Using in flags {
error(p, p.curr_tok.pos, "cannot apply 'using' to more than one of the same type");
- flags &~= {.Using};
+ flags -= {.Using};
}
for flag in ast.Field_Flag {
@@ -1719,12 +1719,12 @@ check_field_flag_prefixes :: proc(p: ^Parser, name_count: int, allowed_flags, se
error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list");
case .Auto_Cast:
error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list");
- case .In:
- error(p, p.curr_tok.pos, "'in' is not allowed within this field list");
+ case .Any_Int:
+ error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list");
case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token:
panic("Impossible prefixes");
}
- flags &~= {flag};
+ flags -= {flag};
}
}
@@ -2062,10 +2062,10 @@ parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) {
ident := expect_token(p, .Ident);
switch ident.text {
- case "bounds_check": tags |= {.Bounds_Check};
- case "no_bounds_check": tags |= {.No_Bounds_Check};
- case "optional_ok": tags |= {.Optional_Ok};
- case "optional_second": tags |= {.Optional_Second};
+ case "bounds_check": tags += {.Bounds_Check};
+ case "no_bounds_check": tags += {.No_Bounds_Check};
+ case "optional_ok": tags += {.Optional_Ok};
+ case "optional_second": tags += {.Optional_Second};
case:
}
}
@@ -2267,12 +2267,12 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
switch name.text {
case "bounds_check":
- operand.state_flags |= {.Bounds_Check};
+ operand.state_flags += {.Bounds_Check};
if .No_Bounds_Check in operand.state_flags {
error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together");
}
case "no_bounds_check":
- operand.state_flags |= {.No_Bounds_Check};
+ operand.state_flags += {.No_Bounds_Check};
if .Bounds_Check in operand.state_flags {
error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together");
}
@@ -3156,16 +3156,18 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr {
}
for prec := token_precedence(p, p.curr_tok.kind); prec >= prec_in; prec -= 1 {
- for {
+ loop: for {
op := p.curr_tok;
op_prec := token_precedence(p, op.kind);
if op_prec != prec {
- break;
+ break loop;
}
- if op.kind == .If || op.kind == .When {
+
+ #partial switch op.kind {
+ case .If, .When, .Or_Return, .Or_Else:
if p.prev_tok.pos.line < op.pos.line {
// NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
- break;
+ break loop;
}
}
@@ -3178,7 +3180,7 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr {
x := parse_expr(p, lhs);
colon := expect_token(p, .Colon);
y := parse_expr(p, lhs);
- te := ast.new(ast.Ternary_Expr, expr.pos, end_pos(p.prev_tok));
+ te := ast.new(ast.Ternary_If_Expr, expr.pos, end_pos(p.prev_tok));
te.cond = cond;
te.op1 = op;
te.x = x;
@@ -3212,6 +3214,21 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr {
te.y = y;
expr = te;
+ case .Or_Else:
+ x := expr;
+ y := parse_expr(p, lhs);
+ oe := ast.new(ast.Or_Else_Expr, expr.pos, end_pos(p.prev_tok));
+ oe.x = x;
+ oe.token = op;
+ oe.y = y;
+
+ expr = oe;
+ case .Or_Return:
+ oe := ast.new(ast.Or_Return_Expr, expr.pos, end_pos(p.prev_tok));
+ oe.expr = expr;
+ oe.token = op;
+
+ expr = oe;
case:
right := parse_binary_expr(p, false, prec+1);
if right == nil {
diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin
index 3eab3b4b3..a6c3d9106 100644
--- a/core/odin/printer/visit.odin
+++ b/core/odin/printer/visit.odin
@@ -944,12 +944,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
case Auto_Cast:
push_generic_token(p, v.op.kind, 1);
visit_expr(p, v.expr);
- case Ternary_Expr:
- visit_expr(p, v.cond);
- push_generic_token(p, v.op1.kind, 1);
- visit_expr(p, v.x);
- push_generic_token(p, v.op2.kind, 1);
- visit_expr(p, v.y);
case Ternary_If_Expr:
visit_expr(p, v.x);
push_generic_token(p, v.op1.kind, 1);
@@ -962,6 +956,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
visit_expr(p, v.cond);
push_generic_token(p, v.op2.kind, 1);
visit_expr(p, v.y);
+ case Or_Else_Expr:
+ visit_expr(p, v.x);
+ push_generic_token(p, v.token.kind, 1);
+ visit_expr(p, v.y);
+ case Or_Return_Expr:
+ visit_expr(p, v.expr);
+ push_generic_token(p, v.token.kind, 1);
case Selector_Call_Expr:
visit_expr(p, v.call.expr);
push_generic_token(p, .Open_Paren, 1);
diff --git a/core/odin/tokenizer/token.odin b/core/odin/tokenizer/token.odin
index 61aa351dd..5283ab590 100644
--- a/core/odin/tokenizer/token.odin
+++ b/core/odin/tokenizer/token.odin
@@ -144,10 +144,12 @@ Token_Kind :: enum u32 {
Transmute, // transmute
Distinct, // distinct
Using, // using
+ Context, // context
+ Or_Else, // or_else
+ Or_Return, // or_return
+ Asm, // asm
Inline, // inline
No_Inline, // no_inline
- Context, // context
- Asm, // asm
B_Keyword_End,
COUNT,
@@ -272,10 +274,12 @@ tokens := [Token_Kind.COUNT]string {
"transmute",
"distinct",
"using",
+ "context",
+ "or_else",
+ "or_return",
+ "asm",
"inline",
"no_inline",
- "context",
- "asm",
"",
};
diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin
index f8a9c2c95..5d69cf3a9 100644
--- a/core/odin/tokenizer/tokenizer.odin
+++ b/core/odin/tokenizer/tokenizer.odin
@@ -724,7 +724,7 @@ scan :: proc(t: ^Tokenizer) -> Token {
case .Ident, .Context, .Typeid, .Break, .Continue, .Fallthrough, .Return,
.Integer, .Float, .Imag, .Rune, .String, .Undef,
.Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace,
- .Increment, .Decrement:
+ .Increment, .Decrement, .Or_Return:
/*fallthrough*/
t.insert_semicolon = true;
case:
diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin
index b7e89b493..8dcfe8dd0 100644
--- a/core/os/os2/errors.odin
+++ b/core/os/os2/errors.odin
@@ -57,7 +57,7 @@ link_error_delete :: proc(lerr: Maybe(Link_Error)) {
is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
- v := or_else(ferr.(Platform_Error), {});
+ v := ferr.(Platform_Error) or_else {};
return v.err, v.err != 0;
}
diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin
index 936d9da57..849f0866e 100644
--- a/core/os/os2/file_stream.odin
+++ b/core/os/os2/file_stream.odin
@@ -13,7 +13,7 @@ error_to_io_error :: proc(ferr: Error) -> io.Error {
if ferr == nil {
return .None;
}
- return or_else(ferr.(io.Error), .Unknown);
+ return ferr.(io.Error) or_else .Unknown;
}
diff --git a/core/path/filepath/match.odin b/core/path/filepath/match.odin
index 1446ceb4d..de65a9d41 100644
--- a/core/path/filepath/match.odin
+++ b/core/path/filepath/match.odin
@@ -298,10 +298,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string) -> (m: [dynamic]s
for fi in fis {
n := fi.name;
- matched, err := match(pattern, n);
- if err != nil {
- return m, err;
- }
+ matched := match(pattern, n) or_return;
if matched {
append(&m, join(dir, n));
}
diff --git a/core/sync/sync2/primitives_pthreads.odin b/core/sync/sync2/primitives_pthreads.odin
index 7e45e0565..d0484e09e 100644
--- a/core/sync/sync2/primitives_pthreads.odin
+++ b/core/sync/sync2/primitives_pthreads.odin
@@ -129,7 +129,7 @@ _Recursive_Mutex :: struct {
}
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
- tid := runtime.current_thread_id();
+ tid := _current_thread_id();
if tid != m.impl.owner {
mutex_lock(&m.impl.mutex);
}
diff --git a/core/testing/runner_windows.odin b/core/testing/runner_windows.odin
index 03ae9ede9..255d44f1b 100644
--- a/core/testing/runner_windows.odin
+++ b/core/testing/runner_windows.odin
@@ -68,7 +68,7 @@ Thread_Os_Specific :: struct {
thread_create :: proc(procedure: Thread_Proc) -> ^Thread {
__windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD {
t := (^Thread)(t_);
- context = or_else(t.init_context.?, runtime.default_context());
+ context = t.init_context.? or_else runtime.default_context();
t.procedure(t);
diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin
index ef17596b8..fa82832ec 100644
--- a/core/thread/thread_unix.odin
+++ b/core/thread/thread_unix.odin
@@ -46,7 +46,7 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
t.start_gate = {};
t.start_mutex = {};
- context = or_else(t.init_context.?, runtime.default_context());
+ context = t.init_context.? or_else runtime.default_context();
t.procedure(t);
diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin
index ad834ddc7..1dfa0c0b6 100644
--- a/core/thread/thread_windows.odin
+++ b/core/thread/thread_windows.odin
@@ -23,7 +23,7 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
__windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD {
t := (^Thread)(t_);
- context = or_else(t.init_context.?, runtime.default_context());
+ context = t.init_context.? or_else runtime.default_context();
t.procedure(t);
diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin
index 9baff266c..e04cf7d49 100644
--- a/examples/all/all_main.odin
+++ b/examples/all/all_main.odin
@@ -3,57 +3,57 @@ package all
// Imports every package
// This is useful for knowing what exists and producing documentation with `odin doc`
-import "core:bufio"
-import "core:bytes"
-import "core:c"
-import c_tokenizer "core:c/frontend/tokenizer"
+import bufio "core:bufio"
+import bytes "core:bytes"
+import c "core:c"
+import c_tokenizer "core:c/frontend/tokenizer"
import c_preprocessor "core:c/frontend/preprocessor"
-import "core:compress"
-import "core:compress/gzip"
-import "core:compress/zlib"
-import "core:container"
-import "core:dynlib"
-import "core:encoding"
-import "core:encoding/base32"
-import "core:encoding/base64"
-import "core:encoding/csv"
-import "core:encoding/hxa"
-import "core:encoding/json"
-import "core:fmt"
-import "core:hash"
-import "core:image"
-import "core:image/png"
-import "core:io"
-import "core:log"
-import "core:math"
-import "core:math/big"
-import "core:math/bits"
-import "core:math/fixed"
-import "core:math/linalg"
-import "core:math/rand"
-import "core:mem"
-import "core:odin/ast"
-import doc_format "core:odin/doc-format"
-import "core:odin/format"
-import "core:odin/parser"
-import "core:odin/printer"
+import compress "core:compress"
+import gzip "core:compress/gzip"
+import zlib "core:compress/zlib"
+import container "core:container"
+import dynlib "core:dynlib"
+import encoding "core:encoding"
+import base32 "core:encoding/base32"
+import base64 "core:encoding/base64"
+import csv "core:encoding/csv"
+import hxa "core:encoding/hxa"
+import json "core:encoding/json"
+import fmt "core:fmt"
+import hash "core:hash"
+import image "core:image"
+import png "core:image/png"
+import io "core:io"
+import log "core:log"
+import math "core:math"
+import big "core:math/big"
+import bits "core:math/bits"
+import fixed "core:math/fixed"
+import linalg "core:math/linalg"
+import rand "core:math/rand"
+import mem "core:mem"
+import ast "core:odin/ast"
+import doc_format "core:odin/doc-format"
+import odin_format "core:odin/format"
+import odin_parser "core:odin/parser"
+import odin_printer "core:odin/printer"
import odin_tokenizer "core:odin/tokenizer"
-import "core:os"
-import "core:path"
-import "core:path/filepath"
-import "core:reflect"
-import "core:runtime"
-import "core:slice"
-import "core:sort"
-import "core:strconv"
-import "core:strings"
-import "core:sync"
-import "core:sync/sync2"
-import "core:text/scanner"
-import "core:thread"
-import "core:time"
-import "core:unicode"
-import "core:unicode/utf8"
-import "core:unicode/utf16"
+import os "core:os"
+import path "core:path"
+import filepath "core:path/filepath"
+import reflect "core:reflect"
+import runtime "core:runtime"
+import slice "core:slice"
+import sort "core:sort"
+import strconv "core:strconv"
+import strings "core:strings"
+import sync "core:sync"
+import sync2 "core:sync/sync2"
+import scanner "core:text/scanner"
+import thread "core:thread"
+import time "core:time"
+import unicode "core:unicode"
+import utf8 "core:unicode/utf8"
+import utf16 "core:unicode/utf16"
main :: proc(){}
diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin
index 2590fdc01..ccbfea75d 100644
--- a/examples/demo/demo.odin
+++ b/examples/demo/demo.odin
@@ -1998,9 +1998,9 @@ relative_data_types :: proc() {
fmt.println(rel_slice[1]);
}
-or_else_procedure :: proc() {
+or_else_operator :: proc() {
fmt.println("\n#'or_else'");
- // IMPORTANT NOTE: 'or_else' is experimental features and subject to change/removal
+ // IMPORTANT NOTE: 'or_else' is an experimental feature and subject to change/removal
{
m: map[string]int;
i: int;
@@ -2010,7 +2010,7 @@ or_else_procedure :: proc() {
i = 123;
}
// The above can be mapped to 'or_else'
- i = or_else(m["hellope"], 123);
+ i = m["hellope"] or_else 123;
assert(i == 123);
}
@@ -2019,16 +2019,117 @@ or_else_procedure :: proc() {
// have optional ok semantics
v: union{int, f64};
i: int;
- i = or_else(v.(int), 123);
- i = or_else(v.?, 123); // Type inference magic
+ i = v.(int) or_else 123;
+ i = v.? or_else 123; // Type inference magic
assert(i == 123);
m: Maybe(int);
- i = or_else(m.?, 456);
+ i = m.? or_else 456;
assert(i == 456);
}
}
+or_return_operator :: proc() {
+ fmt.println("\n#'or_return'");
+ // IMPORTANT NOTE: 'or_return' is an experimental feature and subject to change/removal
+ //
+ // The concept of 'or_return' will work by popping off the end value in a multiple
+ // valued expression and checking whether it was not 'nil' or 'false', and if so,
+ // set the end return value to value if possible. If the procedure only has one
+ // return value, it will do a simple return. If the procedure had multiple return
+ // values, 'or_return' will require that all parameters be named so that the end
+ // value could be assigned to by name and then an empty return could be called.
+
+ Error :: enum {
+ None,
+ Something_Bad,
+ Something_Worse,
+ The_Worst,
+ Your_Mum,
+ };
+
+ caller_1 :: proc() -> Error {
+ return .None;
+ }
+
+ caller_2 :: proc() -> (int, Error) {
+ return 123, .None;
+ }
+ caller_3 :: proc() -> (int, int, Error) {
+ return 123, 345, .None;
+ }
+
+ foo_1 :: proc() -> Error {
+ // This can be a common idiom in many code bases
+ n0, err := caller_2();
+ if err != nil {
+ return err;
+ }
+
+ // The above idiom can be transformed into the following
+ n1 := caller_2() or_return;
+
+
+ // And if the expression is 1-valued, it can be used like this
+ caller_1() or_return;
+ // which is functionally equivalent to
+ if err1 := caller_1(); err1 != nil {
+ return err1;
+ }
+
+ // Multiple return values still work with 'or_return' as it only
+ // pops off the end value in the multi-valued expression
+ n0, n1 = caller_3() or_return;
+
+ return .None;
+ }
+ foo_2 :: proc() -> (n: int, err: Error) {
+ // It is more common that your procedure turns multiple values
+ // If 'or_return' is used within a procedure multiple parameters (2+),
+ // then all the parameters must be named so that the remaining parameters
+ // so that a bare 'return' statement can be used
+
+ // This can be a common idiom in many code bases
+ x: int;
+ x, err = caller_2();
+ if err != nil {
+ return;
+ }
+
+ // The above idiom can be transformed into the following
+ y := caller_2() or_return;
+ _ = y;
+
+ // And if the expression is 1-valued, it can be used like this
+ caller_1() or_return;
+
+ // which is functionally equivalent to
+ if err1 := caller_1(); err1 != nil {
+ err = err1;
+ return;
+ }
+
+ // If using a non-bare 'return' statement is required, setting the return values
+ // using the normal idiom is a better choice and clearer to read.
+ if z, zerr := caller_2(); zerr != nil {
+ return -345 * z, zerr;
+ }
+
+ // If the other return values need to be set depending on what the end value is,
+ // the 'defer if' idiom is can be used
+ defer if err != nil {
+ n = -1;
+ }
+
+ n = 123;
+ return;
+ }
+
+ foo_1();
+ foo_2();
+}
+
+
main :: proc() {
when true {
the_basics();
@@ -2061,7 +2162,7 @@ main :: proc() {
union_maybe();
explicit_context_definition();
relative_data_types();
- or_else_procedure();
+ or_else_operator();
+ or_return_operator();
}
}
-//
\ No newline at end of file
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 846bea296..e1615ce87 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -48,6 +48,17 @@ BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_boolean_end -
};
+void check_or_else_right_type(CheckerContext *c, Ast *expr, String const &name, Type *right_type) {
+ if (right_type == nullptr) {
+ return;
+ }
+ if (!is_type_boolean(right_type) && !type_has_nil(right_type)) {
+ gbString str = type_to_string(right_type);
+ error(expr, "'%.*s' expects an \"optional ok\" like value, or an n-valued expression where the last value is either a boolean or can be compared against 'nil', got %s", LIT(name), str);
+ gb_string_free(str);
+ }
+}
+
void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_) {
Type *left_type = nullptr;
Type *right_type = nullptr;
@@ -70,15 +81,11 @@ void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name
if (left_type_) *left_type_ = left_type;
if (right_type_) *right_type_ = right_type;
- if (!is_type_boolean(right_type)) {
- gbString str = type_to_string(right_type);
- error(x->expr, "'%.*s' expects an \"optional ok\" like value, got %s", LIT(name), str);
- gb_string_free(str);
- }
+ check_or_else_right_type(c, x->expr, name, right_type);
}
-void check_try_expr_no_value_error(CheckerContext *c, String const &name, Operand const &x, Type *type_hint) {
+void check_or_else_expr_no_value_error(CheckerContext *c, String const &name, Operand const &x, Type *type_hint) {
// TODO(bill): better error message
gbString t = type_to_string(x.type);
error(x.expr, "'%.*s' does not return a value, value is of type %s", LIT(name), t);
@@ -108,6 +115,33 @@ void check_try_expr_no_value_error(CheckerContext *c, String const &name, Operan
}
+void check_or_return_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_) {
+ Type *left_type = nullptr;
+ Type *right_type = nullptr;
+ if (x->type->kind == Type_Tuple) {
+ auto const &vars = x->type->Tuple.variables;
+ auto lhs = array_slice(vars, 0, vars.count-1);
+ auto rhs = vars[vars.count-1];
+ if (lhs.count == 1) {
+ left_type = lhs[0]->type;
+ } else if (lhs.count != 0) {
+ left_type = alloc_type_tuple();
+ left_type->Tuple.variables = array_make_from_ptr(lhs.data, lhs.count, lhs.count);
+ }
+
+ right_type = rhs->type;
+ } else {
+ check_promote_optional_ok(c, x, &left_type, &right_type);
+ }
+
+ if (left_type_) *left_type_ = left_type;
+ if (right_type_) *right_type_ = right_type;
+
+ check_or_else_right_type(c, x->expr, name, right_type);
+}
+
+
+
bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
ast_node(ce, CallExpr, call);
if (ce->inlining != ProcInlining_none) {
@@ -145,10 +179,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
// NOTE(bill): The first arg may be a Type, this will be checked case by case
break;
- case BuiltinProc_or_else:
- // NOTE(bill): The arguments may be multi-expr
- break;
-
case BuiltinProc_DIRECTIVE: {
ast_node(bd, BasicDirective, ce->proc);
String name = bd->name.string;
@@ -1800,47 +1830,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break;
}
- case BuiltinProc_or_else: {
- GB_ASSERT(ce->args.count == 2);
- Ast *arg = ce->args[0];
- Ast *default_value = ce->args[1];
-
- Operand x = {};
- Operand y = {};
- check_multi_expr_with_type_hint(c, &x, arg, type_hint);
- if (x.mode == Addressing_Invalid) {
- operand->mode = Addressing_Value;
- operand->type = t_invalid;
- return false;
- }
-
- check_multi_expr_with_type_hint(c, &y, default_value, x.type);
- error_operand_no_value(&y);
- if (y.mode == Addressing_Invalid) {
- operand->mode = Addressing_Value;
- operand->type = t_invalid;
- return false;
- }
-
- Type *left_type = nullptr;
- Type *right_type = nullptr;
- check_or_else_split_types(c, &x, builtin_name, &left_type, &right_type);
- add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value);
-
- if (left_type != nullptr) {
- check_assignment(c, &y, left_type, builtin_name);
- } else {
- check_try_expr_no_value_error(c, builtin_name, x, type_hint);
- }
-
- if (left_type == nullptr) {
- left_type = t_invalid;
- }
- operand->mode = Addressing_Value;
- operand->type = left_type;
- return true;
- }
-
case BuiltinProc_simd_vector: {
Operand x = {};
Operand y = {};
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index f01e9a328..30f44a59f 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -114,6 +114,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
void check_promote_optional_ok(CheckerContext *c, Operand *x, Type **val_type_, Type **ok_type_);
+void check_or_else_right_type(CheckerContext *c, Ast *expr, String const &name, Type *right_type);
+void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_);
+void check_or_else_expr_no_value_error(CheckerContext *c, String const &name, Operand const &x, Type *type_hint);
+void check_or_return_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_);
+
Entity *entity_from_expr(Ast *expr) {
expr = unparen_expr(expr);
switch (expr->kind) {
@@ -2960,6 +2965,25 @@ void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final)
update_untyped_expr_type(c, te->y, type, final);
case_end;
+ case_ast_node(ore, OrReturnExpr, e);
+ if (old->value.kind != ExactValue_Invalid) {
+ // See above note in UnaryExpr case
+ break;
+ }
+
+ update_untyped_expr_type(c, ore->expr, type, final);
+ case_end;
+
+ case_ast_node(oee, OrElseExpr, e);
+ if (old->value.kind != ExactValue_Invalid) {
+ // See above note in UnaryExpr case
+ break;
+ }
+
+ update_untyped_expr_type(c, oee->x, type, final);
+ update_untyped_expr_type(c, oee->y, type, final);
+ case_end;
+
case_ast_node(pe, ParenExpr, e);
update_untyped_expr_type(c, pe->expr, type, final);
case_end;
@@ -6602,6 +6626,123 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
}
case_end;
+ case_ast_node(oe, OrElseExpr, node);
+ String name = oe->token.string;
+ Ast *arg = oe->x;
+ Ast *default_value = oe->y;
+
+ Operand x = {};
+ Operand y = {};
+ check_multi_expr_with_type_hint(c, &x, arg, type_hint);
+ if (x.mode == Addressing_Invalid) {
+ o->mode = Addressing_Value;
+ o->type = t_invalid;
+ o->expr = node;
+ return Expr_Expr;
+ }
+
+ check_multi_expr_with_type_hint(c, &y, default_value, x.type);
+ error_operand_no_value(&y);
+ if (y.mode == Addressing_Invalid) {
+ o->mode = Addressing_Value;
+ o->type = t_invalid;
+ o->expr = node;
+ return Expr_Expr;
+ }
+
+ Type *left_type = nullptr;
+ Type *right_type = nullptr;
+ check_or_else_split_types(c, &x, name, &left_type, &right_type);
+ add_type_and_value(&c->checker->info, arg, x.mode, x.type, x.value);
+
+ if (left_type != nullptr) {
+ check_assignment(c, &y, left_type, name);
+ } else {
+ check_or_else_expr_no_value_error(c, name, x, type_hint);
+ }
+
+ if (left_type == nullptr) {
+ left_type = t_invalid;
+ }
+ o->mode = Addressing_Value;
+ o->type = left_type;
+ o->expr = node;
+ return Expr_Expr;
+ case_end;
+
+ case_ast_node(re, OrReturnExpr, node);
+ String name = re->token.string;
+ Operand x = {};
+ check_multi_expr_with_type_hint(c, &x, re->expr, type_hint);
+ if (x.mode == Addressing_Invalid) {
+ o->mode = Addressing_Value;
+ o->type = t_invalid;
+ o->expr = node;
+ return Expr_Expr;
+ }
+
+ Type *left_type = nullptr;
+ Type *right_type = nullptr;
+ check_or_return_split_types(c, &x, name, &left_type, &right_type);
+ add_type_and_value(&c->checker->info, re->expr, x.mode, x.type, x.value);
+
+ if (right_type == nullptr) {
+ check_or_else_expr_no_value_error(c, name, x, type_hint);
+ } else {
+ Type *proc_type = base_type(c->curr_proc_sig);
+ GB_ASSERT(proc_type->kind == Type_Proc);
+ Type *result_type = proc_type->Proc.results;
+ if (result_type == nullptr) {
+ error(node, "'%.*s' requires the current procedure to have at least one return value", LIT(name));
+ } else {
+ GB_ASSERT(result_type->kind == Type_Tuple);
+
+ auto const &vars = result_type->Tuple.variables;
+ Type *end_type = vars[vars.count-1]->type;
+
+ if (vars.count > 1) {
+ if (!proc_type->Proc.has_named_results) {
+ error(node, "'%.*s' within a procedure with more than 1 return value requires that the return values are named, allowing for early return", LIT(name));
+ }
+ }
+
+ Operand rhs = {};
+ rhs.type = right_type;
+ rhs.mode = Addressing_Value;
+
+ // TODO(bill): better error message
+ if (!check_is_assignable_to(c, &rhs, end_type)) {
+ gbString a = type_to_string(right_type);
+ gbString b = type_to_string(end_type);
+ gbString ret_type = type_to_string(result_type);
+ error(node, "Cannot assign end value of type '%s' to '%s' in '%.*s'", a, b, LIT(name));
+ if (vars.count == 1) {
+ error_line("\tProcedure return value type: %s\n", ret_type);
+ } else {
+ error_line("\tProcedure return value types: (%s)\n", ret_type);
+ }
+ gb_string_free(ret_type);
+ gb_string_free(b);
+ gb_string_free(a);
+ }
+ }
+ }
+
+ o->expr = node;
+ o->type = left_type;
+ if (left_type != nullptr) {
+ o->mode = Addressing_Value;
+ } else {
+ o->mode = Addressing_NoValue;
+ }
+
+ if (c->curr_proc_sig == nullptr) {
+ error(node, "'%.*s' can only be used within a procedure", LIT(name));
+ }
+
+ return Expr_Expr;
+ case_end;
+
case_ast_node(cl, CompoundLit, node);
Type *type = type_hint;
if (type != nullptr && is_type_untyped(type)) {
@@ -8565,6 +8706,16 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) {
str = write_expr_to_string(str, te->y, shorthand);
case_end;
+ case_ast_node(oe, OrElseExpr, node);
+ str = write_expr_to_string(str, oe->x, shorthand);
+ str = gb_string_appendc(str, " or_else ");
+ str = write_expr_to_string(str, oe->y, shorthand);
+ case_end;
+
+ case_ast_node(oe, OrReturnExpr, node);
+ str = write_expr_to_string(str, oe->expr, shorthand);
+ str = gb_string_appendc(str, " or_return");
+ case_end;
case_ast_node(pe, ParenExpr, node);
str = gb_string_append_rune(str, '(');
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index 236b5a9f5..504c23d53 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -1480,8 +1480,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
if (kind == Expr_Stmt) {
return;
}
- if (operand.expr->kind == Ast_CallExpr) {
- AstCallExpr *ce = &operand.expr->CallExpr;
+ Ast *expr = strip_or_return_expr(operand.expr);
+
+ if (expr->kind == Ast_CallExpr) {
+ AstCallExpr *ce = &expr->CallExpr;
Type *t = type_of_expr(ce->proc);
if (is_type_proc(t)) {
if (t->Proc.require_results) {
@@ -1491,8 +1493,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
}
return;
- } else if (operand.expr->kind == Ast_SelectorCallExpr) {
- AstSelectorCallExpr *se = &operand.expr->SelectorCallExpr;
+ } else if (expr->kind == Ast_SelectorCallExpr) {
+ AstSelectorCallExpr *se = &expr->SelectorCallExpr;
ast_node(ce, CallExpr, se->call);
Type *t = type_of_expr(ce->proc);
if (is_type_proc(t)) {
diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp
index a25657abe..57b5d7eb9 100644
--- a/src/checker_builtin_procs.hpp
+++ b/src/checker_builtin_procs.hpp
@@ -33,8 +33,6 @@ enum BuiltinProcId {
BuiltinProc_soa_zip,
BuiltinProc_soa_unzip,
- BuiltinProc_or_else,
-
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
// "Intrinsics"
@@ -265,8 +263,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("soa_zip"), 1, true, Expr_Expr, BuiltinProcPkg_builtin},
{STR_LIT("soa_unzip"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
- {STR_LIT("or_else"), 2, false, Expr_Expr, BuiltinProcPkg_builtin},
-
{STR_LIT(""), 0, true, Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 1c5f03722..e6bb35c0c 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -2305,6 +2305,14 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
}
case_end;
+ case_ast_node(oe, OrElseExpr, expr);
+ return lb_emit_or_else(p, oe->x, oe->y, tv);
+ case_end;
+
+ case_ast_node(oe, OrReturnExpr, expr);
+ return lb_emit_or_return(p, oe->expr, tv);
+ case_end;
+
case_ast_node(ta, TypeAssertion, expr);
TokenPos pos = ast_token(expr).pos;
Type *type = tv.type;
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index 5b922de4b..03b052c71 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -1252,9 +1252,6 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
case BuiltinProc_soa_unzip:
return lb_soa_unzip(p, ce, tv);
- case BuiltinProc_or_else:
- return lb_emit_or_else(p, ce->args[0], ce->args[1], tv);
-
// "Intrinsics"
case BuiltinProc_alloca:
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index 5fc5389c9..406b4fc2e 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -364,6 +364,48 @@ lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, TypeAndValue c
return res;
}
+void lb_build_return_stmt(lbProcedure *p, Slice const &return_results);
+void lb_build_return_stmt_internal(lbProcedure *p, lbValue const &res);
+
+lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue const &tv) {
+ lbValue lhs = {};
+ lbValue rhs = {};
+ lb_emit_try_lhs_rhs(p, arg, tv, &lhs, &rhs);
+
+ lbBlock *return_block = lb_create_block(p, "or_return.return");
+ lbBlock *continue_block = lb_create_block(p, "or_return.continue");
+
+ lb_emit_if(p, lb_emit_try_has_value(p, rhs), continue_block, return_block);
+ lb_start_block(p, return_block);
+ {
+ Type *proc_type = base_type(p->type);
+ Type *results = proc_type->Proc.results;
+ GB_ASSERT(results != nullptr && results->kind == Type_Tuple);
+ TypeTuple *tuple = &results->Tuple;
+
+ GB_ASSERT(tuple->variables.count != 0);
+
+ Entity *end_entity = tuple->variables[tuple->variables.count-1];
+ rhs = lb_emit_conv(p, rhs, end_entity->type);
+ if (p->type->Proc.has_named_results) {
+ GB_ASSERT(end_entity->token.string.len != 0);
+
+ // NOTE(bill): store the named values before returning
+ lbValue found = map_must_get(&p->module->values, hash_entity(end_entity));
+ lb_emit_store(p, found, rhs);
+
+ lb_build_return_stmt(p, {});
+ } else {
+ GB_ASSERT(tuple->variables.count == 1);
+ lb_build_return_stmt_internal(p, rhs);
+ }
+ }
+ lb_start_block(p, continue_block);
+ if (tv.type != nullptr) {
+ return lb_emit_conv(p, lhs, tv.type);
+ }
+ return {};
+}
void lb_emit_increment(lbProcedure *p, lbValue addr) {
diff --git a/src/parser.cpp b/src/parser.cpp
index 893ce9891..8f3ffb8cc 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -187,6 +187,13 @@ Ast *clone_ast(Ast *node) {
n->TernaryWhenExpr.cond = clone_ast(n->TernaryWhenExpr.cond);
n->TernaryWhenExpr.y = clone_ast(n->TernaryWhenExpr.y);
break;
+ case Ast_OrElseExpr:
+ n->OrElseExpr.x = clone_ast(n->OrElseExpr.x);
+ n->OrElseExpr.y = clone_ast(n->OrElseExpr.y);
+ break;
+ case Ast_OrReturnExpr:
+ n->OrReturnExpr.expr = clone_ast(n->OrReturnExpr.expr);
+ break;
case Ast_TypeAssertion:
n->TypeAssertion.expr = clone_ast(n->TypeAssertion.expr);
n->TypeAssertion.type = clone_ast(n->TypeAssertion.type);
@@ -685,6 +692,21 @@ Ast *ast_ternary_when_expr(AstFile *f, Ast *x, Ast *cond, Ast *y) {
return result;
}
+Ast *ast_or_else_expr(AstFile *f, Ast *x, Token const &token, Ast *y) {
+ Ast *result = alloc_ast_node(f, Ast_OrElseExpr);
+ result->OrElseExpr.x = x;
+ result->OrElseExpr.token = token;
+ result->OrElseExpr.y = y;
+ return result;
+}
+
+Ast *ast_or_return_expr(AstFile *f, Ast *expr, Token const &token) {
+ Ast *result = alloc_ast_node(f, Ast_OrReturnExpr);
+ result->OrReturnExpr.expr = expr;
+ result->OrReturnExpr.token = token;
+ return result;
+}
+
Ast *ast_type_assertion(AstFile *f, Ast *expr, Token dot, Ast *type) {
Ast *result = alloc_ast_node(f, Ast_TypeAssertion);
result->TypeAssertion.expr = expr;
@@ -1340,6 +1362,8 @@ Token expect_operator(AstFile *f) {
// okay
} else if (prev.kind == Token_if || prev.kind == Token_when) {
// okay
+ } else if (prev.kind == Token_or_else || prev.kind == Token_or_return) {
+ // okay
} else if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
String p = token_to_string(prev);
syntax_error(f->curr_token, "Expected an operator, got '%.*s'",
@@ -1674,6 +1698,22 @@ Ast *unselector_expr(Ast *node) {
return node;
}
+Ast *strip_or_return_expr(Ast *node) {
+ for (;;) {
+ if (node == nullptr) {
+ return node;
+ }
+ if (node->kind == Ast_OrReturnExpr) {
+ node = node->OrReturnExpr.expr;
+ } else if (node->kind == Ast_ParenExpr) {
+ node = node->ParenExpr.expr;
+ } else {
+ return node;
+ }
+ }
+}
+
+
Ast *parse_value(AstFile *f);
Array parse_element_list(AstFile *f) {
@@ -1892,7 +1932,7 @@ bool ast_on_same_line(Ast *x, Ast *y) {
Ast *parse_force_inlining_operand(AstFile *f, Token token) {
Ast *expr = parse_unary_expr(f, false);
- Ast *e = unparen_expr(expr);
+ Ast *e = strip_or_return_expr(expr);
if (e->kind != Ast_ProcLit && e->kind != Ast_CallExpr) {
syntax_error(expr, "%.*s must be followed by a procedure literal or call, got %.*s", LIT(token.string), LIT(ast_strings[expr->kind]));
return ast_bad_expr(f, token, f->curr_token);
@@ -2777,6 +2817,10 @@ Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
break;
+ case Token_or_return:
+ operand = ast_or_return_expr(f, operand, expect_token(f, Token_or_return));
+ break;
+
case Token_OpenBrace:
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
operand = parse_literal_value(f, operand);
@@ -2870,6 +2914,7 @@ i32 token_precedence(AstFile *f, TokenKind t) {
case Token_Question:
case Token_if:
case Token_when:
+ case Token_or_else:
return 1;
case Token_Ellipsis:
case Token_RangeFull:
@@ -2924,14 +2969,16 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
// NOTE(bill): This will also catch operators that are not valid "binary" operators
break;
}
- if (op.kind == Token_if || op.kind == Token_when) {
- Token prev = f->prev_token;
+ Token prev = f->prev_token;
+ switch (op.kind) {
+ case Token_if:
+ case Token_when:
if (prev.pos.line < op.pos.line) {
// NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition
- break;
+ goto loop_end;
}
+ break;
}
-
expect_operator(f); // NOTE(bill): error checks too
if (op.kind == Token_Question) {
@@ -2955,6 +3002,10 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
Token tok_else = expect_token(f, Token_else);
Ast *y = parse_expr(f, lhs);
expr = ast_ternary_when_expr(f, x, cond, y);
+ } else if (op.kind == Token_or_else) {
+ Ast *x = expr;
+ Ast *y = parse_expr(f, lhs);
+ expr = ast_or_else_expr(f, x, op, y);
} else {
Ast *right = parse_binary_expr(f, false, prec+1);
if (right == nullptr) {
@@ -2965,6 +3016,7 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
lhs = false;
}
+ loop_end:;
}
return expr;
}
diff --git a/src/parser.hpp b/src/parser.hpp
index c284ec586..579ec5b79 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -385,6 +385,8 @@ AST_KIND(_ExprBegin, "", bool) \
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \
AST_KIND(TernaryWhenExpr, "ternary when expression", struct { Ast *x, *cond, *y; }) \
+ AST_KIND(OrElseExpr, "or_else expression", struct { Ast *x; Token token; Ast *y; }) \
+ AST_KIND(OrReturnExpr, "or_return expression", struct { Ast *expr; Token token; }) \
AST_KIND(TypeAssertion, "type assertion", struct { \
Ast *expr; \
Token dot; \
diff --git a/src/parser_pos.cpp b/src/parser_pos.cpp
index 921836afe..0f2ac438a 100644
--- a/src/parser_pos.cpp
+++ b/src/parser_pos.cpp
@@ -41,6 +41,8 @@ Token ast_token(Ast *node) {
case Ast_DerefExpr: return node->DerefExpr.op;
case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
case Ast_TernaryWhenExpr: return ast_token(node->TernaryWhenExpr.x);
+ case Ast_OrElseExpr: return ast_token(node->OrElseExpr.x);
+ case Ast_OrReturnExpr: return ast_token(node->OrReturnExpr.expr);
case Ast_TypeAssertion: return ast_token(node->TypeAssertion.expr);
case Ast_TypeCast: return node->TypeCast.token;
case Ast_AutoCast: return node->AutoCast.token;
@@ -175,6 +177,8 @@ Token ast_end_token(Ast *node) {
case Ast_DerefExpr: return node->DerefExpr.op;
case Ast_TernaryIfExpr: return ast_end_token(node->TernaryIfExpr.y);
case Ast_TernaryWhenExpr: return ast_end_token(node->TernaryWhenExpr.y);
+ case Ast_OrElseExpr: return ast_end_token(node->OrElseExpr.y);
+ case Ast_OrReturnExpr: return node->OrReturnExpr.token;
case Ast_TypeAssertion: return ast_end_token(node->TypeAssertion.type);
case Ast_TypeCast: return ast_end_token(node->TypeCast.expr);
case Ast_AutoCast: return ast_end_token(node->AutoCast.expr);
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index e33c945bc..8772890d9 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -113,10 +113,12 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_distinct, "distinct"), \
TOKEN_KIND(Token_using, "using"), \
+ TOKEN_KIND(Token_context, "context"), \
+ TOKEN_KIND(Token_or_else, "or_else"), \
+ TOKEN_KIND(Token_or_return, "or_return"), \
+ TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_inline, "inline"), \
TOKEN_KIND(Token_no_inline, "no_inline"), \
- TOKEN_KIND(Token_context, "context"), \
- TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token__KeywordEnd, ""), \
TOKEN_KIND(Token_Count, "")
@@ -1508,6 +1510,7 @@ semicolon_check:;
case Token_continue:
case Token_fallthrough:
case Token_return:
+ case Token_or_return:
/*fallthrough*/
case Token_Integer:
case Token_Float: