Merge pull request #1082 from odin-lang/or_else-or_return-operator

`or_else` and `or_return` operators
This commit is contained in:
gingerBill
2021-08-16 12:03:43 +01:00
committed by GitHub
41 changed files with 1113 additions and 840 deletions
+1 -3
View File
@@ -183,9 +183,7 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
for { for {
if writer_available(b) == 0 { if writer_available(b) == 0 {
if ferr := writer_flush(b); ferr != nil { writer_flush(b) or_return;
return n, ferr;
}
} }
if b.max_consecutive_empty_writes <= 0 { if b.max_consecutive_empty_writes <= 0 {
b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS; b.max_consecutive_empty_writes = DEFAULT_MAX_CONSECUTIVE_EMPTY_READS;
+19 -58
View File
@@ -442,24 +442,22 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
return E_General.Unknown_Compression_Method; return E_General.Unknown_Compression_Method;
} }
cinfo := (cmf >> 4) & 0xf; if cinfo := (cmf >> 4) & 0xf; cinfo > 7 {
if cinfo > 7 {
return E_ZLIB.Unsupported_Window_Size; return E_ZLIB.Unsupported_Window_Size;
} }
flg, _ := compress.read_u8(ctx); flg, _ := compress.read_u8(ctx);
fcheck := flg & 0x1f; fcheck := flg & 0x1f;
fcheck_computed := (cmf << 8 | flg) & 0x1f; fcheck_computed := (cmf << 8 | flg) & 0x1f;
if fcheck != fcheck_computed { if fcheck != fcheck_computed {
return E_General.Checksum_Failed; return E_General.Checksum_Failed;
} }
fdict := (flg >> 5) & 1;
/* /*
We don't handle built-in dictionaries for now. We don't handle built-in dictionaries for now.
They're application specific and PNG doesn't use them. 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; 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. // Parse ZLIB stream without header.
err = inflate_raw(z=ctx, expected_output_size=expected_output_size); inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return;
if err != nil {
return err;
}
if !raw { if !raw {
compress.discard_to_next_byte_lsb(ctx); 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_repeat: ^Huffman_Table;
z_offset: ^Huffman_Table; z_offset: ^Huffman_Table;
codelength_ht: ^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_repeat);
defer free(z_offset); defer free(z_offset);
defer free(codelength_ht); 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); final := u32(0);
type := 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 // Discard bits until next byte boundary
compress.discard_to_next_byte_lsb(z); compress.discard_to_next_byte_lsb(z);
uncompressed_len := 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)); 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); // 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); // log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
if type == 1 { if type == 1 {
// Use fixed code lengths. // Use fixed code lengths.
err = build_huffman(z_repeat, Z_FIXED_LENGTH[:]); build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return;
if err != nil { build_huffman(z_offset, Z_FIXED_DIST[:]) or_return;
return err;
}
err = build_huffman(z_offset, Z_FIXED_DIST[:]);
if err != nil {
return err;
}
} else { } else {
lencodes: [286+32+137]u8; lencodes: [286+32+137]u8;
codelength_sizes: [19]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); s := compress.read_bits_lsb(z, 3);
codelength_sizes[Z_LENGTH_DEZIGZAG[i]] = u8(s); codelength_sizes[Z_LENGTH_DEZIGZAG[i]] = u8(s);
} }
err = build_huffman(codelength_ht, codelength_sizes[:]); build_huffman(codelength_ht, codelength_sizes[:]) or_return;
if err != nil {
return err;
}
n = 0; n = 0;
c: u16; c: u16;
for n < ntot { for n < ntot {
c, err = decode_huffman(z, codelength_ht); c = decode_huffman(z, codelength_ht) or_return;
if err != nil {
return err;
}
if c < 0 || c >= 19 { if c < 0 || c >= 19 {
return E_Deflate.Huffman_Bad_Code_Lengths; 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; return E_Deflate.Huffman_Bad_Code_Lengths;
} }
err = build_huffman(z_repeat, lencodes[:hlit]); build_huffman(z_repeat, lencodes[:hlit]) or_return;
if err != nil { build_huffman(z_offset, lencodes[hlit:ntot]) or_return;
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;
} }
parse_huffman_block(z, z_repeat, z_offset) or_return;
} }
if final == 1 { if final == 1 {
break; break;
@@ -698,9 +661,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
ctx.input_data = input; ctx.input_data = input;
ctx.output = buf; ctx.output = buf;
err = inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size); return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size);
return err;
} }
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) { inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
@@ -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); return inflate_raw(z=&ctx, expected_output_size=expected_output_size);
} }
inflate :: proc{inflate_from_context, inflate_from_byte_array}; inflate :: proc{inflate_from_context, inflate_from_byte_array};
+10 -31
View File
@@ -64,21 +64,15 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
field := record[field_idx]; field := record[field_idx];
if field_idx > 0 { if field_idx > 0 {
if _, err := io.write_rune(w.w, w.comma); err != nil { io.write_rune(w.w, w.comma) or_return;
return err;
}
} }
if !field_needs_quoting(w, field) { if !field_needs_quoting(w, field) {
if _, err := io.write_string(w.w, field); err != nil { io.write_string(w.w, field) or_return;
return err;
}
continue; continue;
} }
if err := io.write_byte(w.w, '"'); err != nil { io.write_byte(w.w, '"') or_return;
return err;
}
for len(field) > 0 { for len(field) > 0 {
i := strings.index_any(field, CHAR_SET); i := strings.index_any(field, CHAR_SET);
@@ -86,40 +80,28 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
i = len(field); i = len(field);
} }
if _, err := io.write_string(w.w, field[:i]); err != nil { io.write_string(w.w, field[:i]) or_return;
return err;
}
field = field[i:]; field = field[i:];
if len(field) > 0 { if len(field) > 0 {
switch field[0] { switch field[0] {
case '\r': case '\r':
if !w.use_crlf { if !w.use_crlf {
if err := io.write_byte(w.w, '\r'); err != nil { io.write_byte(w.w, '\r') or_return;
return err;
}
} }
case '\n': case '\n':
if w.use_crlf { if w.use_crlf {
if _, err := io.write_string(w.w, "\r\n"); err != nil { io.write_string(w.w, "\r\n") or_return;
return err;
}
} else { } else {
if err := io.write_byte(w.w, '\n'); err != nil { io.write_byte(w.w, '\n') or_return;
return err;
}
} }
case '"': case '"':
if _, err := io.write_string(w.w, `""`); err != nil { io.write_string(w.w, `""`) or_return;
return err;
}
} }
field = field[1:]; field = field[1:];
} }
} }
if err := io.write_byte(w.w, '"'); err != nil { io.write_byte(w.w, '"') or_return;
return err;
}
} }
if w.use_crlf { 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 writes multiple CSV records to w using write, and then flushes (if necessary).
write_all :: proc(w: ^Writer, records: [][]string) -> io.Error { write_all :: proc(w: ^Writer, records: [][]string) -> io.Error {
for record in records { for record in records {
err := write(w, record); write(w, record) or_return;
if err != nil {
return err;
}
} }
return writer_flush(w); return writer_flush(w);
} }
+32 -53
View File
@@ -67,17 +67,9 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
} }
read_name :: proc(r: ^Reader) -> (value: string, err: Read_Error) { read_name :: proc(r: ^Reader) -> (value: string, err: Read_Error) {
len: u8; len := read_value(r, u8) or_return;
data: []byte; data := read_array(r, byte, int(len)) or_return;
len, err = read_value(r, u8); return string(data[:len]), nil;
if err != nil {
return;
}
data, err = read_array(r, byte, int(len));
if err == nil {
value = string(data[:len]);
}
return;
} }
read_meta :: proc(r: ^Reader, capacity: u32le) -> (meta_data: []Meta, err: Read_Error) { read_meta :: proc(r: ^Reader, capacity: u32le) -> (meta_data: []Meta, err: Read_Error) {
@@ -85,10 +77,9 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
count := 0; count := 0;
defer meta_data = meta_data[:count]; defer meta_data = meta_data[:count];
for m in &meta_data { 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; type := read_value(r, Meta_Value_Type) or_return;
if type, err = read_value(r, Meta_Value_Type); err != nil { return }
if type > max(Meta_Value_Type) { if type > max(Meta_Value_Type) {
if r.print_error { 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))); 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 := "<input>", print_error := false, allocato
err = .Invalid_Data; err = .Invalid_Data;
return; return;
} }
array_length: u32le; array_length := read_value(r, u32le) or_return;
if array_length, err = read_value(r, u32le); err != nil { return }
switch type { switch type {
case .Int64: case .Int64: m.value = read_array(r, i64le, int(array_length)) or_return;
if m.value, err = read_array(r, i64le, int(array_length)); err != nil { return } case .Double: m.value = read_array(r, f64le, int(array_length)) or_return;
case .Double: case .Node: m.value = read_array(r, Node_Index, int(array_length)) or_return;
if m.value, err = read_array(r, f64le, int(array_length)); err != nil { return } case .Text: m.value = read_string(r, int(array_length)) or_return;
case .Node: case .Binary: m.value = read_array(r, byte, int(array_length)) or_return;
if m.value, err = read_array(r, Node_Index, int(array_length)); err != nil { return } case .Meta: m.value = read_meta(r, array_length) or_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 }
} }
count += 1; count += 1;
@@ -120,16 +104,14 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
} }
read_layer_stack :: proc(r: ^Reader, capacity: u32le) -> (layers: Layer_Stack, err: Read_Error) { read_layer_stack :: proc(r: ^Reader, capacity: u32le) -> (layers: Layer_Stack, err: Read_Error) {
stack_count: u32le; stack_count := read_value(r, u32le) or_return;
if stack_count, err = read_value(r, u32le); err != nil { return }
layer_count := 0; layer_count := 0;
layers = make(Layer_Stack, stack_count); layers = make(Layer_Stack, stack_count);
defer layers = layers[:layer_count]; defer layers = layers[:layer_count];
for layer in &layers { for layer in &layers {
type: Layer_Data_Type; layer.name = read_name(r) or_return;
if layer.name, err = read_name(r); err != nil { return } layer.components = read_value(r, u8) or_return;
if layer.components, err = read_value(r, u8); err != nil { return } type := read_value(r, Layer_Data_Type) or_return;
if type, err = read_value(r, Layer_Data_Type); err != nil { return }
if type > max(type) { if type > max(type) {
if r.print_error { 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))); 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 := "<input>", print_error := false, allocato
data_len := int(layer.components) * int(capacity); data_len := int(layer.components) * int(capacity);
switch type { switch type {
case .Uint8: if layer.data, err = read_array(r, u8, data_len); err != nil { return } case .Uint8: layer.data = read_array(r, u8, data_len) or_return;
case .Int32: if layer.data, err = read_array(r, i32le, data_len); err != nil { return } case .Int32: layer.data = read_array(r, i32le, data_len) or_return;
case .Float: if layer.data, err = read_array(r, f32le, data_len); err != nil { return } case .Float: layer.data = read_array(r, f32le, data_len) or_return;
case .Double: if layer.data, err = read_array(r, f64le, data_len); err != nil { return } case .Double: layer.data = read_array(r, f64le, data_len) or_return;
} }
layer_count += 1; layer_count += 1;
} }
@@ -177,8 +159,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
for node_idx in 0..<header.internal_node_count { for node_idx in 0..<header.internal_node_count {
node := &file.nodes[node_count]; node := &file.nodes[node_count];
type: Node_Type; type := read_value(r, Node_Type) or_return;
if type, err = read_value(r, Node_Type); err != nil { return }
if type > max(Node_Type) { if type > max(Node_Type) {
if r.print_error { 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))); 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 := "<input>", print_error := false, allocato
} }
node_count += 1; node_count += 1;
meta_data_count: u32le; node.meta_data = read_meta(r, read_value(r, u32le) or_return) or_return;
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 }
switch type { switch type {
case .Meta_Only: case .Meta_Only:
@@ -198,35 +177,35 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
case .Geometry: case .Geometry:
g: Node_Geometry; g: Node_Geometry;
if g.vertex_count, err = read_value(r, u32le); err != nil { return } g.vertex_count = read_value(r, u32le) or_return;
if g.vertex_stack, err = read_layer_stack(r, g.vertex_count); err != nil { return } g.vertex_stack = read_layer_stack(r, g.vertex_count) or_return;
if g.edge_corner_count, err = read_value(r, u32le); err != nil { return } g.edge_corner_count = read_value(r, u32le) or_return;
if g.corner_stack, err = read_layer_stack(r, g.edge_corner_count); err != nil { return } g.corner_stack = read_layer_stack(r, g.edge_corner_count) or_return;
if header.version > 2 { 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 } g.face_count = read_value(r, u32le) or_return;
if g.face_stack, err = read_layer_stack(r, g.face_count); err != nil { return } g.face_stack = read_layer_stack(r, g.face_count) or_return;
node.content = g; node.content = g;
case .Image: case .Image:
img: Node_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); dimensions := int(img.type);
if img.type == .Image_Cube { if img.type == .Image_Cube {
dimensions = 2; dimensions = 2;
} }
img.resolution = {1, 1, 1}; img.resolution = {1, 1, 1};
for d in 0..<dimensions { for d in 0..<dimensions {
if img.resolution[d], err = read_value(r, u32le); err != nil { return } img.resolution[d] = read_value(r, u32le) or_return;
} }
size := img.resolution[0]*img.resolution[1]*img.resolution[2]; size := img.resolution[0]*img.resolution[1]*img.resolution[2];
if img.type == .Image_Cube { if img.type == .Image_Cube {
size *= 6; size *= 6;
} }
if img.image_stack, err = read_layer_stack(r, size); err != nil { return } img.image_stack = read_layer_stack(r, size) or_return;
node.content = img; node.content = img;
} }
+6 -24
View File
@@ -133,9 +133,7 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) {
} }
parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) { parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
if err = expect_token(p, .Open_Bracket); err != .None { expect_token(p, .Open_Bracket) or_return;
return;
}
array: Array; array: Array;
array.allocator = p.allocator; array.allocator = p.allocator;
@@ -147,11 +145,7 @@ parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) {
} }
for p.curr_token.kind != .Close_Bracket { for p.curr_token.kind != .Close_Bracket {
elem, elem_err := parse_value(p); elem := parse_value(p) or_return;
if elem_err != .None {
err = elem_err;
return;
}
append(&array, elem); append(&array, elem);
// Disallow trailing commas for the time being // 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 { expect_token(p, .Close_Bracket) or_return;
return;
}
value = array; value = array;
return; return;
} }
@@ -200,9 +191,7 @@ parse_object_key :: proc(p: ^Parser) -> (key: string, err: Error) {
} }
parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
if err = expect_token(p, .Open_Brace); err != .None { expect_token(p, .Open_Brace) or_return;
return;
}
obj: Object; obj: Object;
obj.allocator = p.allocator; obj.allocator = p.allocator;
@@ -227,11 +216,7 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) {
return; return;
} }
elem, elem_err := parse_value(p); elem := parse_value(p) or_return;
if elem_err != .None {
err = elem_err;
return;
}
if key in obj { if key in obj {
err = .Duplicate_Object_Key; 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 { expect_token(p, .Close_Brace) or_return;
return;
}
value = obj; value = obj;
return; return;
} }
+9 -30
View File
@@ -372,8 +372,7 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
defer delete(data); defer delete(data);
if ok { if ok {
img, err = load_from_slice(data, options, allocator); return load_from_slice(data, options, allocator);
return;
} else { } else {
img = new(Image); img = new(Image);
return img, E_General.File_Not_Found; 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; seen_ihdr = true;
header, err = read_header(ctx); header = read_header(ctx) or_return;
if err != nil {
return img, err;
}
if .Paletted in header.color_type { if .Paletted in header.color_type {
// Color type 3 // 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; return img, E_PNG.PLTE_Encountered_Unexpectedly;
} }
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
if c.header.length % 3 != 0 || c.header.length > 768 { if c.header.length % 3 != 0 || c.header.length > 768 {
return img, E_PNG.PLTE_Invalid_Length; 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; next := ch.type;
for next == .IDAT { for next == .IDAT {
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
bytes.buffer_write(&idat_b, c.data); bytes.buffer_write(&idat_b, c.data);
idat_length += c.header.length; idat_length += c.header.length;
@@ -560,19 +550,13 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
} }
seen_idat = true; seen_idat = true;
case .IEND: case .IEND:
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
seen_iend = true; seen_iend = true;
case .bKGD: case .bKGD:
// TODO: Make sure that 16-bit bKGD + tRNS chunks return u16 instead of u16be // TODO: Make sure that 16-bit bKGD + tRNS chunks return u16 instead of u16be
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
seen_bkgd = true; seen_bkgd = true;
if .return_metadata in options { if .return_metadata in options {
append(&info.chunks, c); 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])}; img.background = [3]u16{u16(col[0]), u16(col[1]), u16(col[2])};
} }
case .tRNS: case .tRNS:
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
if .Alpha in info.header.color_type { if .Alpha in info.header.color_type {
return img, E_PNG.TRNS_Encountered_Unexpectedly; 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; return img, E_PNG.PNG_Does_Not_Adhere_to_Spec;
case: case:
// Unhandled type // Unhandled type
c, err = read_chunk(ctx); c = read_chunk(ctx) or_return;
if err != nil {
return img, err;
}
if .return_metadata in options { if .return_metadata in options {
// NOTE: Chunk cata is currently allocated on the temp allocator. // NOTE: Chunk cata is currently allocated on the temp allocator.
append(&info.chunks, c); append(&info.chunks, c);
+46 -50
View File
@@ -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. Check that `src` is usable and `dest` isn't immutable.
*/ */
assert_if_nil(dest); 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); 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); assert_if_nil(dest, src);
context.allocator = allocator; context.allocator = allocator;
if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; } #force_inline internal_clear_if_uninitialized(src) or_return;
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_copy(dest, src, minimize); 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); assert_if_nil(dest, src);
context.allocator = allocator; context.allocator = allocator;
if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; } #force_inline internal_clear_if_uninitialized(src) or_return;
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_abs(dest, src); 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); assert_if_nil(dest, src);
context.allocator = allocator; context.allocator = allocator;
if err = #force_inline internal_clear_if_uninitialized(src); err != nil { return err; } #force_inline internal_clear_if_uninitialized(src) or_return;
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_neg(dest, src); 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); assert_if_nil(a);
context.allocator = allocator; context.allocator = allocator;
if err = #force_inline internal_clear_if_uninitialized(a); err != nil { return {}, err; } #force_inline internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_int_bitfield_extract(a, offset, count); 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); assert_if_nil(a);
context.allocator = allocator; context.allocator = allocator;
if err = #force_inline internal_clear_if_uninitialized(a); err != nil { return err; } #force_inline internal_clear_if_uninitialized(a) or_return;
return #force_inline internal_shrink(a); return #force_inline internal_shrink(a);
} }
int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) { 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. Check that `a` is usable.
*/ */
assert_if_nil(a); assert_if_nil(a);
if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return T{}, err; } #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
return #force_inline internal_int_get(a, T); return #force_inline internal_int_get(a, T);
} }
get :: proc { int_get, }; 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. Check that `a` is usable.
*/ */
assert_if_nil(a); assert_if_nil(a);
if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; } #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
return #force_inline internal_int_get_float(a); 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. Check that `a` is usable.
*/ */
assert_if_nil(a); assert_if_nil(a);
if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; } #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
return #force_inline internal_count_bits(a), nil; 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. Check that `a` is usable.
*/ */
assert_if_nil(a); assert_if_nil(a);
if err = #force_inline internal_clear_if_uninitialized(a, allocator); err != nil { return 0, err; } #force_inline internal_clear_if_uninitialized(a, allocator) or_return;
return #force_inline internal_int_count_lsb(a); return #force_inline internal_int_count_lsb(a);
} }
platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) 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); assert_if_nil(..args);
for i in &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; return err;
} }
@@ -425,7 +425,7 @@ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err
integers := integers; integers := integers;
for a in &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; 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. Check that `src` is usable and `dest` isn't immutable.
*/ */
assert_if_nil(dest, src); 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)); digits = min(digits, len(src.digit), len(dest.digit));
return #force_inline internal_copy_digits(dest, src, digits); 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) { clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a); 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 { for a.used > 0 && a.digit[a.used - 1] == 0 {
a.used -= 1; 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) { int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocator) -> (size_in_bytes: int, err: Error) {
assert_if_nil(a); 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); 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) { int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a); 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); l := len(buf);
if size_in_bytes > l { return .Buffer_Overflow; } 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) { int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a); 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); l := len(buf);
if size_in_bytes > l { return .Buffer_Overflow; } 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) { int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a); assert_if_nil(a);
size_in_bytes: int;
if !signed && a.sign == .Negative { return .Invalid_Argument; } if !signed && a.sign == .Negative { return .Invalid_Argument; }
l := len(buf); l := len(buf);
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;
if size_in_bytes > l { return .Buffer_Overflow; } if size_in_bytes > l { return .Buffer_Overflow; }
if a.sign == .Negative { if a.sign == .Negative {
t := &Int{}; t := &Int{};
defer destroy(t); 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); size_in_bits := internal_count_bits(t);
i := 0; 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) { int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) {
assert_if_nil(a); assert_if_nil(a);
size_in_bytes: int;
if !signed && a.sign == .Negative { return .Invalid_Argument; } if !signed && a.sign == .Negative { return .Invalid_Argument; }
if a.sign == .Zero_or_Positive { return int_to_bytes_big(a, buf, signed, allocator); } if a.sign == .Zero_or_Positive { return int_to_bytes_big(a, buf, signed, allocator); }
l := len(buf); l := len(buf);
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;
if size_in_bytes > l { return .Buffer_Overflow; } if size_in_bytes > l { return .Buffer_Overflow; }
t := &Int{}; t := &Int{};
defer destroy(t); 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); size_in_bits := internal_count_bits(t);
i := l - 1; 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 := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1; size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
if err = internal_zero(a, false, allocator); err != nil { return err; } internal_zero(a, false, allocator) or_return;
if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; } internal_grow(a, size_in_digits, false, allocator) or_return;
if signed { if signed {
sign = .Zero_or_Positive if buf[0] == 0 else .Negative; 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 { 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.digit[0] |= DIGIT(v);
} }
a.sign = sign; 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 := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1; size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
if err = internal_zero(a, false, allocator); err != nil { return err; } internal_zero(a, false, allocator) or_return;
if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; } internal_grow(a, size_in_digits, false, allocator) or_return;
if signed { if signed {
sign = .Zero_or_Positive if buf[0] == 0 else .Negative; 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 { 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 { if signed && sign == .Negative {
a.digit[0] |= DIGIT(255 - v); a.digit[0] |= DIGIT(255 - v);
} else { } else {
@@ -674,7 +670,7 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator
} }
a.sign = sign; a.sign = sign;
a.used = size_in_digits; a.used = size_in_digits;
if err = internal_clamp(a); err != nil { return err; } internal_clamp(a) or_return;
if signed && sign == .Negative { if signed && sign == .Negative {
return internal_sub(a, a, 1); 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 := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1; size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
if err = internal_zero(a, false, allocator); err != nil { return err; } internal_zero(a, false, allocator) or_return;
if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; } internal_grow(a, size_in_digits, false, allocator) or_return;
if signed { if signed {
sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; 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 { 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.digit[0] |= DIGIT(buf[l-i-1]);
} }
a.sign = sign; 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 := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS;
size_in_digits += 0 if size_in_bits % 8 == 0 else 1; size_in_digits += 0 if size_in_bits % 8 == 0 else 1;
if err = internal_zero(a, false, allocator); err != nil { return err; } internal_zero(a, false, allocator) or_return;
if err = internal_grow(a, size_in_digits, false, allocator); err != nil { return err; } internal_grow(a, size_in_digits, false, allocator) or_return;
if signed { if signed {
sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; 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 { 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 { if signed && sign == .Negative {
a.digit[0] |= DIGIT(255 - buf[l-i-1]); a.digit[0] |= DIGIT(255 - buf[l-i-1]);
} else { } else {
@@ -759,7 +755,7 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca
} }
a.sign = sign; a.sign = sign;
a.used = size_in_digits; a.used = size_in_digits;
if err = internal_clamp(a); err != nil { return err; } internal_clamp(a) or_return;
if signed && sign == .Negative { if signed && sign == .Negative {
return internal_sub(a, a, 1); return internal_sub(a, a, 1);
+72 -75
View File
@@ -58,7 +58,7 @@ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocat
max_used = x.used; max_used = x.used;
old_used = dest.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; dest.used = max_used + 1;
/* /*
All parameters have been initialized. 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) { internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator; 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. 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; max_used := x.used;
i: int; 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; dest.used = max_used;
/* /*
All parameters have been initialized. 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) { internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator; 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; 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) { internal_int_shl1 :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator; 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. Grow `dest` to accommodate the additional bits.
*/ */
digits_needed := dest.used + 1; 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; dest.used = digits_needed;
mask := (DIGIT(1) << uint(1)) - DIGIT(1); 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); return #force_inline internal_int_shl1(dest, src);
} }
if #force_inline platform_int_is_power_of_two(int(multiplier)) { if #force_inline platform_int_is_power_of_two(int(multiplier)) {
ix: int; ix := internal_log(multiplier, 2) or_return;
if ix, err = internal_log(multiplier, 2); err != nil { return err; }
return internal_shl(dest, src, ix); return internal_shl(dest, src, ix);
} }
/* /*
Ensure `dest` is big enough to hold `src` * `multiplier`. 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. 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 #force_inline internal_cmp_mag(numerator, denominator) == -1 {
if remainder != nil { if remainder != nil {
if err = internal_copy(remainder, numerator); err != nil { return err; } internal_copy(remainder, numerator) or_return;
} }
if quotient != nil { if quotient != nil {
internal_zero(quotient); internal_zero(quotient);
@@ -809,7 +808,7 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT,
*/ */
q := &Int{}; 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.used = numerator.used;
q.sign = numerator.sign; 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. 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) { 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; } if remainder.used == 0 || denominator.sign == remainder.sign { return nil; }
@@ -865,7 +864,7 @@ internal_mod :: proc{ internal_int_mod, };
remainder = (number + addend) % modulus. remainder = (number + addend) % modulus.
*/ */
internal_int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) { 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); return #force_inline internal_mod(remainder, remainder, modulus, allocator);
} }
internal_addmod :: proc { internal_int_addmod, }; internal_addmod :: proc { internal_int_addmod, };
@@ -874,7 +873,7 @@ internal_addmod :: proc { internal_int_addmod, };
remainder = (number - decrease) % modulus. remainder = (number - decrease) % modulus.
*/ */
internal_int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) { 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); return #force_inline internal_mod(remainder, remainder, modulus, allocator);
} }
internal_submod :: proc { internal_int_submod, }; internal_submod :: proc { internal_int_submod, };
@@ -883,7 +882,7 @@ internal_submod :: proc { internal_int_submod, };
remainder = (number * multiplicand) % modulus. remainder = (number * multiplicand) % modulus.
*/ */
internal_int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) { 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); return #force_inline internal_mod(remainder, remainder, modulus, allocator);
} }
internal_mulmod :: proc { internal_int_mulmod, }; internal_mulmod :: proc { internal_int_mulmod, };
@@ -892,7 +891,7 @@ internal_mulmod :: proc { internal_int_mulmod, };
remainder = (number * number) % modulus. remainder = (number * number) % modulus.
*/ */
internal_int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) { 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); return #force_inline internal_mod(remainder, remainder, modulus, allocator);
} }
internal_sqrmod :: proc { internal_int_sqrmod, }; 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]); 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 { 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; 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. If the modulus is larger than the value, return the value.
*/ */
err = internal_copy(remainder, numerator); internal_copy(remainder, numerator) or_return;
if bits >= (numerator.used * _DIGIT_BITS) || err != nil { if bits >= (numerator.used * _DIGIT_BITS) {
return; return;
} }
@@ -1264,7 +1265,7 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo
A zero base is a special case. A zero base is a special case.
*/ */
if power < 0 { if power < 0 {
if err = internal_zero(dest); err != nil { return err; } internal_zero(dest) or_return;
return .Math_Domain_Error; return .Math_Domain_Error;
} }
if power == 0 { return internal_one(dest); } 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{}; g := &Int{};
if err = internal_copy(g, base); err != nil { return err; } internal_copy(g, base) or_return;
/* /*
Set initial result. 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 the bit is set, multiply.
*/ */
if power & 1 != 0 { if power & 1 != 0 {
if err = internal_mul(dest, g, dest); err != nil { internal_mul(dest, g, dest) or_return;
break loop;
}
} }
/* /*
Square. Square.
*/ */
if power > 1 { if power > 1 {
if err = #force_inline internal_sqr(g, g); err != nil { internal_sqr(g, g) or_return;
break loop;
}
} }
/* shift to next bit */ /* shift to next bit */
power >>= 1; power >>= 1;
} }
internal_destroy(g); return;
return err;
} }
/* /*
@@ -1336,7 +1334,7 @@ internal_int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.
base_t := &Int{}; base_t := &Int{};
defer internal_destroy(base_t); 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); 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); count := #force_inline internal_count_bits(src);
a, b := count >> 1, count & 1; 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 { for {
/* /*
y = (x + n // x) // 2 y = (x + n // x) // 2
*/ */
if err = internal_div(t1, src, x); err != nil { return err; } internal_div(t1, src, x) or_return;
if err = internal_add(t2, t1, x); err != nil { return err; } internal_add(t2, t1, x) or_return;
if err = internal_shr(y, t2, 1); err != nil { return err; } internal_shr(y, t2, 1) or_return;
if c := internal_cmp(y, x); c == 0 || c == 1 { if c := internal_cmp(y, x); c == 0 || c == 1 {
internal_swap(dest, x); 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. Start value must be larger than root.
*/ */
ilog2 += 2; 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; c: int;
iterations := 0; iterations := 0;
for { for {
/* t1 = t2 */ /* 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))) */ /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
/* t3 = 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 */ /* numerator */
/* t2 = t1**b */ /* 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 */ /* t2 = t1**b - a */
if err = internal_sub(t2, t2, a); err != nil { return err; } internal_sub(t2, t2, a) or_return;
/* denominator */ /* denominator */
/* t3 = t1**(b-1) * b */ /* 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)) */ /* t3 = (t1**b - a)/(b * t1**(b-1)) */
if err = internal_div(t3, t2, t3); err != nil { return err; } internal_div(t3, t2, t3) or_return;
if err = internal_sub(t2, t1, t3); err != nil { return err; } internal_sub(t2, t1, t3) or_return;
/* /*
Number of rounds is at most log_2(root). If it is more it 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; iterations = 0;
for { for {
if err = internal_pow(t2, t1, n); err != nil { return err; } internal_pow(t2, t1, n) or_return;
c = internal_cmp(t2, a); c = internal_cmp(t2, a);
if c == 0 { if c == 0 {
swap(dest, t1); swap(dest, t1);
return nil; return nil;
} else if c == -1 { } 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 { } else {
break; 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. Correct overshoot from above or from recurrence.
*/ */
for { 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 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; iterations += 1;
if iterations == MAX_ITERATIONS_ROOT_N { 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; 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, 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. 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. 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_set :: proc { internal_int_set_from_integer, internal_int_copy };
internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int) -> (err: Error) { 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 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 (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`. 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); 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. 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` Copy `src` to `dest`
*/ */
if err = internal_copy(dest, src); err != nil { internal_copy(dest, src) or_return;
return err;
}
/* /*
Fix sign. Fix sign.
@@ -1744,7 +1740,7 @@ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (er
/* /*
Copy `src` to `dest` Copy `src` to `dest`
*/ */
if err = internal_copy(dest, src); err != nil { return err; } internal_copy(dest, src) or_return;
/* /*
Fix sign. 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. Grow to accomodate the single bit.
*/ */
a.used = (power / _DIGIT_BITS) + 1; 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. 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. 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_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b); 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. 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_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b); 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. 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_a := #force_inline internal_is_negative(a);
neg_b := #force_inline internal_is_negative(b); 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; bits := bits;
if bits < 0 { return .Invalid_Argument; } 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.) Shift right by a certain bit count (store quotient and optional remainder.)
`numerator` should not be used after this. `numerator` should not be used after this.
*/ */
if remainder != nil { 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. Shift by as many digits in the bit count.
*/ */
if bits >= _DIGIT_BITS { 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 { if src.sign == .Zero_or_Positive {
return internal_shr(dest, src, bits); return internal_shr(dest, src, bits);
} }
if err = internal_int_add_digit(dest, src, DIGIT(1)); err != nil { return err; } internal_int_add_digit(dest, src, DIGIT(1)) or_return;
internal_shr(dest, dest, bits) or_return;
if err = internal_shr(dest, dest, bits); err != nil { return err; }
return internal_sub(dest, src, DIGIT(1)); 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 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. Grow `dest` to accommodate the additional bits.
*/ */
digits_needed := dest.used + (bits / _DIGIT_BITS) + 1; 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; dest.used = digits_needed;
/* /*
Shift by as many digits in the bit count as we have. Shift by as many digits in the bit count as we have.
*/ */
if bits >= _DIGIT_BITS { 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. 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. 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. 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; 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 { for i := 0; i < digits; i += 1 {
dest.digit[i] = int_random_digit(r) & _MASK; dest.digit[i] = int_random_digit(r) & _MASK;
@@ -2600,7 +2597,7 @@ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator
integers := integers; integers := integers;
for a in &integers { for a in &integers {
if err = internal_clear(a); err != nil { return err; } internal_clear(a) or_return;
} }
return nil; return nil;
} }
+8 -8
View File
@@ -25,7 +25,7 @@ int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, a, b); assert_if_nil(dest, a, b);
context.allocator = allocator; 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); return #force_inline internal_int_and(dest, a, b);
} }
and :: proc { int_and, }; 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); assert_if_nil(dest, a, b);
context.allocator = allocator; 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); return #force_inline internal_int_or(dest, a, b);
} }
or :: proc { int_or, }; 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); assert_if_nil(dest, a, b);
context.allocator = allocator; 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); return #force_inline internal_int_xor(dest, a, b);
} }
xor :: proc { int_xor, }; xor :: proc { int_xor, };
@@ -64,7 +64,7 @@ int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err:
assert_if_nil(dest, src); assert_if_nil(dest, src);
context.allocator = allocator; 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); return #force_inline internal_int_complement(dest, src);
} }
complement :: proc { int_complement, }; complement :: proc { int_complement, };
@@ -97,7 +97,7 @@ int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato
assert_if_nil(quotient); assert_if_nil(quotient);
context.allocator = allocator; 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); return #force_inline internal_int_shr_digit(quotient, digits);
} }
shr_digit :: proc { int_shr_digit, }; 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); assert_if_nil(dest, src);
context.allocator = allocator; 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); 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); assert_if_nil(dest, src);
context.allocator = allocator; 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); return #force_inline internal_int_shl(dest, src, bits);
} }
shl :: proc { int_shl, }; shl :: proc { int_shl, };
@@ -138,7 +138,7 @@ int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato
assert_if_nil(quotient); assert_if_nil(quotient);
context.allocator = allocator; 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); return #force_inline internal_int_shl_digit(quotient, digits);
} }
shl_digit :: proc { int_shl_digit, }; shl_digit :: proc { int_shl_digit, };
+5 -4
View File
@@ -19,12 +19,13 @@ int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res:
assert_if_nil(a); assert_if_nil(a);
context.allocator = allocator; 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 { for prime in _private_prime_table {
if rem, err = #force_inline int_mod_digit(a, prime); err != nil { return false, err; } rem := #force_inline int_mod_digit(a, prime) or_return;
if rem == 0 { return true, nil; } if rem == 0 {
return true, nil;
}
} }
/* /*
Default to not divisible. Default to not divisible.
+241 -206
View File
File diff suppressed because it is too large Load Diff
+45 -46
View File
@@ -24,7 +24,7 @@ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error
assert_if_nil(dest, a, b); assert_if_nil(dest, a, b);
context.allocator = allocator; 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. 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); assert_if_nil(dest, a);
context.allocator = allocator; 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. 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. 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); assert_if_nil(dest, number, decrease);
context.allocator = allocator; 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. 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); assert_if_nil(dest, a);
context.allocator = allocator; 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. 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. 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); assert_if_nil(dest, src);
context.allocator = allocator; 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. 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); 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); assert_if_nil(dest, src);
context.allocator = allocator; 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. 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); 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); assert_if_nil(dest, src);
context.allocator = allocator; 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); 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); assert_if_nil(dest, src, multiplier);
context.allocator = allocator; 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); 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. Early out if neither of the results is wanted.
*/ */
if quotient == nil && remainder == nil { return nil; } 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); 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); assert_if_nil(quotient, numerator);
context.allocator = allocator; 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); 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); assert_if_nil(quotient, numerator, denominator);
context.allocator = allocator; 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); 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); assert_if_nil(quotient, numerator);
context.allocator = allocator; context.allocator = allocator;
if err = internal_clear_if_uninitialized(numerator); err != nil { return err; } internal_clear_if_uninitialized(numerator) or_return;
remainder: DIGIT; _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return;
remainder, err = #force_inline internal_divmod(quotient, numerator, denominator); return;
return err;
} }
div :: proc { int_div, int_div_digit, }; 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); assert_if_nil(remainder, numerator, denominator);
context.allocator = allocator; 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); 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); assert_if_nil(remainder, number, addend);
context.allocator = allocator; 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); 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); assert_if_nil(remainder, number, decrease);
context.allocator = allocator; 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); 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); assert_if_nil(remainder, number, multiplicand);
context.allocator = allocator; 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); 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); assert_if_nil(remainder, number, modulus);
context.allocator = allocator; 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); 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{}; n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{};
defer internal_destroy(n_fac, k_fac, n_minus_k_fac); 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; } #force_inline internal_int_factorial(n_minus_k_fac, n - k) or_return;
if err = #force_inline internal_int_factorial(k_fac, k); err != nil { return err; } #force_inline internal_int_factorial(k_fac, k) or_return;
if err = #force_inline internal_mul(k_fac, k_fac, n_minus_k_fac); err != nil { return err; } #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; } #force_inline internal_int_factorial(n_fac, n) or_return;
if err = #force_inline internal_div(res, n_fac, k_fac); err != nil { return err; } #force_inline internal_div(res, n_fac, k_fac) or_return;
return err; return;
} }
choose :: proc { int_choose_digit, }; 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); assert_if_nil(a, b);
context.allocator = allocator; 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); return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b);
} }
gcd_lcm :: proc { int_gcd_lcm, }; 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); assert_if_nil(remainder, numerator);
context.allocator = allocator; context.allocator = allocator;
if err = internal_clear_if_uninitialized(remainder, numerator); err != nil { return err; } internal_clear_if_uninitialized(remainder, numerator) or_return;
if bits < 0 { return .Invalid_Argument; } if bits < 0 { return .Invalid_Argument; }
return #force_inline internal_int_mod_bits(remainder, numerator, bits); 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); assert_if_nil(a);
context.allocator = allocator; 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); 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); assert_if_nil(dest, base);
context.allocator = allocator; 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); 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); assert_if_nil(dest, src);
context.allocator = allocator; 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); 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. 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); 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a, b);
context.allocator = allocator; 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; 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); assert_if_nil(a);
context.allocator = allocator; 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; 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); assert_if_nil(a, b);
context.allocator = allocator; 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; return #force_inline internal_cmp_mag(a, b), nil;
} }
+19 -24
View File
@@ -26,7 +26,7 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc
context.allocator = allocator; context.allocator = allocator;
a := a; radix := radix; a := a; radix := radix;
if err = clear_if_uninitialized(a); err != nil { return "", err; } clear_if_uninitialized(a) or_return;
/* /*
Radix defaults to 10. 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 Calculate the size of the buffer we need, and
*/
size: int;
/*
Exit if calculating the size returned an error. Exit if calculating the size returned an error.
*/ */
if size, err = radix_size(a, radix, zero_terminate); err != nil { size := radix_size(a, radix, zero_terminate) or_return;
return "", err;
}
/* /*
Allocate the buffer we need. Allocate the buffer we need.
@@ -70,7 +65,7 @@ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocato
context.allocator = allocator; context.allocator = allocator;
a := a; radix := radix; a := a; radix := radix;
if err = clear_if_uninitialized(a); err != nil { return "", err; } clear_if_uninitialized(a) or_return;
/* /*
Radix defaults to 10. 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) { int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_terminate := false) -> (written: int, err: Error) {
assert_if_nil(a); assert_if_nil(a);
a := a; radix := radix; size := size; 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. 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. We weren't given a size. Let's compute it.
*/ */
if size == -1 { if size == -1 {
if size, err = radix_size(a, radix, zero_terminate); err != nil { size = radix_size(a, radix, zero_terminate) or_return;
return 0, err;
}
} }
/* /*
@@ -256,12 +249,14 @@ int_atoi :: proc(res: ^Int, input: string, radix: i8, allocator := context.alloc
/* /*
Set the integer to the default of zero. 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. 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. 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; break;
} }
if err = internal_mul(res, res, DIGIT(radix)); err != nil { return err; } internal_mul(res, res, DIGIT(radix)) or_return;
if err = internal_add(res, res, DIGIT(y)); err != nil { return err; } internal_add(res, res, DIGIT(y)) or_return;
input = input[1:]; input = input[1:];
} }
@@ -333,7 +328,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con
assert_if_nil(a); assert_if_nil(a);
if radix < 2 || radix > 64 { return -1, .Invalid_Argument; } 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 internal_is_zero(a) {
if zero_terminate { if zero_terminate {
@@ -352,22 +347,22 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con
digit = a.digit, digit = a.digit,
}; };
if size, err = internal_log(t, DIGIT(radix)); err != nil { return {}, err; } size = internal_log(t, DIGIT(radix)) or_return;
} else { } else {
la, k := &Int{}, &Int{}; la, k := &Int{}, &Int{};
defer internal_destroy(la, k); defer internal_destroy(la, k);
/* la = floor(log_2(a)) + 1 */ /* la = floor(log_2(a)) + 1 */
bit_count := internal_count_bits(a); 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 */ /* k = floor(2^29/log_2(radix)) + 1 */
lb := _log_bases; 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 */ /* n = floor((la * k) / 2^29) + 1 */
if err = internal_mul(k, la, k); err != nil { return 0, err; } internal_mul(k, la, k) or_return;
if err = internal_shr(k, k, _RADIX_SIZE_SCALE); err != nil { return {}, err; } internal_shr(k, k, _RADIX_SIZE_SCALE) or_return;
/* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */ /* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */
/* n = n + 1 + EOS + sign */ /* 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{}; temp, denominator := &Int{}, &Int{};
if err = internal_copy(temp, a); err != nil { return 0, err; } internal_copy(temp, a) or_return;
if err = internal_set(denominator, radix); err != nil { return 0, err; } internal_set(denominator, radix) or_return;
available := len(buffer); available := len(buffer);
if zero_terminate { if zero_terminate {
+14 -14
View File
@@ -49,7 +49,7 @@ PyRes :: struct {
if bb.used == 1 { 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}; } if err = #force_inline internal_add(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; }
} else { } 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; r: cstring;
@@ -70,7 +70,7 @@ PyRes :: struct {
if bb.used == 1 { 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}; } if err = #force_inline internal_sub(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; }
} else { } 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; 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(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 = 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: cstring;
r, err = int_itoa_cstring(product, 16, context.temp_allocator); r, err = int_itoa_cstring(product, 16, context.temp_allocator);
@@ -104,7 +104,7 @@ PyRes :: struct {
defer internal_destroy(aa, square); defer internal_destroy(aa, square);
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sqr:atoi(a):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(square, 16, context.temp_allocator); 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(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 = 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: cstring;
r, err = int_itoa_cstring(quotient, 16, context.temp_allocator); r, err = int_itoa_cstring(quotient, 16, context.temp_allocator);
@@ -145,7 +145,7 @@ PyRes :: struct {
defer internal_destroy(aa); defer internal_destroy(aa);
if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err}; } 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); #force_inline internal_zero(aa);
aa.digit[0] = DIGIT(l) & _MASK; aa.digit[0] = DIGIT(l) & _MASK;
@@ -170,7 +170,7 @@ PyRes :: struct {
defer internal_destroy(dest, bb); defer internal_destroy(dest, bb);
if err = atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(dest, 16, context.temp_allocator); r, err = int_itoa_cstring(dest, 16, context.temp_allocator);
@@ -189,7 +189,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -208,7 +208,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -227,7 +227,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -246,7 +246,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -265,7 +265,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -284,7 +284,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
@@ -303,7 +303,7 @@ PyRes :: struct {
defer internal_destroy(src); defer internal_destroy(src);
if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", err=err}; } 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: cstring;
r, err = int_itoa_cstring(src, 16, context.temp_allocator); r, err = int_itoa_cstring(src, 16, context.temp_allocator);
+15 -11
View File
@@ -241,15 +241,6 @@ Field_Value :: struct {
value: ^Expr, value: ^Expr,
} }
Ternary_Expr :: struct {
using node: Expr,
cond: ^Expr,
op1: tokenizer.Token,
x: ^Expr,
op2: tokenizer.Token,
y: ^Expr,
}
Ternary_If_Expr :: struct { Ternary_If_Expr :: struct {
using node: Expr, using node: Expr,
x: ^Expr, x: ^Expr,
@@ -261,13 +252,26 @@ Ternary_If_Expr :: struct {
Ternary_When_Expr :: struct { Ternary_When_Expr :: struct {
using node: Expr, using node: Expr,
x: ^Expr, x: ^Expr,
op1: tokenizer.Token, op1: tokenizer.Token,
cond: ^Expr, cond: ^Expr,
op2: tokenizer.Token, op2: tokenizer.Token,
y: ^Expr, 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 { Type_Assertion :: struct {
using node: Expr, using node: Expr,
expr: ^Expr, expr: ^Expr,
@@ -542,7 +546,7 @@ Field_Flag :: enum {
No_Alias, No_Alias,
C_Vararg, C_Vararg,
Auto_Cast, Auto_Cast,
In, Any_Int,
Results, Results,
Tags, Tags,
+5 -4
View File
@@ -129,10 +129,6 @@ clone_node :: proc(node: ^Node) -> ^Node {
case Field_Value: case Field_Value:
r.field = clone(r.field); r.field = clone(r.field);
r.value = clone(r.value); 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: case Ternary_If_Expr:
r.x = clone(r.x); r.x = clone(r.x);
r.cond = clone(r.cond); r.cond = clone(r.cond);
@@ -141,6 +137,11 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.x = clone(r.x); r.x = clone(r.x);
r.cond = clone(r.cond); r.cond = clone(r.cond);
r.y = clone(r.y); 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: case Type_Assertion:
r.expr = clone(r.expr); r.expr = clone(r.expr);
r.type = clone(r.type); r.type = clone(r.type);
+5 -4
View File
@@ -126,10 +126,6 @@ walk :: proc(v: ^Visitor, node: ^Node) {
case Field_Value: case Field_Value:
walk(v, n.field); walk(v, n.field);
walk(v, n.value); walk(v, n.value);
case Ternary_Expr:
walk(v, n.cond);
walk(v, n.x);
walk(v, n.y);
case Ternary_If_Expr: case Ternary_If_Expr:
walk(v, n.x); walk(v, n.x);
walk(v, n.cond); walk(v, n.cond);
@@ -138,6 +134,11 @@ walk :: proc(v: ^Visitor, node: ^Node) {
walk(v, n.x); walk(v, n.x);
walk(v, n.cond); walk(v, n.cond);
walk(v, n.y); 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: case Type_Assertion:
walk(v, n.expr); walk(v, n.expr);
if n.type != nil { if n.type != nil {
+64 -47
View File
@@ -374,11 +374,14 @@ expect_token_after :: proc(p: ^Parser, kind: tokenizer.Token_Kind, msg: string)
expect_operator :: proc(p: ^Parser) -> tokenizer.Token { expect_operator :: proc(p: ^Parser) -> tokenizer.Token {
prev := p.curr_tok; prev := p.curr_tok;
if prev.kind == .If || prev.kind == .When { #partial switch prev.kind {
case .If, .When, .Or_Else, .Or_Return:
// okay // okay
} else if !tokenizer.is_operator(prev.kind) { case:
g := tokenizer.token_to_string(prev); if !tokenizer.is_operator(prev.kind) {
error(p, prev.pos, "expected an operator, got '%s'", g); g := tokenizer.token_to_string(prev);
error(p, prev.pos, "expected an operator, got '%s'", g);
}
} }
advance_token(p); advance_token(p);
return prev; return prev;
@@ -1366,9 +1369,9 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
stmt := parse_stmt(p); stmt := parse_stmt(p);
switch name { switch name {
case "bounds_check": case "bounds_check":
stmt.state_flags |= {.Bounds_Check}; stmt.state_flags += {.Bounds_Check};
case "no_bounds_check": case "no_bounds_check":
stmt.state_flags |= {.No_Bounds_Check}; stmt.state_flags += {.No_Bounds_Check};
} }
return stmt; return stmt;
case "partial": case "partial":
@@ -1449,7 +1452,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
token_precedence :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> int { token_precedence :: proc(p: ^Parser, kind: tokenizer.Token_Kind) -> int {
#partial switch kind { #partial switch kind {
case .Question, .If, .When: case .Question, .If, .When, .Or_Else, .Or_Return:
return 1; return 1;
case .Ellipsis, .Range_Half, .Range_Full: case .Ellipsis, .Range_Half, .Range_Full:
if !p.allow_range { if !p.allow_range {
@@ -1578,8 +1581,8 @@ Field_Prefix :: enum {
Using, Using,
No_Alias, No_Alias,
C_Vararg, C_Vararg,
In,
Auto_Cast, Auto_Cast,
Any_Int,
} }
Field_Prefixes :: distinct bit_set[Field_Prefix]; 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 { is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
using Field_Prefix;
#partial switch p.curr_tok.kind { #partial switch p.curr_tok.kind {
case .EOF: case .EOF:
return Invalid; return .Invalid;
case .Using: case .Using:
advance_token(p); advance_token(p);
return Using; return .Using;
case .In:
advance_token(p);
return In;
case .Auto_Cast: case .Auto_Cast:
advance_token(p); advance_token(p);
return Auto_Cast; return .Auto_Cast;
case .Hash: case .Hash:
advance_token(p); advance_token(p);
defer advance_token(p); defer advance_token(p);
@@ -1646,14 +1645,16 @@ is_token_field_prefix :: proc(p: ^Parser) -> Field_Prefix {
case .Ident: case .Ident:
switch p.curr_tok.text { switch p.curr_tok.text {
case "no_alias": case "no_alias":
return No_Alias; return .No_Alias;
case "c_vararg": 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 { 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 { for kind in Field_Prefix {
count := counts[kind]; count := counts[kind];
using Field_Prefix;
switch kind { switch kind {
case Invalid, Unknown: // Ignore case .Invalid, .Unknown: // Ignore
case Using: case .Using:
if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list"); } if count > 1 { error(p, p.curr_tok.pos, "multiple 'using' in this field list"); }
if count > 0 { flags |= {.Using}; } if count > 0 { flags += {.Using}; }
case No_Alias: case .No_Alias:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list"); } if count > 1 { error(p, p.curr_tok.pos, "multiple '#no_alias' in this field list"); }
if count > 0 { flags |= {.No_Alias}; } if count > 0 { flags += {.No_Alias}; }
case C_Vararg: case .C_Vararg:
if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list"); } if count > 1 { error(p, p.curr_tok.pos, "multiple '#c_vararg' in this field list"); }
if count > 0 { flags |= {.C_Vararg}; } if count > 0 { flags += {.C_Vararg}; }
case In: case .Auto_Cast:
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 > 1 { error(p, p.curr_tok.pos, "multiple 'auto_cast' in this field list"); } 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; flags = set_flags;
if name_count > 1 && .Using in 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"); 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 { 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"); error(p, p.curr_tok.pos, "'#c_vararg' is not allowed within this field list");
case .Auto_Cast: case .Auto_Cast:
error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list"); error(p, p.curr_tok.pos, "'auto_cast' is not allowed within this field list");
case .In: case .Any_Int:
error(p, p.curr_tok.pos, "'in' is not allowed within this field list"); error(p, p.curr_tok.pos, "'#any_int' is not allowed within this field list");
case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token: case .Tags, .Ellipsis, .Results, .Default_Parameters, .Typeid_Token:
panic("Impossible prefixes"); 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); ident := expect_token(p, .Ident);
switch ident.text { switch ident.text {
case "bounds_check": tags |= {.Bounds_Check}; case "bounds_check": tags += {.Bounds_Check};
case "no_bounds_check": tags |= {.No_Bounds_Check}; case "no_bounds_check": tags += {.No_Bounds_Check};
case "optional_ok": tags |= {.Optional_Ok}; case "optional_ok": tags += {.Optional_Ok};
case "optional_second": tags |= {.Optional_Second}; case "optional_second": tags += {.Optional_Second};
case: case:
} }
} }
@@ -2267,12 +2267,12 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
switch name.text { switch name.text {
case "bounds_check": case "bounds_check":
operand.state_flags |= {.Bounds_Check}; operand.state_flags += {.Bounds_Check};
if .No_Bounds_Check in operand.state_flags { if .No_Bounds_Check in operand.state_flags {
error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together"); error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together");
} }
case "no_bounds_check": case "no_bounds_check":
operand.state_flags |= {.No_Bounds_Check}; operand.state_flags += {.No_Bounds_Check};
if .Bounds_Check in operand.state_flags { if .Bounds_Check in operand.state_flags {
error(p, name.pos, "#bounds_check and #no_bounds_check cannot be applied together"); 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 prec := token_precedence(p, p.curr_tok.kind); prec >= prec_in; prec -= 1 {
for { loop: for {
op := p.curr_tok; op := p.curr_tok;
op_prec := token_precedence(p, op.kind); op_prec := token_precedence(p, op.kind);
if op_prec != prec { 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 { 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 // 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); x := parse_expr(p, lhs);
colon := expect_token(p, .Colon); colon := expect_token(p, .Colon);
y := parse_expr(p, lhs); 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.cond = cond;
te.op1 = op; te.op1 = op;
te.x = x; te.x = x;
@@ -3212,6 +3214,21 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr {
te.y = y; te.y = y;
expr = te; 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: case:
right := parse_binary_expr(p, false, prec+1); right := parse_binary_expr(p, false, prec+1);
if right == nil { if right == nil {
+7 -6
View File
@@ -944,12 +944,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
case Auto_Cast: case Auto_Cast:
push_generic_token(p, v.op.kind, 1); push_generic_token(p, v.op.kind, 1);
visit_expr(p, v.expr); 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: case Ternary_If_Expr:
visit_expr(p, v.x); visit_expr(p, v.x);
push_generic_token(p, v.op1.kind, 1); 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); visit_expr(p, v.cond);
push_generic_token(p, v.op2.kind, 1); push_generic_token(p, v.op2.kind, 1);
visit_expr(p, v.y); 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: case Selector_Call_Expr:
visit_expr(p, v.call.expr); visit_expr(p, v.call.expr);
push_generic_token(p, .Open_Paren, 1); push_generic_token(p, .Open_Paren, 1);
+8 -4
View File
@@ -144,10 +144,12 @@ Token_Kind :: enum u32 {
Transmute, // transmute Transmute, // transmute
Distinct, // distinct Distinct, // distinct
Using, // using Using, // using
Context, // context
Or_Else, // or_else
Or_Return, // or_return
Asm, // asm
Inline, // inline Inline, // inline
No_Inline, // no_inline No_Inline, // no_inline
Context, // context
Asm, // asm
B_Keyword_End, B_Keyword_End,
COUNT, COUNT,
@@ -272,10 +274,12 @@ tokens := [Token_Kind.COUNT]string {
"transmute", "transmute",
"distinct", "distinct",
"using", "using",
"context",
"or_else",
"or_return",
"asm",
"inline", "inline",
"no_inline", "no_inline",
"context",
"asm",
"", "",
}; };
+1 -1
View File
@@ -724,7 +724,7 @@ scan :: proc(t: ^Tokenizer) -> Token {
case .Ident, .Context, .Typeid, .Break, .Continue, .Fallthrough, .Return, case .Ident, .Context, .Typeid, .Break, .Continue, .Fallthrough, .Return,
.Integer, .Float, .Imag, .Rune, .String, .Undef, .Integer, .Float, .Imag, .Rune, .String, .Undef,
.Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace, .Question, .Pointer, .Close_Paren, .Close_Bracket, .Close_Brace,
.Increment, .Decrement: .Increment, .Decrement, .Or_Return:
/*fallthrough*/ /*fallthrough*/
t.insert_semicolon = true; t.insert_semicolon = true;
case: case:
+1 -1
View File
@@ -57,7 +57,7 @@ link_error_delete :: proc(lerr: Maybe(Link_Error)) {
is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) { 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; return v.err, v.err != 0;
} }
+1 -1
View File
@@ -13,7 +13,7 @@ error_to_io_error :: proc(ferr: Error) -> io.Error {
if ferr == nil { if ferr == nil {
return .None; return .None;
} }
return or_else(ferr.(io.Error), .Unknown); return ferr.(io.Error) or_else .Unknown;
} }
+1 -4
View File
@@ -298,10 +298,7 @@ _glob :: proc(dir, pattern: string, matches: ^[dynamic]string) -> (m: [dynamic]s
for fi in fis { for fi in fis {
n := fi.name; n := fi.name;
matched, err := match(pattern, n); matched := match(pattern, n) or_return;
if err != nil {
return m, err;
}
if matched { if matched {
append(&m, join(dir, n)); append(&m, join(dir, n));
} }
+1 -1
View File
@@ -129,7 +129,7 @@ _Recursive_Mutex :: struct {
} }
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) { _recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
tid := runtime.current_thread_id(); tid := _current_thread_id();
if tid != m.impl.owner { if tid != m.impl.owner {
mutex_lock(&m.impl.mutex); mutex_lock(&m.impl.mutex);
} }
+1 -1
View File
@@ -68,7 +68,7 @@ Thread_Os_Specific :: struct {
thread_create :: proc(procedure: Thread_Proc) -> ^Thread { thread_create :: proc(procedure: Thread_Proc) -> ^Thread {
__windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD {
t := (^Thread)(t_); t := (^Thread)(t_);
context = or_else(t.init_context.?, runtime.default_context()); context = t.init_context.? or_else runtime.default_context();
t.procedure(t); t.procedure(t);
+1 -1
View File
@@ -46,7 +46,7 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
t.start_gate = {}; t.start_gate = {};
t.start_mutex = {}; t.start_mutex = {};
context = or_else(t.init_context.?, runtime.default_context()); context = t.init_context.? or_else runtime.default_context();
t.procedure(t); t.procedure(t);
+1 -1
View File
@@ -23,7 +23,7 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
__windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD { __windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD {
t := (^Thread)(t_); t := (^Thread)(t_);
context = or_else(t.init_context.?, runtime.default_context()); context = t.init_context.? or_else runtime.default_context();
t.procedure(t); t.procedure(t);
+50 -50
View File
@@ -3,57 +3,57 @@ package all
// Imports every package // Imports every package
// This is useful for knowing what exists and producing documentation with `odin doc` // This is useful for knowing what exists and producing documentation with `odin doc`
import "core:bufio" import bufio "core:bufio"
import "core:bytes" import bytes "core:bytes"
import "core:c" import c "core:c"
import c_tokenizer "core:c/frontend/tokenizer" import c_tokenizer "core:c/frontend/tokenizer"
import c_preprocessor "core:c/frontend/preprocessor" import c_preprocessor "core:c/frontend/preprocessor"
import "core:compress" import compress "core:compress"
import "core:compress/gzip" import gzip "core:compress/gzip"
import "core:compress/zlib" import zlib "core:compress/zlib"
import "core:container" import container "core:container"
import "core:dynlib" import dynlib "core:dynlib"
import "core:encoding" import encoding "core:encoding"
import "core:encoding/base32" import base32 "core:encoding/base32"
import "core:encoding/base64" import base64 "core:encoding/base64"
import "core:encoding/csv" import csv "core:encoding/csv"
import "core:encoding/hxa" import hxa "core:encoding/hxa"
import "core:encoding/json" import json "core:encoding/json"
import "core:fmt" import fmt "core:fmt"
import "core:hash" import hash "core:hash"
import "core:image" import image "core:image"
import "core:image/png" import png "core:image/png"
import "core:io" import io "core:io"
import "core:log" import log "core:log"
import "core:math" import math "core:math"
import "core:math/big" import big "core:math/big"
import "core:math/bits" import bits "core:math/bits"
import "core:math/fixed" import fixed "core:math/fixed"
import "core:math/linalg" import linalg "core:math/linalg"
import "core:math/rand" import rand "core:math/rand"
import "core:mem" import mem "core:mem"
import "core:odin/ast" import ast "core:odin/ast"
import doc_format "core:odin/doc-format" import doc_format "core:odin/doc-format"
import "core:odin/format" import odin_format "core:odin/format"
import "core:odin/parser" import odin_parser "core:odin/parser"
import "core:odin/printer" import odin_printer "core:odin/printer"
import odin_tokenizer "core:odin/tokenizer" import odin_tokenizer "core:odin/tokenizer"
import "core:os" import os "core:os"
import "core:path" import path "core:path"
import "core:path/filepath" import filepath "core:path/filepath"
import "core:reflect" import reflect "core:reflect"
import "core:runtime" import runtime "core:runtime"
import "core:slice" import slice "core:slice"
import "core:sort" import sort "core:sort"
import "core:strconv" import strconv "core:strconv"
import "core:strings" import strings "core:strings"
import "core:sync" import sync "core:sync"
import "core:sync/sync2" import sync2 "core:sync/sync2"
import "core:text/scanner" import scanner "core:text/scanner"
import "core:thread" import thread "core:thread"
import "core:time" import time "core:time"
import "core:unicode" import unicode "core:unicode"
import "core:unicode/utf8" import utf8 "core:unicode/utf8"
import "core:unicode/utf16" import utf16 "core:unicode/utf16"
main :: proc(){} main :: proc(){}
+109 -8
View File
@@ -1998,9 +1998,9 @@ relative_data_types :: proc() {
fmt.println(rel_slice[1]); fmt.println(rel_slice[1]);
} }
or_else_procedure :: proc() { or_else_operator :: proc() {
fmt.println("\n#'or_else'"); 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; m: map[string]int;
i: int; i: int;
@@ -2010,7 +2010,7 @@ or_else_procedure :: proc() {
i = 123; i = 123;
} }
// The above can be mapped to 'or_else' // The above can be mapped to 'or_else'
i = or_else(m["hellope"], 123); i = m["hellope"] or_else 123;
assert(i == 123); assert(i == 123);
} }
@@ -2019,16 +2019,117 @@ or_else_procedure :: proc() {
// have optional ok semantics // have optional ok semantics
v: union{int, f64}; v: union{int, f64};
i: int; i: int;
i = or_else(v.(int), 123); i = v.(int) or_else 123;
i = or_else(v.?, 123); // Type inference magic i = v.? or_else 123; // Type inference magic
assert(i == 123); assert(i == 123);
m: Maybe(int); m: Maybe(int);
i = or_else(m.?, 456); i = m.? or_else 456;
assert(i == 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() { main :: proc() {
when true { when true {
the_basics(); the_basics();
@@ -2061,7 +2162,7 @@ main :: proc() {
union_maybe(); union_maybe();
explicit_context_definition(); explicit_context_definition();
relative_data_types(); relative_data_types();
or_else_procedure(); or_else_operator();
or_return_operator();
} }
} }
//
+40 -51
View File
@@ -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_) { void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_) {
Type *left_type = nullptr; Type *left_type = nullptr;
Type *right_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 (left_type_) *left_type_ = left_type;
if (right_type_) *right_type_ = right_type; if (right_type_) *right_type_ = right_type;
if (!is_type_boolean(right_type)) { check_or_else_right_type(c, x->expr, name, 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);
}
} }
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 // TODO(bill): better error message
gbString t = type_to_string(x.type); gbString t = type_to_string(x.type);
error(x.expr, "'%.*s' does not return a value, value is of type %s", LIT(name), t); 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) { bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint) {
ast_node(ce, CallExpr, call); ast_node(ce, CallExpr, call);
if (ce->inlining != ProcInlining_none) { 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 // NOTE(bill): The first arg may be a Type, this will be checked case by case
break; break;
case BuiltinProc_or_else:
// NOTE(bill): The arguments may be multi-expr
break;
case BuiltinProc_DIRECTIVE: { case BuiltinProc_DIRECTIVE: {
ast_node(bd, BasicDirective, ce->proc); ast_node(bd, BasicDirective, ce->proc);
String name = bd->name.string; String name = bd->name.string;
@@ -1800,47 +1830,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
break; 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: { case BuiltinProc_simd_vector: {
Operand x = {}; Operand x = {};
Operand y = {}; Operand y = {};
+151
View File
@@ -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_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) { Entity *entity_from_expr(Ast *expr) {
expr = unparen_expr(expr); expr = unparen_expr(expr);
switch (expr->kind) { 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); update_untyped_expr_type(c, te->y, type, final);
case_end; 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); case_ast_node(pe, ParenExpr, e);
update_untyped_expr_type(c, pe->expr, type, final); update_untyped_expr_type(c, pe->expr, type, final);
case_end; case_end;
@@ -6602,6 +6626,123 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
} }
case_end; 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); case_ast_node(cl, CompoundLit, node);
Type *type = type_hint; Type *type = type_hint;
if (type != nullptr && is_type_untyped(type)) { 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); str = write_expr_to_string(str, te->y, shorthand);
case_end; 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); case_ast_node(pe, ParenExpr, node);
str = gb_string_append_rune(str, '('); str = gb_string_append_rune(str, '(');
+6 -4
View File
@@ -1480,8 +1480,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
if (kind == Expr_Stmt) { if (kind == Expr_Stmt) {
return; return;
} }
if (operand.expr->kind == Ast_CallExpr) { Ast *expr = strip_or_return_expr(operand.expr);
AstCallExpr *ce = &operand.expr->CallExpr;
if (expr->kind == Ast_CallExpr) {
AstCallExpr *ce = &expr->CallExpr;
Type *t = type_of_expr(ce->proc); Type *t = type_of_expr(ce->proc);
if (is_type_proc(t)) { if (is_type_proc(t)) {
if (t->Proc.require_results) { if (t->Proc.require_results) {
@@ -1491,8 +1493,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
} }
} }
return; return;
} else if (operand.expr->kind == Ast_SelectorCallExpr) { } else if (expr->kind == Ast_SelectorCallExpr) {
AstSelectorCallExpr *se = &operand.expr->SelectorCallExpr; AstSelectorCallExpr *se = &expr->SelectorCallExpr;
ast_node(ce, CallExpr, se->call); ast_node(ce, CallExpr, se->call);
Type *t = type_of_expr(ce->proc); Type *t = type_of_expr(ce->proc);
if (is_type_proc(t)) { if (is_type_proc(t)) {
-4
View File
@@ -33,8 +33,6 @@ enum BuiltinProcId {
BuiltinProc_soa_zip, BuiltinProc_soa_zip,
BuiltinProc_soa_unzip, BuiltinProc_soa_unzip,
BuiltinProc_or_else,
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
// "Intrinsics" // "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_zip"), 1, true, Expr_Expr, BuiltinProcPkg_builtin},
{STR_LIT("soa_unzip"), 1, false, 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 {STR_LIT(""), 0, true, Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
+8
View File
@@ -2305,6 +2305,14 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
} }
case_end; 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); case_ast_node(ta, TypeAssertion, expr);
TokenPos pos = ast_token(expr).pos; TokenPos pos = ast_token(expr).pos;
Type *type = tv.type; Type *type = tv.type;
-3
View File
@@ -1252,9 +1252,6 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
case BuiltinProc_soa_unzip: case BuiltinProc_soa_unzip:
return lb_soa_unzip(p, ce, tv); 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" // "Intrinsics"
case BuiltinProc_alloca: case BuiltinProc_alloca:
+42
View File
@@ -364,6 +364,48 @@ lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, TypeAndValue c
return res; return res;
} }
void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> 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) { void lb_emit_increment(lbProcedure *p, lbValue addr) {
+57 -5
View File
@@ -187,6 +187,13 @@ Ast *clone_ast(Ast *node) {
n->TernaryWhenExpr.cond = clone_ast(n->TernaryWhenExpr.cond); n->TernaryWhenExpr.cond = clone_ast(n->TernaryWhenExpr.cond);
n->TernaryWhenExpr.y = clone_ast(n->TernaryWhenExpr.y); n->TernaryWhenExpr.y = clone_ast(n->TernaryWhenExpr.y);
break; 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: case Ast_TypeAssertion:
n->TypeAssertion.expr = clone_ast(n->TypeAssertion.expr); n->TypeAssertion.expr = clone_ast(n->TypeAssertion.expr);
n->TypeAssertion.type = clone_ast(n->TypeAssertion.type); 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; 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 *ast_type_assertion(AstFile *f, Ast *expr, Token dot, Ast *type) {
Ast *result = alloc_ast_node(f, Ast_TypeAssertion); Ast *result = alloc_ast_node(f, Ast_TypeAssertion);
result->TypeAssertion.expr = expr; result->TypeAssertion.expr = expr;
@@ -1340,6 +1362,8 @@ Token expect_operator(AstFile *f) {
// okay // okay
} else if (prev.kind == Token_if || prev.kind == Token_when) { } else if (prev.kind == Token_if || prev.kind == Token_when) {
// okay // 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)) { } else if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
String p = token_to_string(prev); String p = token_to_string(prev);
syntax_error(f->curr_token, "Expected an operator, got '%.*s'", syntax_error(f->curr_token, "Expected an operator, got '%.*s'",
@@ -1674,6 +1698,22 @@ Ast *unselector_expr(Ast *node) {
return 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); Ast *parse_value(AstFile *f);
Array<Ast *> parse_element_list(AstFile *f) { Array<Ast *> 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 *parse_force_inlining_operand(AstFile *f, Token token) {
Ast *expr = parse_unary_expr(f, false); 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) { 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])); 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); 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)); operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer));
break; break;
case Token_or_return:
operand = ast_or_return_expr(f, operand, expect_token(f, Token_or_return));
break;
case Token_OpenBrace: case Token_OpenBrace:
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) { if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
operand = parse_literal_value(f, operand); operand = parse_literal_value(f, operand);
@@ -2870,6 +2914,7 @@ i32 token_precedence(AstFile *f, TokenKind t) {
case Token_Question: case Token_Question:
case Token_if: case Token_if:
case Token_when: case Token_when:
case Token_or_else:
return 1; return 1;
case Token_Ellipsis: case Token_Ellipsis:
case Token_RangeFull: 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 // NOTE(bill): This will also catch operators that are not valid "binary" operators
break; 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) { 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 // 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 expect_operator(f); // NOTE(bill): error checks too
if (op.kind == Token_Question) { 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); Token tok_else = expect_token(f, Token_else);
Ast *y = parse_expr(f, lhs); Ast *y = parse_expr(f, lhs);
expr = ast_ternary_when_expr(f, x, cond, y); 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 { } else {
Ast *right = parse_binary_expr(f, false, prec+1); Ast *right = parse_binary_expr(f, false, prec+1);
if (right == nullptr) { if (right == nullptr) {
@@ -2965,6 +3016,7 @@ Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
lhs = false; lhs = false;
} }
loop_end:;
} }
return expr; return expr;
} }
+2
View File
@@ -385,6 +385,8 @@ AST_KIND(_ExprBegin, "", bool) \
AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \ AST_KIND(FieldValue, "field value", struct { Token eq; Ast *field, *value; }) \
AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \ AST_KIND(TernaryIfExpr, "ternary if expression", struct { Ast *x, *cond, *y; }) \
AST_KIND(TernaryWhenExpr, "ternary when 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_KIND(TypeAssertion, "type assertion", struct { \
Ast *expr; \ Ast *expr; \
Token dot; \ Token dot; \
+4
View File
@@ -41,6 +41,8 @@ Token ast_token(Ast *node) {
case Ast_DerefExpr: return node->DerefExpr.op; case Ast_DerefExpr: return node->DerefExpr.op;
case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x); case Ast_TernaryIfExpr: return ast_token(node->TernaryIfExpr.x);
case Ast_TernaryWhenExpr: return ast_token(node->TernaryWhenExpr.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_TypeAssertion: return ast_token(node->TypeAssertion.expr);
case Ast_TypeCast: return node->TypeCast.token; case Ast_TypeCast: return node->TypeCast.token;
case Ast_AutoCast: return node->AutoCast.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_DerefExpr: return node->DerefExpr.op;
case Ast_TernaryIfExpr: return ast_end_token(node->TernaryIfExpr.y); case Ast_TernaryIfExpr: return ast_end_token(node->TernaryIfExpr.y);
case Ast_TernaryWhenExpr: return ast_end_token(node->TernaryWhenExpr.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_TypeAssertion: return ast_end_token(node->TypeAssertion.type);
case Ast_TypeCast: return ast_end_token(node->TypeCast.expr); case Ast_TypeCast: return ast_end_token(node->TypeCast.expr);
case Ast_AutoCast: return ast_end_token(node->AutoCast.expr); case Ast_AutoCast: return ast_end_token(node->AutoCast.expr);
+5 -2
View File
@@ -113,10 +113,12 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
TOKEN_KIND(Token_transmute, "transmute"), \ TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_distinct, "distinct"), \ TOKEN_KIND(Token_distinct, "distinct"), \
TOKEN_KIND(Token_using, "using"), \ 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_inline, "inline"), \
TOKEN_KIND(Token_no_inline, "no_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__KeywordEnd, ""), \
TOKEN_KIND(Token_Count, "") TOKEN_KIND(Token_Count, "")
@@ -1508,6 +1510,7 @@ semicolon_check:;
case Token_continue: case Token_continue:
case Token_fallthrough: case Token_fallthrough:
case Token_return: case Token_return:
case Token_or_return:
/*fallthrough*/ /*fallthrough*/
case Token_Integer: case Token_Integer:
case Token_Float: case Token_Float: