diff --git a/assets/test_prelude.ld b/assets/test_prelude.ld index 0d7ceae..e788a59 100644 --- a/assets/test_prelude.ld +++ b/assets/test_prelude.ld @@ -859,52 +859,14 @@ fn butlast { } fn indices_of { - "Takes a list or string and returns a list of all the indices where the scrutinee appears. Returns an empty list if the scrutinee does not appear in the search target." - (target as :list, scrutinee) -> { - fn searcher ((i, indices), curr) -> if eq? (scrutinee, curr) - then (inc (i), append (indices, i)) - else (inc (i), indices) - let (_, idxes) = fold (searcher, target, (0, [])) - idxes - } - & (target as :string, scrutinee as :string) -> { - & let scrut_len = count (scrutinee) - & fn searcher ((i, indices), curr) -> { - & let srch_substr = slice_n (remaining, scrut_len) - & if eq? (scrutinee, srch_substr) - & then (inc (i), append (indices, i)) - & else (inc (i), indices) - & } - & let (_, idxes) = fold (searcher, target, (0, [])) - & idxes - & } + "Takes a list or string and returns a list of all the indices where the target appears. Returns an empty list if the target does not appear in the scrutinee." + (scrutinee as :list, target) -> base :indices_of (scrutinee, target) } fn index_of { "Takes a list or string returns the first index at which the scrutinee appears. Returns `nil` if the scrutinee does not appear in the search target." - (target as :list, scrutinee) -> first (indices_of (target, scrutinee)) - (target as :string, scrutinee as :string) -> first (indices_of (target, scrutinee)) + (scrutinee as :list, target) -> base :index_of (scrutinee, target) } -& (target as :list, scrutinee) -> loop (0) with { -& (i) if gte? (i, count (target)) -> nil -& (i) -> if eq? (scrutinee, at (target, i)) -& then i -& else recur (inc (i)) -& } -& (target as :string, scrutinee as :string) -> { -& let scrut_len = count (scrutinee) -& loop (0, target) with { -& (i, "") -> nil -& (i, remaining) -> { -& let srch_substr = slice_n (remaining, scrut_len) -& if eq? (scrutinee, srch_substr) -& then i -& else recur (inc (i), rest (remaining)) -& } -& } -& } -& } - &&& keywords: funny names fn keyword? { diff --git a/pkg/rudus.d.ts b/pkg/rudus.d.ts index bb38565..86c1521 100644 --- a/pkg/rudus.d.ts +++ b/pkg/rudus.d.ts @@ -14,8 +14,8 @@ export interface InitOutput { readonly __wbindgen_malloc: (a: number, b: number) => number; readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_export_6: WebAssembly.Table; - readonly closure359_externref_shim: (a: number, b: number, c: any) => void; - readonly closure382_externref_shim: (a: number, b: number, c: any, d: any) => void; + readonly closure361_externref_shim: (a: number, b: number, c: any) => void; + readonly closure384_externref_shim: (a: number, b: number, c: any, d: any) => void; readonly __wbindgen_start: () => void; } diff --git a/pkg/rudus.js b/pkg/rudus.js index d045a63..2e86394 100644 --- a/pkg/rudus.js +++ b/pkg/rudus.js @@ -240,13 +240,13 @@ function _assertNum(n) { function __wbg_adapter_20(arg0, arg1, arg2) { _assertNum(arg0); _assertNum(arg1); - wasm.closure359_externref_shim(arg0, arg1, arg2); + wasm.closure361_externref_shim(arg0, arg1, arg2); } function __wbg_adapter_46(arg0, arg1, arg2, arg3) { _assertNum(arg0); _assertNum(arg1); - wasm.closure382_externref_shim(arg0, arg1, arg2, arg3); + wasm.closure384_externref_shim(arg0, arg1, arg2, arg3); } async function __wbg_load(module, imports) { @@ -403,8 +403,8 @@ function __wbg_get_imports() { _assertBoolean(ret); return ret; }; - imports.wbg.__wbindgen_closure_wrapper8162 = function() { return logError(function (arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 360, __wbg_adapter_20); + imports.wbg.__wbindgen_closure_wrapper8168 = function() { return logError(function (arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 362, __wbg_adapter_20); return ret; }, arguments) }; imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { diff --git a/pkg/rudus_bg.wasm b/pkg/rudus_bg.wasm index f1317c2..0e5af42 100644 Binary files a/pkg/rudus_bg.wasm and b/pkg/rudus_bg.wasm differ diff --git a/pkg/rudus_bg.wasm.d.ts b/pkg/rudus_bg.wasm.d.ts index af356e0..e654bfa 100644 --- a/pkg/rudus_bg.wasm.d.ts +++ b/pkg/rudus_bg.wasm.d.ts @@ -9,6 +9,6 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void; export const __wbindgen_malloc: (a: number, b: number) => number; export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_export_6: WebAssembly.Table; -export const closure359_externref_shim: (a: number, b: number, c: any) => void; -export const closure382_externref_shim: (a: number, b: number, c: any, d: any) => void; +export const closure361_externref_shim: (a: number, b: number, c: any) => void; +export const closure384_externref_shim: (a: number, b: number, c: any, d: any) => void; export const __wbindgen_start: () => void; diff --git a/src/base.rs b/src/base.rs index c541058..55d2f91 100644 --- a/src/base.rs +++ b/src/base.rs @@ -123,6 +123,27 @@ pub fn words(str: &Value) -> Value { Value::list(words) } +pub fn index_of(scrutinee: &Value, target: &Value) -> Value { + let scrutinee = scrutinee.as_list(); + for (i, value) in scrutinee.iter().enumerate() { + if value == target { + return Value::from_usize(i); + } + } + Value::Nil +} + +pub fn indices_of(scrutinee: &Value, target: &Value) -> Value { + let scrutinee = scrutinee.as_list(); + let mut indices = Vector::new(); + for (i, value) in scrutinee.iter().enumerate() { + if value == target { + indices.push_back(Value::from_usize(i)) + } + } + Value::list(indices) +} + // TODO: figure out how to get to opportunistic mutation here pub fn concat(x: &Value, y: &Value) -> Value { match (x, y) { @@ -662,6 +683,14 @@ pub fn make_base() -> Value { ("gt?", Value::BaseFn(Box::new(BaseFn::Binary("gt?", gt)))), ("gte?", Value::BaseFn(Box::new(BaseFn::Binary("gte?", gte)))), ("inc", Value::BaseFn(Box::new(BaseFn::Unary("inc", inc)))), + ( + "index_of", + Value::BaseFn(Box::new(BaseFn::Binary("index_of", index_of))), + ), + ( + "indices_of", + Value::BaseFn(Box::new(BaseFn::Binary("indices_of", indices_of))), + ), ("last", Value::BaseFn(Box::new(BaseFn::Unary("last", last)))), ("list", Value::BaseFn(Box::new(BaseFn::Unary("list", list)))), ("lt?", Value::BaseFn(Box::new(BaseFn::Binary("lt?", lt)))),