Skip to content

Commit d3ebdc5

Browse files
authored
feat: min(), max(), sum() and avg() (#145)
* feat: `min()`, `max(), `sum()` and `avg()` - Globals `min()`, `max(), `sum()` and `avg()` implemented as preludes - Internal `iter_min()` and `iter_max()` * Docstrings and some bugfixing - iter(void) should really return an iter with void, not void - avoid divison by zero in avg * Added tests and fixed some issues * Added more tests and fixed Int+=Float bug
1 parent 815b1d3 commit d3ebdc5

File tree

7 files changed

+683
-5
lines changed

7 files changed

+683
-5
lines changed

CONTRIBUTING.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ This section contains some useful information for Tokay maintenance.
3939
This repository holds all required source files to provide Tokay with examples.
4040

4141
```
42-
. # Build scripts, Cargo.toml, etc.
42+
. # Cargo.toml, README.md, LICENSE, etc.
43+
├── build # Build scripts to generate parts of Tokay using Tokay itself
4344
├── examples # Example programs
4445
├── macros # Source of the tokay-macros crate required for building
4546
├── src # Tokay's source code
4647
│ ├── compiler # Compiler source
4748
│ ├── value # Object system source
4849
│ └── vm # Virtual machine source
49-
└── tests # Some use-case examples required by the test suite
50+
└── tests # Part of the test suite with plenty of Tokay test cases
5051
```
5152

5253
## Releasing a version

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; 65] = [
9+
pub static BUILTINS: [Builtin; 67] = [
1010
Builtin {
1111
name: "Float",
1212
func: crate::value::token::tokay_token_float,
@@ -135,6 +135,14 @@ pub static BUILTINS: [Builtin; 65] = [
135135
name: "iter_map",
136136
func: crate::value::iter::mapiter::MapIter::tokay_method_iter_map,
137137
},
138+
Builtin {
139+
name: "iter_max",
140+
func: crate::value::iter::iter::Iter::tokay_method_iter_max,
141+
},
142+
Builtin {
143+
name: "iter_min",
144+
func: crate::value::iter::iter::Iter::tokay_method_iter_min,
145+
},
138146
Builtin {
139147
name: "iter_next",
140148
func: crate::value::iter::iter::Iter::tokay_method_iter_next,

src/compiler/prelude.rs

+517
Large diffs are not rendered by default.

src/prelude.tok

+56
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,59 @@ Number : Float | Int
9898

9999
# Parse any token, which is just no whitespace in default terms.
100100
Token : AsciiPunctuation | Word | Number
101+
102+
# Functions
103+
104+
# Calculates the maximum of a value.
105+
#
106+
# In case the provided value is not an iterator,
107+
# it will be turned into an iterator with just
108+
# its own value.
109+
max : @value {
110+
iter(value).max
111+
}
112+
113+
# Calculates the minimum of a value.
114+
#
115+
# In case the provided value is not an iterator,
116+
# it will be turned into an iterator with just
117+
# its own value.
118+
min : @value {
119+
iter(value).min
120+
}
121+
122+
# Calculates the sum of a value.
123+
#
124+
# In case the provided value is not an iterator,
125+
# it will be turned into an iterator with just
126+
# its own value.
127+
sum : @value {
128+
res = void
129+
130+
for i in value {
131+
res += i
132+
}
133+
134+
res
135+
}
136+
137+
# Calculates the average of a value.
138+
#
139+
# In case the provided value is not an iterator,
140+
# it will be turned into an iterator with just
141+
# its own value.
142+
avg : @value {
143+
res = void
144+
cnt = 0
145+
146+
for i in value {
147+
res += i
148+
cnt++
149+
}
150+
151+
# TODO: Facilities for type checking divisable types must be improved!
152+
if !cnt || (type(res) != "int" && type(res) != "float" && type(res) != "bool" && type(res) != "null")
153+
return void
154+
155+
res / cnt
156+
}

src/value/iter/iter.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl Iter {
4949

5050
tokay_method!("iter : @value", {
5151
// If parameter is already an iterator, just return it
52-
if value.is("iter") || value.is_void() {
52+
if value.is("iter") {
5353
Ok(value)
5454
}
5555
// Check for an available iter() method on the provided value first
@@ -93,6 +93,26 @@ impl Iter {
9393
))
9494
});
9595

96+
tokay_method!("iter_max : @iter", {
97+
let mut borrowed_iter = iter.borrow_mut();
98+
99+
if let Some(iter) = borrowed_iter.object_mut::<Iter>() {
100+
Ok(iter.max().unwrap_or(RefValue::from(Value::Void)))
101+
} else {
102+
Ok(iter.clone())
103+
}
104+
});
105+
106+
tokay_method!("iter_min : @iter", {
107+
let mut borrowed_iter = iter.borrow_mut();
108+
109+
if let Some(iter) = borrowed_iter.object_mut::<Iter>() {
110+
Ok(iter.min().unwrap_or(RefValue::from(Value::Void)))
111+
} else {
112+
Ok(iter.clone())
113+
}
114+
});
115+
96116
tokay_method!("iter_rev : @iter", {
97117
{
98118
let mut iter = iter.borrow_mut();

src/value/refvalue.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl RefValue {
144144
},
145145

146146
// Int inline fast-lane
147-
(Value::Int(int), _) => match op {
147+
(Value::Int(int), no_float) if !no_float.is("float") => match op {
148148
"iadd" => {
149149
*int += that.to_i64()?;
150150
return Ok(self.clone());

tests/aggregates.tok

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#testmode:repl
2+
# Aggregate Functions
3+
4+
# aggregate with list of integers
5+
l = list(range(10))
6+
7+
min(l)
8+
max(l)
9+
sum(l)
10+
avg(l)
11+
12+
# aggregate with list of mixed float/int
13+
l = 1, 23.5, 42, 3.1415
14+
15+
min(l)
16+
max(l)
17+
sum(l)
18+
avg(l)
19+
20+
# aggregate with single value
21+
min(42)
22+
max(42)
23+
sum(42)
24+
avg(42)
25+
26+
# aggregate with void
27+
print(type(min(void)))
28+
print(type(max(void)))
29+
print(type(sum(void)))
30+
print(type(avg(void)))
31+
32+
# special cases
33+
34+
## aggregate str
35+
36+
s = "Hello"
37+
min(s)
38+
max(s)
39+
sum(s)
40+
print(type(avg(s))) # should be void
41+
42+
## aggrgate list of list, or mixed
43+
sum(((1,2),3))
44+
sum((1,(2,3)))
45+
sum(((1,2),(3,4)))
46+
47+
#---
48+
49+
#0
50+
#9
51+
#45
52+
#4.5
53+
54+
#1
55+
#42
56+
#69.6415
57+
#17.410375
58+
59+
#42
60+
#42
61+
#42
62+
#42
63+
64+
#void
65+
#void
66+
#void
67+
#void
68+
69+
#"H"
70+
#"o"
71+
#"Hello"
72+
#void
73+
74+
#(1, 2, 3)
75+
#(1, 2, 3)
76+
#(1, 2, 3, 4)

0 commit comments

Comments
 (0)