Skip to content

Commit 5540178

Browse files
Add helper functions for type coercion
1 parent a071efb commit 5540178

File tree

2 files changed

+160
-1
lines changed

2 files changed

+160
-1
lines changed

src/analyser/InternPool.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2495,7 +2495,7 @@ const InMemoryCoercionResult = union(enum) {
24952495
/// * error union: coerceable error set and payload
24962496
/// * error set: sub-set to super-set
24972497
/// * array: same shape and coerceable child
2498-
fn coerceInMemoryAllowed(
2498+
pub fn coerceInMemoryAllowed(
24992499
ip: *InternPool,
25002500
gpa: Allocator,
25012501
arena: Allocator,

src/analysis.zig

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7219,3 +7219,162 @@ fn typeIsPointerAtRuntime(analyser: *Analyser, ty: Type) bool {
72197219
.one, .many => !ptr_info.is_optional or !ptr_info.flags.is_allowzero,
72207220
};
72217221
}
7222+
7223+
fn typeIsSlice(analyser: *Analyser, ty: Type) bool {
7224+
const ptr_info = analyser.typePointerInfo(ty) orelse return false;
7225+
if (ptr_info.is_optional) return false;
7226+
return switch (ptr_info.flags.size) {
7227+
.slice => true,
7228+
.one, .many, .c => false,
7229+
};
7230+
}
7231+
7232+
fn typePointerOrOptionalPointerType(analyser: *Analyser, ty: Type) !?Type {
7233+
return switch (ty.data) {
7234+
.pointer => |ptr_info| switch (ptr_info.size) {
7235+
.one, .many, .c => ty,
7236+
.slice => null,
7237+
},
7238+
.optional => |opt_child| {
7239+
const ptr_info = analyser.typePointerInfo(ty) orelse return null;
7240+
return switch (ptr_info.flags.size) {
7241+
.slice, .c => null,
7242+
.many, .one => {
7243+
if (ptr_info.flags.is_allowzero) return null;
7244+
7245+
if (try analyser.typeHasOnePossibleValue(opt_child.*) != null) {
7246+
return null;
7247+
}
7248+
7249+
return opt_child.*;
7250+
},
7251+
};
7252+
},
7253+
.ip_index => null, // TODO
7254+
else => null,
7255+
};
7256+
}
7257+
7258+
fn typeHasOnePossibleValue(analyser: *Analyser, ty: Type) !?InternPool.Index {
7259+
std.debug.assert(ty.is_type_val);
7260+
const ip_index = switch (ty.data) {
7261+
.ip_index => |payload| payload.index orelse return null,
7262+
else => return null,
7263+
};
7264+
if (ip_index == .unknown_type) return null;
7265+
return analyser.ip.onePossibleValue(ip_index);
7266+
}
7267+
7268+
fn resolvePairInMemoryCoercible(analyser: *Analyser, ty_a: Type, ty_b: Type) !?Type {
7269+
if (try analyser.coerceInMemoryAllowed(ty_a, ty_b, false)) {
7270+
return ty_a;
7271+
}
7272+
7273+
if (try analyser.coerceInMemoryAllowed(ty_b, ty_a, false)) {
7274+
return ty_b;
7275+
}
7276+
7277+
return null;
7278+
}
7279+
7280+
fn coerceInMemoryAllowed(
7281+
analyser: *Analyser,
7282+
dest_ty: Type,
7283+
src_ty: Type,
7284+
dest_is_mut: bool,
7285+
) error{OutOfMemory}!bool {
7286+
std.debug.assert(dest_ty.is_type_val);
7287+
std.debug.assert(src_ty.is_type_val);
7288+
7289+
if (dest_ty.eql(src_ty))
7290+
return true;
7291+
7292+
// Primitives / Error Sets
7293+
if (dest_ty.data == .ip_index and src_ty.data == .ip_index) {
7294+
const dest_ip_index = dest_ty.data.ip_index.index orelse return false;
7295+
const src_ip_index = src_ty.data.ip_index.index orelse return false;
7296+
const result = try analyser.ip.coerceInMemoryAllowed(analyser.gpa, analyser.arena, dest_ip_index, src_ip_index, !dest_is_mut, builtin.target);
7297+
return result == .ok;
7298+
}
7299+
7300+
// Pointers / Pointer-like Optionals
7301+
const maybe_dest_ptr_ty = try analyser.typePointerOrOptionalPointerType(dest_ty);
7302+
const maybe_src_ptr_ty = try analyser.typePointerOrOptionalPointerType(src_ty);
7303+
if (maybe_dest_ptr_ty) |dest_ptr_ty| {
7304+
if (maybe_src_ptr_ty) |src_ptr_ty| {
7305+
return try analyser.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut);
7306+
}
7307+
}
7308+
7309+
// Slices
7310+
if (analyser.typeIsSlice(dest_ty) and analyser.typeIsSlice(src_ty)) {
7311+
return try analyser.coerceInMemoryAllowedPtrs(dest_ty, src_ty, dest_ty, src_ty, dest_is_mut);
7312+
}
7313+
7314+
// Functions
7315+
if (dest_ty.data == .function and src_ty.data == .function) {
7316+
return try analyser.coerceInMemoryAllowedFns(dest_ty, src_ty, dest_is_mut);
7317+
}
7318+
7319+
// Error Unions
7320+
if (dest_ty.data == .error_union and src_ty.data == .error_union) {
7321+
// TODO
7322+
return false;
7323+
}
7324+
7325+
// Arrays
7326+
if (dest_ty.data == .array and src_ty.data == .array) {
7327+
// TODO
7328+
return false;
7329+
}
7330+
7331+
// TODO: coerce non-primitive vectors/arrays
7332+
7333+
// Optionals
7334+
if (dest_ty.data == .optional and src_ty.data == .optional) {
7335+
// TODO
7336+
return false;
7337+
}
7338+
7339+
// Tuples (with in-memory-coercible fields)
7340+
if (dest_ty.data == .tuple and src_ty.data == .tuple) {
7341+
// TODO
7342+
return false;
7343+
}
7344+
7345+
return false;
7346+
}
7347+
7348+
fn coerceInMemoryAllowedErrorSets(
7349+
analyser: *Analyser,
7350+
dest_ty: Type,
7351+
src_ty: Type,
7352+
) !bool {
7353+
// TODO
7354+
_ = .{ analyser, dest_ty, src_ty };
7355+
return false;
7356+
}
7357+
7358+
fn coerceInMemoryAllowedFns(
7359+
analyser: *Analyser,
7360+
dest_ty: Type,
7361+
src_ty: Type,
7362+
dest_is_mut: bool,
7363+
) !bool {
7364+
// TODO
7365+
_ = .{ analyser, dest_ty, src_ty, dest_is_mut };
7366+
return false;
7367+
}
7368+
7369+
fn coerceInMemoryAllowedPtrs(
7370+
analyser: *Analyser,
7371+
dest_ty: Type,
7372+
src_ty: Type,
7373+
dest_ptr_ty: Type,
7374+
src_ptr_ty: Type,
7375+
dest_is_mut: bool,
7376+
) !bool {
7377+
// TODO
7378+
_ = .{ analyser, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut };
7379+
return false;
7380+
}

0 commit comments

Comments
 (0)