| ... | @@ -1520,33 +1520,38 @@ pub const Value = struct { | ... | @@ -1520,33 +1520,38 @@ pub const Value = struct { |
| 1520 | /// Asserts the value is a single-item pointer to an array, or an array, | 1520 | /// Asserts the value is a single-item pointer to an array, or an array, |
| 1521 | /// or an unknown-length pointer, and returns the element value at the index. | 1521 | /// or an unknown-length pointer, and returns the element value at the index. |
| 1522 | pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value { | 1522 | pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value { |
| | 1523 | return (try val.maybeElemValue(mod, index)).?; |
| | 1524 | } |
| | 1525 | |
| | 1526 | /// Like `elemValue`, but returns `null` instead of asserting on failure. |
| | 1527 | pub fn maybeElemValue(val: Value, mod: *Module, index: usize) Allocator.Error!?Value { |
| 1523 | return switch (val.ip_index) { | 1528 | return switch (val.ip_index) { |
| 1524 | .none => switch (val.tag()) { | 1529 | .none => switch (val.tag()) { |
| 1525 | .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]), | 1530 | .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]), |
| 1526 | .repeated => val.castTag(.repeated).?.data, | 1531 | .repeated => val.castTag(.repeated).?.data, |
| 1527 | .aggregate => val.castTag(.aggregate).?.data[index], | 1532 | .aggregate => val.castTag(.aggregate).?.data[index], |
| 1528 | .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index), | 1533 | .slice => val.castTag(.slice).?.data.ptr.maybeElemValue(mod, index), |
| 1529 | else => unreachable, | 1534 | else => null, |
| 1530 | }, | 1535 | }, |
| 1531 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { | 1536 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1532 | .undef => |ty| (try mod.intern(.{ | 1537 | .undef => |ty| (try mod.intern(.{ |
| 1533 | .undef = ty.toType().elemType2(mod).toIntern(), | 1538 | .undef = ty.toType().elemType2(mod).toIntern(), |
| 1534 | })).toValue(), | 1539 | })).toValue(), |
| 1535 | .ptr => |ptr| switch (ptr.addr) { | 1540 | .ptr => |ptr| switch (ptr.addr) { |
| 1536 | .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index), | 1541 | .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), |
| 1537 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) | 1542 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) |
| 1538 | .toValue().elemValue(mod, index), | 1543 | .toValue().maybeElemValue(mod, index), |
| 1539 | .int, .eu_payload => unreachable, | 1544 | .int, .eu_payload => null, |
| 1540 | .opt_payload => |base| base.toValue().elemValue(mod, index), | 1545 | .opt_payload => |base| base.toValue().maybeElemValue(mod, index), |
| 1541 | .comptime_field => |field_val| field_val.toValue().elemValue(mod, index), | 1546 | .comptime_field => |field_val| field_val.toValue().maybeElemValue(mod, index), |
| 1542 | .elem => |elem| elem.base.toValue().elemValue(mod, index + @as(usize, @intCast(elem.index))), | 1547 | .elem => |elem| elem.base.toValue().maybeElemValue(mod, index + @as(usize, @intCast(elem.index))), |
| 1543 | .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| { | 1548 | .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| { |
| 1544 | const base_decl = mod.declPtr(decl_index); | 1549 | const base_decl = mod.declPtr(decl_index); |
| 1545 | const field_val = try base_decl.val.fieldValue(mod, @as(usize, @intCast(field.index))); | 1550 | const field_val = try base_decl.val.fieldValue(mod, @as(usize, @intCast(field.index))); |
| 1546 | return field_val.elemValue(mod, index); | 1551 | return field_val.maybeElemValue(mod, index); |
| 1547 | } else unreachable, | 1552 | } else null, |
| 1548 | }, | 1553 | }, |
| 1549 | .opt => |opt| opt.val.toValue().elemValue(mod, index), | 1554 | .opt => |opt| opt.val.toValue().maybeElemValue(mod, index), |
| 1550 | .aggregate => |aggregate| { | 1555 | .aggregate => |aggregate| { |
| 1551 | const len = mod.intern_pool.aggregateTypeLen(aggregate.ty); | 1556 | const len = mod.intern_pool.aggregateTypeLen(aggregate.ty); |
| 1552 | if (index < len) return switch (aggregate.storage) { | 1557 | if (index < len) return switch (aggregate.storage) { |
| ... | @@ -1560,7 +1565,7 @@ pub const Value = struct { | ... | @@ -1560,7 +1565,7 @@ pub const Value = struct { |
| 1560 | assert(index == len); | 1565 | assert(index == len); |
| 1561 | return mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel.toValue(); | 1566 | return mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel.toValue(); |
| 1562 | }, | 1567 | }, |
| 1563 | else => unreachable, | 1568 | else => null, |
| 1564 | }, | 1569 | }, |
| 1565 | }; | 1570 | }; |
| 1566 | } | 1571 | } |