Skip to content

Commit

Permalink
[main] Add avg function, fix empty-generator problem (fixes #140).
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhrr committed Jun 7, 2024
1 parent 03b3d44 commit 62a3c64
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 8 deletions.
3 changes: 3 additions & 0 deletions doc/all.md
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,9 @@ into a hexadecimal string.)
`range` takes an integer and returns a generator over the integers
from zero to that integer, minus one.

`avg` takes a generator and returns the average of the values in that
generator.

`to-function` takes a callable string (e.g. a function name) and
converts it into a function object. Using `funcall` on the function
object will then be quicker than using it on the original string.
Expand Down
19 changes: 19 additions & 0 deletions lib/rt.ch
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,25 @@
then;
.f until; ,,

: avg
gen var; gen !;
0 total var; total !;
0 count var; count !;
begin;
gen @; shift; dup; is-null; if;
drop;
leave;
then;
total @; +; total !;
count @; 1 +; count !;
0 until;
count @; 0 =; if;
0
else;
total @; 0.0 +; count @; /;
then;
,,

: mlist
depth; 1 <; if;
"mlist requires at least one argument" error;
Expand Down
16 changes: 8 additions & 8 deletions src/vm/vm_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,18 +182,18 @@ impl VM {
}
}

/* todo: need a generator-specific run function,
* to avoid the stuffing around here. */
let local_vars_stack = generator_object.local_vars_stack.clone();
let chunk = generator_object.chunk.clone();
let call_stack_chunks = &mut generator_object.call_stack_chunks;
mem::swap(call_stack_chunks, &mut self.call_stack_chunks);

let current_index = index;
if current_index == chunk.borrow().data.len() {
if current_index == generator_object.chunk.borrow().data.len() {
/* At end of function: push null. */
self.stack.push(Value::Null);
} else {
/* todo: need a generator-specific run function,
* to avoid the stuffing around here. */
let local_vars_stack = generator_object.local_vars_stack.clone();
let chunk = generator_object.chunk.clone();
let call_stack_chunks = &mut generator_object.call_stack_chunks;
mem::swap(call_stack_chunks, &mut self.call_stack_chunks);

let plvs_stack = self.local_var_stack.clone();
self.local_var_stack = local_vars_stack;
let backup_chunk = self.chunk.clone();
Expand Down
5 changes: 5 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2213,3 +2213,8 @@ fn hash_literal_test() {
basic_error_test("h(1)", "1:5: expected even number of elements for hash");
basic_error_test("h(h(1 2) 3)", "1:13: expected string for hash key");
}

#[test]
fn avg_test() {
basic_test("10 range; avg", "4.5");
}

0 comments on commit 62a3c64

Please sign in to comment.