Skip to content

Commit f8967d9

Browse files
committed
merge with master
2 parents c19556f + bbcf192 commit f8967d9

File tree

14 files changed

+573
-142
lines changed

14 files changed

+573
-142
lines changed

bridge_adapters/src/lisp_adapters/collections.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::lisp_adapters::{SlFromRef, SlFromRefMut};
22
use bridge_types::ErrorStrings;
33
use compile_state::state::SloshVm;
4+
use slvm::vm_hashmap::VMHashMap;
45
use slvm::{VMError, VMResult, Value, ValueType};
5-
use std::collections::HashMap;
66

7-
impl<'a> SlFromRef<'a, Value> for &'a HashMap<Value, Value> {
7+
impl<'a> SlFromRef<'a, Value> for &'a VMHashMap {
88
fn sl_from_ref(value: Value, vm: &'a SloshVm) -> VMResult<Self> {
99
match value {
1010
Value::Map(h) => Ok(vm.get_map(h)),
@@ -18,7 +18,7 @@ impl<'a> SlFromRef<'a, Value> for &'a HashMap<Value, Value> {
1818
}
1919
}
2020

21-
impl<'a> SlFromRefMut<'a, Value> for &'a mut HashMap<Value, Value> {
21+
impl<'a> SlFromRefMut<'a, Value> for &'a mut VMHashMap {
2222
fn sl_from_ref_mut(value: Value, vm: &'a mut SloshVm) -> VMResult<Self> {
2323
match value {
2424
Value::Map(h) => Ok(vm.get_map_mut(h)?),

bridge_types/src/lib.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::borrow::Cow;
2-
use std::collections::HashMap;
32
use std::fmt::Display;
43

54
/// Marker traits
@@ -13,14 +12,6 @@ impl<T> BridgedType for Option<T> where T: BridgedType {}
1312
/// A [`Result`] value that contains a [`BridgedType`] can be represented as a rust value.
1413
impl<T, U> BridgedType for Result<T, U> where T: BridgedType {}
1514

16-
/// A [`HashMap`] that contains a [`BridgedType`] can be represented as a rust value.
17-
impl<T, U> BridgedType for HashMap<T, U>
18-
where
19-
T: BridgedType,
20-
U: BridgedType,
21-
{
22-
}
23-
2415
/// A [`Vec`] that contains a [`BridgedType`] can be represented as a rust value.
2516
impl<T> BridgedType for Vec<T> where T: BridgedType {}
2617

builtins/src/collections.rs

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::SloshVm;
22
use bridge_adapters::add_builtin;
33
use bridge_macros::sl_sh_fn;
4+
use slvm::vm_hashmap::{VMHashMap, ValHash};
45
use slvm::{VMError, VMResult, Value, ValueType};
5-
use std::collections::HashMap;
66

77
pub fn vec_slice(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
88
let (vector, start, end) = match registers.len() {
@@ -72,39 +72,26 @@ pub fn vec_to_list(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
7272
}
7373
}
7474

75-
/// Usage: (hash-remove! hashmap key)
76-
///
77-
/// Remove a key from a hashmap. This is a destructive form!
78-
///
79-
/// Section: hashmap
80-
///
81-
/// Example:
82-
/// (def tst-hash {:key1 "val one" 'key2 "val two" "key3" "val three" \S "val S"})
83-
/// (test::assert-equal 4 (len (hash-keys tst-hash)))
84-
/// (test::assert-equal "val one" tst-hash.:key1)
85-
/// (test::assert-equal "val two" (get tst-hash 'key2))
86-
/// (test::assert-equal "val three" (get tst-hash "key3"))
87-
/// (test::assert-equal "val S" (get tst-hash \S))
88-
/// (hash-remove! tst-hash 'key2)
89-
/// (test::assert-equal 3 (len (hash-keys tst-hash)))
90-
/// (test::assert-equal "val one" tst-hash.:key1)
91-
/// (test::assert-equal "val three" (get tst-hash "key3"))
92-
/// (test::assert-equal "val S" (get tst-hash \S))
93-
/// (hash-remove! tst-hash :key1)
94-
/// (test::assert-equal 2 (len (hash-keys tst-hash)))
95-
/// (test::assert-equal "val three" (get tst-hash "key3"))
96-
/// (test::assert-equal "val S" (get tst-hash \S))
97-
/// (hash-remove! tst-hash "key3")
98-
/// (test::assert-equal 1 (len (hash-keys tst-hash)))
99-
/// (test::assert-equal "val S" (get tst-hash \S))
100-
/// (hash-remove! tst-hash \S)
101-
/// (test::assert-equal 0 (len (hash-keys tst-hash)))
102-
#[sl_sh_fn(fn_name = "hash-remove!")]
103-
pub fn hash_remove(map: &mut HashMap<Value, Value>, key: Value) -> VMResult<Value> {
104-
if let Some(old) = map.remove(&key) {
105-
Ok(old)
75+
// This has to be a low level not macro implementation because passing in a &mut VMHashMap means
76+
// we can not use our vm (it has a mutable borrow already out) so we have to play some ordering games
77+
// for the borrow checker and need the raw registers...
78+
// Note, this should probably become a bytecode at some point anyway (?).
79+
pub fn hash_remove(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
80+
let mut args = registers.iter();
81+
if let (Some(Value::Map(map_handle)), Some(key), None) = (args.next(), args.next(), args.next())
82+
{
83+
let id = ValHash::from_value(vm, *key);
84+
let map = vm.get_map_mut(*map_handle)?;
85+
if let Some(old) = map.remove_id(id) {
86+
Ok(old)
87+
} else {
88+
Ok(Value::Nil)
89+
}
10690
} else {
107-
Ok(Value::Nil)
91+
Err(VMError::new(
92+
"hashmap",
93+
"Invalid args, requires hashmap and key to remove.",
94+
))
10895
}
10996
}
11097

@@ -128,9 +115,9 @@ pub fn hash_remove(map: &mut HashMap<Value, Value>, key: Value) -> VMResult<Valu
128115
/// (test::assert-false (hash-haskey tst-hash :key1))
129116
/// (set! tst-hash :key1 "val one b")
130117
/// (test::assert-true (hash-haskey tst-hash :key1))
131-
#[sl_sh_fn(fn_name = "hash-haskey?")]
132-
pub fn hash_hashkey(map: &mut HashMap<Value, Value>, key: Value) -> VMResult<Value> {
133-
if map.contains_key(&key) {
118+
#[sl_sh_fn(fn_name = "hash-haskey?", takes_env = true)]
119+
pub fn hash_hashkey(environment: &mut SloshVm, map: &VMHashMap, key: Value) -> VMResult<Value> {
120+
if map.contains_key(environment, key) {
134121
Ok(Value::True)
135122
} else {
136123
Ok(Value::False)
@@ -232,10 +219,10 @@ pub fn to_list(environment: &mut SloshVm, src: Value) -> VMResult<Value> {
232219
/// (test::assert-true (in? (hash-keys tst-hash) "key3") " Test key3")
233220
/// (test::assert-false (in? (hash-keys tst-hash) :key4))
234221
#[sl_sh_fn(fn_name = "hash-keys")]
235-
pub fn hash_keys(map: &HashMap<Value, Value>) -> VMResult<Vec<Value>> {
222+
pub fn hash_keys(map: &VMHashMap) -> VMResult<Vec<Value>> {
236223
let mut keys = Vec::with_capacity(map.len());
237224
for key in map.keys() {
238-
keys.push(*key);
225+
keys.push(key);
239226
}
240227
Ok(keys)
241228
}
@@ -288,10 +275,43 @@ pub fn setup_collection_builtins(env: &mut SloshVm) {
288275
intern_occurs(env);
289276
intern_reverse(env);
290277
intern_hash_keys(env);
291-
intern_hash_remove(env);
292278
intern_is_in(env);
293279
intern_to_vec(env);
294280
intern_to_list(env);
281+
282+
add_builtin(
283+
env,
284+
"hash-remove!",
285+
hash_remove,
286+
r#"Usage: (hash-remove! hashmap key)
287+
288+
Remove a key from a hashmap. This is a destructive form!
289+
290+
Section: hashmap
291+
292+
Example:
293+
(def tst-hash {:key1 "val one" 'key2 "val two" "key3" "val three" \S "val S"})
294+
(test::assert-equal 4 (len (hash-keys tst-hash)))
295+
(test::assert-equal "val one" tst-hash.:key1)
296+
(test::assert-equal "val two" (get tst-hash 'key2))
297+
(test::assert-equal "val three" (get tst-hash "key3"))
298+
(test::assert-equal "val S" (get tst-hash \S))
299+
(hash-remove! tst-hash 'key2)
300+
(test::assert-equal 3 (len (hash-keys tst-hash)))
301+
(test::assert-equal "val one" tst-hash.:key1)
302+
(test::assert-equal "val three" (get tst-hash "key3"))
303+
(test::assert-equal "val S" (get tst-hash \S))
304+
(hash-remove! tst-hash :key1)
305+
(test::assert-equal 2 (len (hash-keys tst-hash)))
306+
(test::assert-equal "val three" (get tst-hash "key3"))
307+
(test::assert-equal "val S" (get tst-hash \S))
308+
(hash-remove! tst-hash "key3")
309+
(test::assert-equal 1 (len (hash-keys tst-hash)))
310+
(test::assert-equal "val S" (get tst-hash \S))
311+
(hash-remove! tst-hash \S)
312+
(test::assert-equal 0 (len (hash-keys tst-hash)))
313+
"#,
314+
);
295315
add_builtin(
296316
env,
297317
"flatten",

builtins/src/fs_meta.rs

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use compile_state::state::SloshVm;
44
use shell::builtins::expand_tilde;
55
use sl_compiler::load_eval::apply_callable;
66
use slvm::{from_i56, VMError, VMResult, Value};
7-
use std::collections::HashMap;
87
use std::path::{Path, PathBuf};
98
use std::{env, fs, io};
109

1110
use glob::glob;
1211

1312
use bridge_adapters::add_builtin;
1413
use same_file;
14+
use slvm::vm_hashmap::VMHashMap;
1515
use std::fs::{File, Metadata};
1616
use std::time::SystemTime;
1717
use walkdir::{DirEntry, WalkDir};
@@ -354,19 +354,18 @@ fn is_same_file(path_0: &str, path_1: &str) -> VMResult<Value> {
354354
/// (defn create-in (in-dir num-files visited)
355355
/// (dotimes-i i num-files
356356
/// (let (tmp-file (get-temp-file in-dir))
357-
/// (set! visited.~tmp-file nil))))
357+
/// (set! visited.~tmp-file #f))))
358358
///
359359
/// (defn create-dir (tmp-dir visited)
360360
/// (let (new-tmp (get-temp tmp-dir))
361361
/// (set! visited.~new-tmp #f)
362362
/// new-tmp))
363363
///
364-
/// #| XXXX Fix hashmaps so strings and string consts hash the same then restore this testing...
365364
/// (with-temp (fn (root-tmp-dir)
366365
/// (let (tmp-file-count 5
367-
/// visited {})
368-
/// (def cnt 0)
369-
/// (set! visited.~root-tmp-dir nil)
366+
/// visited {}
367+
/// cnt 0)
368+
/// (set! visited.~root-tmp-dir #f)
370369
/// (create-in root-tmp-dir tmp-file-count visited)
371370
/// (let (tmp-dir (create-dir root-tmp-dir visited)
372371
/// new-files (create-in tmp-dir tmp-file-count visited)
@@ -378,47 +377,46 @@ fn is_same_file(path_0: &str, path_1: &str) -> VMResult<Value> {
378377
/// (set! visited.~x #t)
379378
/// (inc! cnt))))
380379
/// (test::assert-equal (+ 3 (* 3 tmp-file-count)) cnt)
381-
/// (test::assert-equal (+ 3 (* 3 tmp-file-count)) (len (hash-keys visited)))
380+
/// (test::assert-equal (+ 3 (* 3 tmp-file-count)) (len visited))
382381
/// (seq-for key in (hash-keys visited) (test::assert-true visited.~key))))))
383382
///
384383
/// (with-temp (fn (root-tmp-dir)
385384
/// (let (tmp-file-count 5
386-
/// visited {})
387-
/// (def cnt 0)
388-
/// (set! visited.~root-tmp-dir nil)
385+
/// visited {}
386+
/// cnt 0)
387+
/// (set! visited.~root-tmp-dir #f)
389388
/// (create-in root-tmp-dir tmp-file-count visited)
390389
/// (let (tmp-dir (create-dir root-tmp-dir visited)
391-
/// new-files (create-in tmp-dir tmp-file-count visited)
392-
/// tmp-dir (create-dir tmp-dir {})
393-
/// new-files (create-in tmp-dir tmp-file-count {}))
390+
/// new-files (create-in tmp-dir tmp-file-count visited)
391+
/// tmp-dir (create-dir tmp-dir {})
392+
/// new-files (do (set! visited.~tmp-dir #f)(create-in tmp-dir tmp-file-count {})))
394393
/// (fs-crawl root-tmp-dir (fn (x)
395394
/// (let (file visited.~x)
396395
/// (test::assert-true (not file)) ;; also tests double counting
397396
/// (set! visited.~x #t)
398397
/// (inc! cnt))) 2)
399398
/// (test::assert-equal (+ 3 (* 2 tmp-file-count)) cnt)
400-
/// (test::assert-equal (+ 3 (* 2 tmp-file-count)) (length (hash-keys visited)))
401-
/// (seq-for key in (hash-keys visited) (test::assert-true visited.~key)))))
399+
/// (test::assert-equal (+ 3 (* 2 tmp-file-count)) (len visited))
400+
/// (seq-for key in (hash-keys visited) (test::assert-true visited.~key))))))
402401
///
403402
/// (with-temp (fn (root-tmp-dir)
404403
/// (let (tmp-file-count 5
405-
/// visited {})
406-
/// (def cnt 0)
407-
/// (set! visited.~root-tmp-dir nil)
404+
/// visited {}
405+
/// cnt 0)
406+
/// (set! visited.~root-tmp-dir #f)
408407
/// (create-in root-tmp-dir tmp-file-count visited)
409408
/// (let (tmp-dir (create-dir root-tmp-dir {})
410-
/// new-files (create-in tmp-dir tmp-file-count {})
411-
/// tmp-dir (create-dir tmp-dir {})
412-
/// new-files (create-in tmp-dir tmp-file-count {}))
409+
/// new-files (do (set! visited.~tmp-dir #f)(create-in tmp-dir tmp-file-count {}))
410+
/// tmp-dir (create-dir tmp-dir {})
411+
/// new-files (create-in tmp-dir tmp-file-count {}))
413412
/// (fs-crawl root-tmp-dir (fn (x)
414413
/// (let (file visited.~x)
415414
/// (test::assert-true (not file)) ;; also tests double counting
416415
/// (set! visited.~x #t)
417416
/// (inc! cnt))) 1)
418417
/// (test::assert-equal (+ 2 tmp-file-count) cnt)
419-
/// (test::assert-equal (+ 2 tmp-file-count) (length (hash-keys visited)))
420-
/// (seq-for key in (hash-keys visited) (test::assert-true visited.~key)))))
421-
/// |#
418+
/// (test::assert-equal (+ 2 tmp-file-count) (len visited))
419+
/// (seq-for key in (hash-keys visited) (test::assert-true visited.~key))))))
422420
#[sl_sh_fn(fn_name = "fs-crawl", takes_env = true)]
423421
fn fs_crawl(
424422
environment: &mut SloshVm,
@@ -619,7 +617,7 @@ fn fs_meta(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
619617
let name = string.pretty_value(vm);
620618
let file = File::open(name)?;
621619
let meta = file.metadata()?;
622-
let mut map = HashMap::new();
620+
let mut map = VMHashMap::new();
623621
let ftype = if meta.is_dir() {
624622
"dir"
625623
} else if meta.is_file() {
@@ -634,15 +632,14 @@ fn fs_meta(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
634632
} else {
635633
Value::False
636634
};
637-
map.insert(Value::Keyword(vm.intern_static("readonly")), ro);
638-
map.insert(
639-
Value::Keyword(vm.intern_static("len")),
640-
(meta.len() as i64).into(),
641-
);
642-
map.insert(
643-
Value::Keyword(vm.intern_static("type")),
644-
Value::Keyword(vm.intern_static(ftype)),
645-
);
635+
let key = Value::Keyword(vm.intern_static("readonly"));
636+
map.insert(vm, key, ro);
637+
let key = Value::Keyword(vm.intern_static("len"));
638+
let val: Value = (meta.len() as i64).into();
639+
map.insert(vm, key, val);
640+
let key = Value::Keyword(vm.intern_static("type"));
641+
let val = Value::Keyword(vm.intern_static(ftype));
642+
map.insert(vm, key, val);
646643
// XXX TODO- include times.
647644
Ok(vm.alloc_map(map))
648645
} else {

builtins/src/rand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,9 @@ Section: random
279279
280280
Example:
281281
(def rand-int (random 100))
282-
(test::assert-true (and (> rand-int 0) (< rand-int 100)))
282+
(test::assert-true (and (>= rand-int 0) (< rand-int 100)))
283283
(def rand-float (random 1.0))
284-
(test::assert-true (and (> rand-float 0) (< rand-float 1)))
284+
(test::assert-true (and (>= rand-float 0.0) (< rand-float 1.0)))
285285
(test::assert-error-msg (random -1) :rand \"Expected positive number\")
286286
(test::assert-error-msg (random 1 2) :rand \"Expected positive number, float or int\")
287287
",

0 commit comments

Comments
 (0)