Skip to content

Commit ec1c869

Browse files
committed
feat: Improving dict iteration & access
- `dict_get_item()` doesn't fallback to index access - `dict_values()` for index access and iteration - `dict_keys()` and `dict_items()` with default value parameter - `dict_iter()` to iterate over items - Updated test cases
1 parent 9519ef0 commit ec1c869

File tree

3 files changed

+93
-17
lines changed

3 files changed

+93
-17
lines changed

src/_builtins.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use crate::builtin::Builtin;
77

88
/*GENERATE cargo run -- _builtins.tok -- `find . -name "*.rs"` */
9-
pub static BUILTINS: [Builtin; 67] = [
9+
pub static BUILTINS: [Builtin; 69] = [
1010
Builtin {
1111
name: "Float",
1212
func: crate::value::token::tokay_token_float,
@@ -63,6 +63,10 @@ pub static BUILTINS: [Builtin; 67] = [
6363
name: "dict_items",
6464
func: crate::value::dict::Dict::tokay_method_dict_items,
6565
},
66+
Builtin {
67+
name: "dict_iter",
68+
func: crate::value::dict::Dict::tokay_method_dict_iter,
69+
},
6670
Builtin {
6771
name: "dict_keys",
6872
func: crate::value::dict::Dict::tokay_method_dict_keys,
@@ -87,6 +91,10 @@ pub static BUILTINS: [Builtin; 67] = [
8791
name: "dict_set_item",
8892
func: crate::value::dict::Dict::tokay_method_dict_set_item,
8993
},
94+
Builtin {
95+
name: "dict_values",
96+
func: crate::value::dict::Dict::tokay_method_dict_values,
97+
},
9098
Builtin {
9199
name: "eof",
92100
func: crate::builtin::tokay_function_eof,

src/value/dict.rs

+54-16
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//! Dictionary object
2-
use super::{BoxedObject, MethodIter, Object, RefValue, Str, Value};
2+
use super::{BoxedObject, MethodIter, Object, RefValue, Str};
33
use crate::value;
44
use crate::Error;
55
use indexmap::IndexMap;
66
use tokay_macros::tokay_method;
77
extern crate self as tokay;
8-
use num::ToPrimitive;
98
use std::cmp::Ordering;
109

1110
// Alias for the inner dict
@@ -103,6 +102,25 @@ impl Dict {
103102

104103
tokay_method!("dict : @", Ok(RefValue::from(Dict::new())));
105104

105+
tokay_method!("dict_iter : @dict", {
106+
// If index is void, create an iterator on keys.
107+
if dict.is("dict") {
108+
Ok(RefValue::from(MethodIter::new_method_iter(
109+
dict.clone(),
110+
"values",
111+
None,
112+
"iinc",
113+
)))
114+
} else {
115+
Err(Error::from(format!(
116+
"{} only accepts '{}' as parameter, not '{}'",
117+
__function,
118+
"dict",
119+
dict.name()
120+
)))
121+
}
122+
});
123+
106124
tokay_method!("dict_len : @dict", {
107125
let dict = dict.borrow();
108126

@@ -134,7 +152,7 @@ impl Dict {
134152
});
135153

136154
// Method to retrieve or iterate the keys of a dict.
137-
tokay_method!("dict_keys : @dict, index=void", {
155+
tokay_method!("dict_keys : @dict, index=void, default=void", {
138156
// If index is void, create an iterator on keys.
139157
if index.is_void() {
140158
return Ok(RefValue::from(MethodIter::new_method_iter(
@@ -151,7 +169,37 @@ impl Dict {
151169
if let Some((key, _)) = dict.get_index(index.to_usize()?) {
152170
Ok(key.clone())
153171
} else {
154-
Ok(value!(void))
172+
Ok(default)
173+
}
174+
} else {
175+
Err(Error::from(format!(
176+
"{} only accepts '{}' as parameter, not '{}'",
177+
__function,
178+
"dict",
179+
dict.name()
180+
)))
181+
}
182+
});
183+
184+
// Method to retrieve or iterate the values of a dict.
185+
tokay_method!("dict_values : @dict, index=void, default=void", {
186+
// If index is void, create an iterator on keys.
187+
if index.is_void() {
188+
return Ok(RefValue::from(MethodIter::new_method_iter(
189+
dict.clone(),
190+
"values",
191+
None,
192+
"iinc",
193+
)));
194+
}
195+
196+
// Otherwise, borrow
197+
let dict = dict.borrow();
198+
if let Some(dict) = dict.object::<Dict>() {
199+
if let Some((_, value)) = dict.get_index(index.to_usize()?) {
200+
Ok(value.clone())
201+
} else {
202+
Ok(default)
155203
}
156204
} else {
157205
Err(Error::from(format!(
@@ -164,7 +212,7 @@ impl Dict {
164212
});
165213

166214
// Method to retrieve or iterate a list of [key, value] from a dict by index
167-
tokay_method!("dict_items : @dict, index=void", {
215+
tokay_method!("dict_items : @dict, index=void, default=void", {
168216
// If index is void, create an iterator on items.
169217
if index.is_void() {
170218
return Ok(RefValue::from(MethodIter::new_method_iter(
@@ -181,7 +229,7 @@ impl Dict {
181229
if let Some((key, value)) = dict.get_index(index.to_usize()?) {
182230
Ok(value!([(key.clone()), (value.clone())]))
183231
} else {
184-
Ok(value!(void))
232+
Ok(default)
185233
}
186234
} else {
187235
Err(Error::from(format!(
@@ -209,16 +257,6 @@ impl Dict {
209257
if let Some(item) = dict.get(&item) {
210258
Ok(item.clone())
211259
} else {
212-
// In case index is an int that can be turned into an usize,
213-
// try to obtain the dict item by its index
214-
if let Value::Int(index) = &*item.borrow() {
215-
if let Some(index) = index.to_usize() {
216-
if let Some((_, item)) = dict.get_index(index) {
217-
return Ok(item.clone());
218-
}
219-
}
220-
}
221-
222260
Ok(default)
223261
}
224262
} else {

tests/dict.tok

+30
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,23 @@ d.len()
8484
dict_len("Donkey") # invalid
8585

8686
list(iter(d))
87+
list(d.values)
88+
d.values(0)
89+
d.values(1)
90+
type(d.values(2))
91+
d.values(2, default="Esel")
92+
8793
list(d.keys)
94+
d.keys(0)
95+
d.keys(1)
96+
type(d.keys(2))
97+
d.keys(2, default="Esel")
98+
8899
list(d.items)
100+
d.items(0)
101+
d.items(1)
102+
type(d.items(2))
103+
d.items(2, default="Esel")
89104

90105
# clone
91106

@@ -162,8 +177,23 @@ d
162177
#ERR:Line 1, column 1: dict_len() only accepts 'dict' as parameter, not 'str'
163178

164179
#(1, 2)
180+
#(1, 2)
181+
#1
182+
#2
183+
#"void"
184+
#"Esel"
185+
165186
#("a", "b")
187+
#"a"
188+
#"b"
189+
#"void"
190+
#"Esel"
191+
166192
#(("a", 1), ("b", 2))
193+
#("a", 1)
194+
#("b", 2)
195+
#"void"
196+
#"Esel"
167197

168198
#(a => 1 b => 2)
169199
#(a => 1 b => 2 c => 3)

0 commit comments

Comments
 (0)