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