diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-12-30 15:13:28 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-12-30 16:45:41 +0100 |
| commit | f70cea508cd30fa40770ea989fe2a19e715a357b (patch) | |
| tree | 731bb96b375dc8fd0f7e5a2a7e1d1fe5cb2a600e /src/model/methods.rs | |
| parent | fe1f4400693690b68db5a7ec0976ba998624a740 (diff) | |
Remove index syntax in favor of accessor methods
Diffstat (limited to 'src/model/methods.rs')
| -rw-r--r-- | src/model/methods.rs | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src/model/methods.rs b/src/model/methods.rs index dac36be2..8155685c 100644 --- a/src/model/methods.rs +++ b/src/model/methods.rs @@ -1,6 +1,6 @@ //! Methods on values. -use super::{Args, Value, Vm}; +use super::{Args, Str, Value, Vm}; use crate::diag::{At, SourceResult}; use crate::syntax::Span; use crate::util::EcoString; @@ -26,6 +26,9 @@ pub fn call( Value::Str(string) => match method { "len" => Value::Int(string.len() as i64), + "first" => Value::Str(string.first().at(span)?), + "last" => Value::Str(string.last().at(span)?), + "at" => Value::Str(string.at(args.expect("index")?).at(span)?), "slice" => { let start = args.expect("start")?; let mut end = args.eat()?; @@ -65,8 +68,9 @@ pub fn call( Value::Array(array) => match method { "len" => Value::Int(array.len()), - "first" => array.first().cloned().unwrap_or(Value::None), - "last" => array.last().cloned().unwrap_or(Value::None), + "first" => array.first().at(span)?.clone(), + "last" => array.last().at(span)?.clone(), + "at" => array.at(args.expect("index")?).at(span)?.clone(), "slice" => { let start = args.expect("start")?; let mut end = args.eat()?; @@ -82,6 +86,9 @@ pub fn call( .map_or(Value::None, Value::Int), "filter" => Value::Array(array.filter(vm, args.expect("function")?)?), "map" => Value::Array(array.map(vm, args.expect("function")?)?), + "fold" => { + array.fold(vm, args.expect("initial value")?, args.expect("function")?)? + } "any" => Value::Bool(array.any(vm, args.expect("function")?)?), "all" => Value::Bool(array.all(vm, args.expect("function")?)?), "flatten" => Value::Array(array.flatten()), @@ -97,6 +104,7 @@ pub fn call( Value::Dict(dict) => match method { "len" => Value::Int(dict.len()), + "at" => dict.at(&args.expect::<Str>("key")?).cloned().at(span)?, "keys" => Value::Array(dict.keys()), "values" => Value::Array(dict.values()), "pairs" => Value::Array(dict.map(vm, args.expect("function")?)?), @@ -158,11 +166,44 @@ pub fn call_mut( Ok(output) } +/// Call an accessor method on a value. +pub fn call_access<'a>( + value: &'a mut Value, + method: &str, + mut args: Args, + span: Span, +) -> SourceResult<&'a mut Value> { + let name = value.type_name(); + let missing = || Err(missing_method(name, method)).at(span); + + let slot = match value { + Value::Array(array) => match method { + "first" => array.first_mut().at(span)?, + "last" => array.last_mut().at(span)?, + "at" => array.at_mut(args.expect("index")?).at(span)?, + _ => return missing(), + }, + Value::Dict(dict) => match method { + "at" => dict.at_mut(args.expect("index")?), + _ => return missing(), + }, + _ => return missing(), + }; + + args.finish()?; + Ok(slot) +} + /// Whether a specific method is mutating. pub fn is_mutating(method: &str) -> bool { matches!(method, "push" | "pop" | "insert" | "remove") } +/// Whether a specific method is an accessor. +pub fn is_accessor(method: &str) -> bool { + matches!(method, "first" | "last" | "at") +} + /// The missing method error message. #[cold] fn missing_method(type_name: &str, method: &str) -> String { |
