From 6801f46b19fccd2c411351bca97b395fe2e0e606 Mon Sep 17 00:00:00 2001 From: David Ellis Date: Wed, 31 Jul 2024 16:18:35 -0500 Subject: [PATCH] Implement the `Array` `store` and `delete` functions and the `Buffer` `store` function (#825) --- src/compile/integration_tests.rs | 20 +++++++++++++ src/std/root.ln | 3 ++ src/std/root.rs | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/compile/integration_tests.rs b/src/compile/integration_tests.rs index 6f8fb1c6a..5c0914c48 100644 --- a/src/compile/integration_tests.rs +++ b/src/compile/integration_tests.rs @@ -1918,6 +1918,17 @@ concat test 1, 1, 2, 3, 5, 8, 4, 5, 6 "#; ); +test!(array_store_and_delete => r#" + export fn main { + const test = [ 1, 2, 5 ]; + test.store(2, 3); + test.store(3, 4); + test.print; + test.delete(4).print; + test.print; + }"#; + stdout "[1, 2, 3, 4, 5]\n5\n[1, 2, 3, 4]\n"; +); test!(array_custom_types => r#" type Foo = foo: string, @@ -2004,6 +2015,15 @@ test!(buffer_repeat => r#" }"#; stdout "1, 2, 3, 1, 2, 3, 1, 2, 3\n"; ); +test!(buffer_store => r#" + export fn main { + let buf = {i64[3]}(1, 2, 5); + print(buf); + buf.store(2, 3).print; + print(buf); + }"#; + stdout "[1, 2, 5]\n5\n[1, 2, 3]\n"; +); // Hashing test!(hash => r#" diff --git a/src/std/root.ln b/src/std/root.ln index 5b74c12f0..c81f4635b 100644 --- a/src/std/root.ln +++ b/src/std/root.ln @@ -583,6 +583,8 @@ export fn has{T}(a: Array{T}, f: (T) -> bool) -> bool binds hasfnarray; export fn find{T}(a: Array{T}, f: (T) -> bool) -> Maybe{T} binds findarray; export fn every{T}(a: Array{T}, f: (T) -> bool) -> bool binds everyarray; export fn repeat{T}(a: Array{T}, c: i64) -> Array{T} binds repeatarray; +export fn store{T}(a: Array{T}, i: i64, v: T) -> Fallible{void} binds storearray; +export fn delete{T}(a: Array{T}, i: i64) -> Fallible{T} binds deletearray; /// Buffer related bindings export fn get{T, S}(b: T[S], i: i64) -> Maybe{T} binds getbuffer; @@ -608,6 +610,7 @@ export fn concat{T, S, N}(a: Buffer{T, S}, b: Buffer{T, N}) -> Buffer{T, S + N} // TODO: Be able to resolve explicit integer constant values as the integer type so it can be // grabbed by the type inference system. For now, repeat for buffers outputs an array, instead. export fn repeat{T, S}(b: Buffer{T, S}, c: i64) -> Array{T} binds repeatbuffertoarray; +export fn store{T, S}(b: Buffer{T, S}, i: i64, v: T) -> Fallible{T} binds storebuffer; /// Dictionary-related bindings export fn Dict{K, V}() -> Dict{K, V} binds newdict; diff --git a/src/std/root.rs b/src/std/root.rs index 930a95099..2f4ad34e3 100644 --- a/src/std/root.rs +++ b/src/std/root.rs @@ -2870,6 +2870,38 @@ fn repeatarray(a: &Vec, c: &i64) -> Vec { out } +/// `storearray` inserts a new value at the specified index, but fails if the index is greater than +/// the length of the length of the array (so there would be at least one "gap" in the array in +/// that situation) +#[inline(always)] +fn storearray(a: &mut Vec, i: &i64, v: &T) -> Result<(), AlanError> { + match (*i as usize) > a.len() { + true => Err(format!( + "Provided array index {} is greater than the length of the array", + i + ) + .into()), + false => { + a.insert(*i as usize, v.clone()); + Ok(()) + } + } +} + +/// `deletearray` deletes a value at the specified index, but fails if the index is out-of-bounds. +/// If it succeeds, it returns the value wrapped in a Fallible. +#[inline(always)] +fn deletearray(a: &mut Vec, i: &i64) -> Result { + match (*i as usize) >= a.len() { + true => Err(format!( + "Provided array index {} is beyond the bounds of the array", + i + ) + .into()), + false => Ok(a.remove(*i as usize).clone()), + } +} + /// Buffer-related functions /// `getbuffer` returns the value at the given index presuming it exists @@ -3007,6 +3039,24 @@ fn repeatbuffertoarray(a: &[T; S], c: &i64 out } +/// `storebuffer` stores the provided value in the specified index. If the index is out-of-bounds +/// for the buffer it fails, otherwise it returns the old value. +#[inline(always)] +fn storebuffer( + a: &mut [T; S], + i: &i64, + v: &T, +) -> Result { + match (*i as usize) < a.len() { + false => Err(format!( + "The provided index {} is out-of-bounds for the specified buffer", + i + ) + .into()), + true => Ok(std::mem::replace(a.each_mut()[*i as usize], v.clone())), + } +} + /// Dictionary-related bindings /// `newdict` creates a new dictionary