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