mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-09 02:54:49 +00:00
Add some new tests
This commit is contained in:
parent
4b6876ce98
commit
d6e802c50f
2 changed files with 52 additions and 49 deletions
|
|
@ -264,6 +264,7 @@ pub const Interpreter = struct {
|
|||
active_closures: std.array_list.Managed(StackValue),
|
||||
canonical_bool_rt_var: ?types.Var,
|
||||
canonical_str_rt_var: ?types.Var,
|
||||
cached_list_u8_rt_var: ?types.Var,
|
||||
// Used to unwrap extensible tags
|
||||
scratch_tags: std.array_list.Managed(types.Tag),
|
||||
/// Builtin types required by the interpreter (Bool, Try, etc.)
|
||||
|
|
@ -422,6 +423,7 @@ pub const Interpreter = struct {
|
|||
.active_closures = try std.array_list.Managed(StackValue).initCapacity(allocator, 4),
|
||||
.canonical_bool_rt_var = null,
|
||||
.canonical_str_rt_var = null,
|
||||
.cached_list_u8_rt_var = null,
|
||||
.scratch_tags = try std.array_list.Managed(types.Tag).initCapacity(allocator, 8),
|
||||
.builtins = builtin_types,
|
||||
.def_stack = try std.array_list.Managed(DefInProgress).initCapacity(allocator, 4),
|
||||
|
|
@ -1490,19 +1492,36 @@ pub const Interpreter = struct {
|
|||
// Get the result layout - should be List(U8).
|
||||
// If return_rt_var is a flex that would default to a scalar,
|
||||
// we need to ensure we get a proper list layout for correct refcounting.
|
||||
const result_rt_var = return_rt_var orelse {
|
||||
const provided_rt_var = return_rt_var orelse {
|
||||
self.triggerCrash("str_to_utf8 requires return type info", false, roc_ops);
|
||||
return error.Crash;
|
||||
};
|
||||
const result_layout = blk: {
|
||||
const maybe_layout = try self.getRuntimeLayout(result_rt_var);
|
||||
// If the layout is a list, use it
|
||||
if (maybe_layout.tag == .list or maybe_layout.tag == .list_of_zst) {
|
||||
break :blk maybe_layout;
|
||||
|
||||
// Get the result layout - should be List(U8).
|
||||
// If the provided_rt_var leads to a non-list layout, we need to create
|
||||
// a proper List(U8) type to ensure correct method dispatch.
|
||||
const u8_layout_idx = try self.runtime_layout_store.insertLayout(Layout.int(.u8));
|
||||
const list_u8_layout = Layout.list(u8_layout_idx);
|
||||
|
||||
const maybe_layout = try self.getRuntimeLayout(provided_rt_var);
|
||||
const result_rt_var, const result_layout = if (maybe_layout.tag == .list or maybe_layout.tag == .list_of_zst) blk: {
|
||||
// Layout is already a list - check if the type is also a List
|
||||
const resolved_rt = self.runtime_types.resolveVar(provided_rt_var);
|
||||
const is_list_type = switch (resolved_rt.desc.content) {
|
||||
.structure => |s| switch (s) {
|
||||
.nominal_type => true,
|
||||
else => false,
|
||||
},
|
||||
else => false,
|
||||
};
|
||||
if (is_list_type) {
|
||||
break :blk .{ provided_rt_var, maybe_layout };
|
||||
}
|
||||
// Fallback: create a proper List(U8) layout
|
||||
const u8_layout_idx = try self.runtime_layout_store.insertLayout(Layout.int(.u8));
|
||||
break :blk Layout.list(u8_layout_idx);
|
||||
// Layout is list but type is not nominal - create proper List(U8) type
|
||||
break :blk .{ try self.createListU8Type(), list_u8_layout };
|
||||
} else blk: {
|
||||
// Layout is not a list - create both proper layout and type
|
||||
break :blk .{ try self.createListU8Type(), list_u8_layout };
|
||||
};
|
||||
|
||||
var out = try self.pushRaw(result_layout, 0, result_rt_var);
|
||||
|
|
@ -7626,6 +7645,28 @@ pub const Interpreter = struct {
|
|||
return try self.runtime_types.freshFromContent(list_content);
|
||||
}
|
||||
|
||||
/// Create List(U8) type for runtime type propagation.
|
||||
/// Used by str_to_utf8 to ensure correct method dispatch.
|
||||
fn createListU8Type(self: *Interpreter) !types.Var {
|
||||
// Return cached value if available
|
||||
if (self.cached_list_u8_rt_var) |cached| return cached;
|
||||
|
||||
const origin_module_id = self.root_env.idents.builtin_module;
|
||||
|
||||
// Create U8 type
|
||||
const u8_type_name = "U8";
|
||||
const u8_type_name_ident = try self.runtime_layout_store.env.insertIdent(base_pkg.Ident.for_text(u8_type_name));
|
||||
const u8_type_ident = types.TypeIdent{ .ident_idx = u8_type_name_ident };
|
||||
const u8_backing_var = try self.runtime_types.freshFromContent(.{ .flex = types.Flex.init() });
|
||||
const u8_content = try self.runtime_types.mkNominal(u8_type_ident, u8_backing_var, &.{}, origin_module_id, false);
|
||||
const u8_rt_var = try self.runtime_types.freshFromContent(u8_content);
|
||||
|
||||
// Create List(U8) type and cache it
|
||||
const list_u8_var = try self.createListTypeWithElement(u8_rt_var);
|
||||
self.cached_list_u8_rt_var = list_u8_var;
|
||||
return list_u8_var;
|
||||
}
|
||||
|
||||
/// Create a type variable from a layout. Used as a fallback when type info is corrupted.
|
||||
/// Recursively handles nested types (e.g., List(List(Dec))).
|
||||
fn createTypeFromLayout(self: *Interpreter, lay: layout.Layout) !types.Var {
|
||||
|
|
@ -13797,13 +13838,9 @@ pub const Interpreter = struct {
|
|||
.origin = nom.origin_module,
|
||||
.ident = nom.ident.ident_idx,
|
||||
},
|
||||
else => {
|
||||
return error.InvalidMethodReceiver;
|
||||
},
|
||||
},
|
||||
else => {
|
||||
return error.InvalidMethodReceiver;
|
||||
else => return error.InvalidMethodReceiver,
|
||||
},
|
||||
else => return error.InvalidMethodReceiver,
|
||||
};
|
||||
|
||||
// Resolve the method function
|
||||
|
|
|
|||
|
|
@ -18,40 +18,6 @@ parse_range = |range_str| {
|
|||
}
|
||||
|
||||
|
||||
is_invalid : I64 -> Bool
|
||||
is_invalid = |x| {
|
||||
s = x.to_str().to_utf8()
|
||||
n = s.len()
|
||||
mid = n // 2
|
||||
|
||||
left = s.sublist({ start: 0, len: mid })
|
||||
right = s.sublist({ start: mid, len: n - mid })
|
||||
|
||||
left == right
|
||||
}
|
||||
|
||||
|
||||
part1! : Str => Try(I64, _)
|
||||
part1! = |input| {
|
||||
var $sum = 0
|
||||
|
||||
for range_str in input.trim().split_on(",") {
|
||||
print!(range_str)
|
||||
(start, end) = parse_range(range_str)?
|
||||
|
||||
var $x = start
|
||||
while $x <= end {
|
||||
if is_invalid($x) {
|
||||
$sum = $sum + $x
|
||||
}
|
||||
$x = $x + 1
|
||||
}
|
||||
}
|
||||
|
||||
Ok($sum)
|
||||
}
|
||||
|
||||
|
||||
repeat = |list, n| repeat_helper([], list, n)
|
||||
|
||||
repeat_helper = |acc, list, n| match n {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue