mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-23 08:48:03 +00:00
Working on implementing List.append in low level interpreter
This commit is contained in:
parent
b5eb58ba3d
commit
882bc163ae
6 changed files with 92 additions and 7 deletions
|
|
@ -130,6 +130,9 @@ fn replaceStrIsEmptyWithLowLevel(env: *ModuleEnv) !std.ArrayList(CIR.Def.Idx) {
|
|||
if (env.common.findIdent("Builtin.List.concat")) |list_concat_ident| {
|
||||
try low_level_map.put(list_concat_ident, .list_concat);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.List.append")) |list_append_ident| {
|
||||
try low_level_map.put(list_append_ident, .list_append);
|
||||
}
|
||||
if (env.common.findIdent("list_get_unsafe")) |list_get_unsafe_ident| {
|
||||
try low_level_map.put(list_get_unsafe_ident, .list_get_unsafe);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ Builtin :: [].{
|
|||
True
|
||||
}
|
||||
|
||||
append : List(a), a -> List(a)
|
||||
|
||||
first : List(item) -> Try(item, [ListWasEmpty])
|
||||
first = |list| List.get(list, 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ const RocOps = @import("host_abi.zig").RocOps;
|
|||
const RocStr = @import("str.zig").RocStr;
|
||||
const increfDataPtrC = utils.increfDataPtrC;
|
||||
|
||||
const Opaque = ?[*]u8;
|
||||
pub const Opaque = ?[*]u8;
|
||||
const EqFn = *const fn (Opaque, Opaque) callconv(.c) bool;
|
||||
const CompareFn = *const fn (Opaque, Opaque, Opaque) callconv(.c) u8;
|
||||
const CopyFn = *const fn (Opaque, Opaque) callconv(.c) void;
|
||||
pub const CopyFn = *const fn (Opaque, Opaque) callconv(.c) void;
|
||||
|
||||
const Inc = *const fn (?*anyopaque, ?[*]u8) callconv(.c) void;
|
||||
const IncN = *const fn (?*anyopaque, ?[*]u8, usize) callconv(.c) void;
|
||||
|
|
@ -531,7 +531,7 @@ pub fn listAppendUnsafe(
|
|||
list: RocList,
|
||||
element: Opaque,
|
||||
element_width: usize,
|
||||
copy: CopyFn,
|
||||
// copy: CopyFn,
|
||||
) callconv(.c) RocList {
|
||||
const old_length = list.len();
|
||||
var output = list;
|
||||
|
|
@ -540,22 +540,23 @@ pub fn listAppendUnsafe(
|
|||
if (output.bytes) |bytes| {
|
||||
if (element) |source| {
|
||||
const target = bytes + old_length * element_width;
|
||||
copy(target, source);
|
||||
@memcpy(target[0..element_width], source[0..element_width]);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
fn listAppend(
|
||||
pub fn listAppend(
|
||||
list: RocList,
|
||||
alignment: u32,
|
||||
element: Opaque,
|
||||
element_width: usize,
|
||||
elements_refcounted: bool,
|
||||
inc_context: ?*anyopaque,
|
||||
inc: Inc,
|
||||
update_mode: UpdateMode,
|
||||
copy: CopyFn,
|
||||
// copy: CopyFn,
|
||||
roc_ops: *RocOps,
|
||||
) callconv(.c) RocList {
|
||||
const with_capacity = listReserve(
|
||||
|
|
@ -564,11 +565,12 @@ fn listAppend(
|
|||
1,
|
||||
element_width,
|
||||
elements_refcounted,
|
||||
inc_context,
|
||||
inc,
|
||||
update_mode,
|
||||
roc_ops,
|
||||
);
|
||||
return listAppendUnsafe(with_capacity, element, element_width, copy);
|
||||
return listAppendUnsafe(with_capacity, element, element_width); // copy
|
||||
}
|
||||
|
||||
/// Directly mutate the given list to push an element onto the end, and then return it.
|
||||
|
|
|
|||
|
|
@ -464,6 +464,7 @@ pub const Expr = union(enum) {
|
|||
list_is_empty,
|
||||
list_get_unsafe,
|
||||
list_concat,
|
||||
list_append,
|
||||
|
||||
// Set operations
|
||||
set_is_empty,
|
||||
|
|
|
|||
|
|
@ -3423,6 +3423,73 @@ pub const Interpreter = struct {
|
|||
out.is_initialized = true;
|
||||
return out;
|
||||
},
|
||||
|
||||
// .list_append => {
|
||||
// // List.append: List(a), a -> List(a)
|
||||
// std.debug.assert(args.len == 2); // low-level .list_get_unsafe expects 2 arguments
|
||||
//
|
||||
// const roc_list_arg = args[0];
|
||||
// const elt_arg = args[1];
|
||||
//
|
||||
// std.debug.assert(roc_list_arg.ptr != null); // low-level .list_get_unsafe expects non-null list pointer
|
||||
//
|
||||
// // Extract element layout from List(a)
|
||||
// std.debug.assert(roc_list_arg.layout.tag == .list or roc_list_arg.layout.tag == .list_of_zst); // low-level .list_get_unsafe expects list layout
|
||||
//
|
||||
// const roc_list: *const builtins.list.RocList = @ptrCast(@alignCast(roc_list_arg.ptr.?));
|
||||
//
|
||||
// // const append_elt: *const builtins.list.Opaque = @ptrCast(@alignCast(elt_arg.ptr.?));
|
||||
//
|
||||
// // Get element layout
|
||||
// const elem_layout_idx = roc_list_arg.layout.data.list;
|
||||
// const elem_layout = self.runtime_layout_store.getLayout(elem_layout_idx);
|
||||
// const elem_size: u32 = self.runtime_layout_store.layoutSize(elem_layout);
|
||||
// const elem_alignment = elem_layout.alignment(self.runtime_layout_store.targetUsize()).toByteUnits();
|
||||
// const elem_alignment_u32: u32 = @intCast(elem_alignment);
|
||||
//
|
||||
// // Determine if elements are refcounted
|
||||
// const elements_refcounted = elem_layout.isRefcounted();
|
||||
//
|
||||
// var temp_ptr: [32]u8 align(@alignOf(u128)) = undefined;
|
||||
//
|
||||
// try elt_arg.copyToPtr(&self.runtime_layout_store, &temp_ptr, roc_ops);
|
||||
//
|
||||
// const append_elt: *const builtins.list.Opaque = @ptrCast(@alignCast(&temp_ptr));
|
||||
//
|
||||
// // Determine if list can be mutated in place
|
||||
// const update_mode = if (roc_list.isUnique()) builtins.utils.UpdateMode.InPlace else builtins.utils.UpdateMode.Immutable;
|
||||
//
|
||||
// // Set up context for refcount callbacks
|
||||
// var refcount_context = RefcountContext{
|
||||
// .layout_store = &self.runtime_layout_store,
|
||||
// .elem_layout = elem_layout,
|
||||
// .roc_ops = roc_ops,
|
||||
// };
|
||||
//
|
||||
// // const sized_copy = struct {
|
||||
// // const item_size = elem_size;
|
||||
// // fn copy_fn(target: builtins.list.Opaque, src: builtins.list.Opaque) callconv(.c) void {
|
||||
// // const target_ptr: [*]u8 = target.?;
|
||||
// // const src_ptr: [*]u8 = src.?;
|
||||
// // @memcpy(target_ptr, src_ptr[0..item_size]);
|
||||
// // }
|
||||
// // };
|
||||
//
|
||||
// const result_list = builtins.list.listAppend(roc_list.*, elem_alignment_u32, append_elt.*, elem_size, elements_refcounted, if (elements_refcounted) @ptrCast(&refcount_context) else null, if (elements_refcounted) &listElementInc else &builtins.list.rcNone, update_mode, roc_ops);
|
||||
//
|
||||
// // Allocate space for the result list
|
||||
// const result_layout = roc_list_arg.layout; // Same layout as input
|
||||
// var out = try self.pushRaw(result_layout, 0);
|
||||
// out.is_initialized = false;
|
||||
//
|
||||
// // Copy the result list structure to the output
|
||||
// const result_ptr: *builtins.list.RocList = @ptrCast(@alignCast(out.ptr.?));
|
||||
// result_ptr.* = result_list;
|
||||
//
|
||||
// out.is_initialized = true;
|
||||
// return out;
|
||||
// // return error.Crash;
|
||||
// },
|
||||
.set_is_empty => {
|
||||
// TODO: implement Set.is_empty
|
||||
self.triggerCrash("Set.is_empty not yet implemented", false, roc_ops);
|
||||
|
|
|
|||
|
|
@ -666,6 +666,16 @@ test "e_low_level_lambda - List.concat with empty string list" {
|
|||
try testing.expectEqual(@as(i128, 3), len_value);
|
||||
}
|
||||
|
||||
test "e_low_level_lambda - List.append on non-empty list" {
|
||||
const src =
|
||||
\\x = List.append([0, 1, 2, 3], 4)
|
||||
\\len = List.len(x)
|
||||
;
|
||||
|
||||
const len_value = try evalModuleAndGetInt(src, 1);
|
||||
try testing.expectEqual(@as(i128, 3), len_value);
|
||||
}
|
||||
|
||||
test "e_low_level_lambda - Dec.to_str returns string representation of decimal" {
|
||||
const src =
|
||||
\\a : Dec
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue