#Case for all possible integer types

1 messages · Page 1 of 1 (latest)

paper grail
#

I have the following function that handles few types, but what I want really is to support all possible integer types. If the value is out of range, error is thrown and control flow jumps back to parent process runtime.

How can I have a case for all integer types? I assume some kind of reflection.

/// Coerces primitive type to R atomic vector.
pub fn asScalarVector(from: anytype) Robject {
    const T = @TypeOf(from);

    //TODO: Handle arbitrary sized integers
    const out = switch (T) {
        f64 => r.Rf_ScalarReal(from),
        bool => r.Rf_ScalarLogical(@intCast(@intFromBool(from))),
        c_int, i32 => r.Rf_ScalarInteger(@intCast(from)),
        i64, u64, isize, usize, comptime_int => out: {
            if (from > math.maxInt(c_int)) {
                errors.stop("Number is larger than 32-bit integer can represent. Max: {d}, found: {d}", .{ math.maxInt(c_int), from });
                unreachable;
            }

            if (from < math.minInt(c_int)) {
                errors.stop("Number is smaller than 32-bit integer can represent. Min: {d}, found: {d}", .{ math.minInt(c_int), from });
                unreachable;
            }

            break :out r.Rf_ScalarInteger(@intCast(from));
        },
        else => @compileError("Attempting to coerce unsupported type"),
    };

    return out;
}
limber glade
#

switch on @typeInfo(T)

paper grail
#

And then case is .Int?

limber glade
#

yes and .ComptimeInt

paper grail
#

What about f64?

#

I guess it could also be f32

limber glade
#

ig it depends what all you want to handle

#

if you only want ints to be lenient you could do what youre doing now but move the int part into the main else branch

paper grail
#

Oh inside the case I can check for the bits

limber glade
#

something like

switch (T) {
    f64 => ...,
    bool => ...,
    else => switch (@typeInfo(T)) {
        .Int, .ComptimeInt => ...,
        else => @compileError(...),
    }
}
paper grail
#

Ah nice. Thanks!

#

Hmm where do I put the label?

/// Coerces primitive type to R atomic vector.
pub fn asScalarVector(from: anytype) Robject {
    const T = @TypeOf(from);

    const out = switch (T) {
        f32, f64 => r.Rf_ScalarReal(from),
        bool => r.Rf_ScalarLogical(@intCast(@intFromBool(from))),
        c_int, i32 => r.Rf_ScalarInteger(@intCast(from)),
        else => switch (@typeInfo(T)) {
            .Int, .ComptimeInt => {
                if (from > math.maxInt(c_int)) {
                    errors.stop("Number is larger than 32-bit integer can represent. Max: {d}, found: {d}", .{ math.maxInt(c_int), from });
                    unreachable;
                }

                if (from < math.minInt(c_int)) {
                    errors.stop("Number is smaller than 32-bit integer can represent. Min: {d}, found: {d}", .{ math.minInt(c_int), from });
                    unreachable;
                }

                break :out r.Rf_ScalarInteger(@intCast(from));
            },
            else => @compileError("Attempting to coerce unsupported type"),
        },
    };

    return out;
}
#

I thought it's after => but it doens't work because of the nested switch