Skip to content

Commit 8a0db5b

Browse files
committed
Implemented iobj and imeta protocols, implementd analogous trait
1 parent 59808fa commit 8a0db5b

File tree

7 files changed

+161
-52
lines changed

7 files changed

+161
-52
lines changed

src/protocols.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ pub use self::ifn::*;
66

77
pub(crate) mod imeta;
88
pub use self::imeta::*;
9+
10+
pub(crate) mod iobj;
11+
pub use self::iobj::*;

src/protocols/imeta.rs

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
use crate::keyword::Keyword;
22
use crate::maps::MapEntry;
3-
use crate::persistent_list::PersistentListIter;
4-
use crate::persistent_list::ToPersistentListIter;
5-
use crate::persistent_list_map::ToPersistentListMapIter;
6-
use crate::persistent_list_map::{PersistentListMap, PersistentListMapIter};
7-
use crate::persistent_vector::PersistentVectorIter;
8-
use crate::persistent_vector::ToPersistentVector;
9-
use crate::persistent_vector::ToPersistentVectorIter;
10-
use crate::protocol::Protocol;
3+
use crate::persistent_list_map::{PersistentListMap};
114
use crate::define_protocol;
5+
use crate::traits;
126
use crate::symbol::Symbol;
137
use crate::value::ToValue;
148
use crate::value::Value;
@@ -17,54 +11,32 @@ use std::rc::Rc;
1711
define_protocol!(
1812
IMeta = PersistentList |
1913
PersistentVector |
20-
PersistentList |
2114
PersistentListMap |
22-
Symbol |
23-
IFn
15+
Symbol // |
16+
// IFn
2417
);
25-
26-
/// Syntactic sugar, DRY
27-
/// map_entry!("doc", "this is a docstring");
28-
#[macro_export]
29-
macro_rules! map_entry {
30-
($key:expr, $value:expr) => {{
31-
MapEntry {
32-
key: Keyword::intern($key).to_rc_value(),
33-
val: $value.to_rc_value(),
34-
}
35-
}};
36-
}
37-
38-
/// Syntactic sugar, DRY
39-
/// persistent_list_map!(map_entry!("key1", "value1"), map_entry!("key2", "value2"));
40-
#[macro_export]
41-
macro_rules! persistent_list_map {}
42-
( $($kv:expr), *) => {
43-
{
44-
let mut temp_vec = Vec::new();
45-
$(
46-
temp_vec.push($kv);
47-
)*
48-
temp_vec.into_iter().collect::<PersistentListMap>()
49-
}
50-
};
51-
}
52-
53-
/// Syntactic sugar, DRY
54-
/// merge!(base_meta(name, ns), map_entry!("key1", "value1"), map_entry!("key2", "value2"));
55-
#[macro_export]
56-
macro_rules! merge {
57-
( $plistmap:expr, $($kv:expr), *) => {
58-
{
59-
let mut temp_plistmap_as_vec = $plistmap.clone().iter().collect::<Vec<MapEntry>>();
60-
$(
61-
temp_plistmap_as_vec.push($kv);
62-
)*
63-
temp_plistmap_as_vec.into_iter().collect::<PersistentListMap>()
18+
impl traits::IMeta for IMeta {
19+
fn meta(&self) -> PersistentListMap {
20+
match &*self.value {
21+
Value::PersistentList(val) => {
22+
val.meta()
23+
}
24+
Value::PersistentVector(val) => {
25+
val.meta()
26+
}
27+
Value::PersistentListMap(val) => {
28+
val.meta()
29+
}
30+
Value::Symbol(val) => {
31+
val.meta()
32+
}
33+
_ => panic!("protocols::IMeta was wrapping an invalid type {} when calling meta()",self.value.type_tag())
34+
// Value::IFn(val) => {
35+
// val.with_meta(meta)
36+
// }
6437
}
65-
};
38+
}
6639
}
67-
6840
/// Constructs base meta if none provided
6941
/// {:line 1
7042
/// :column 1
@@ -81,3 +53,6 @@ pub fn base_meta(ns: &str, name: &str) -> PersistentListMap {
8153
map_entry!("name", Symbol::intern(name))
8254
)
8355
}
56+
57+
mod tests {
58+
}

src/protocols/iobj.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use crate::persistent_list_map::{PersistentListMap};
2+
use crate::protocol::ProtocolCastable;
3+
use crate::define_protocol;
4+
use crate::value::{Value,ToValue};
5+
use crate::traits;
6+
use std::rc::Rc;
7+
// TODO allow nullable protocols
8+
define_protocol!(
9+
IObj = PersistentList |
10+
PersistentVector |
11+
PersistentListMap |
12+
Symbol // |
13+
// IFn
14+
);
15+
impl traits::IMeta for IObj {
16+
fn meta(&self) -> PersistentListMap {
17+
match &*self.value {
18+
Value::PersistentList(val) => {
19+
val.meta()
20+
}
21+
Value::PersistentVector(val) => {
22+
val.meta()
23+
}
24+
Value::PersistentListMap(val) => {
25+
val.meta()
26+
}
27+
Value::Symbol(val) => {
28+
val.meta()
29+
}
30+
_ => {
31+
panic!("protocols::IMeta was wrapping an invalid type {} when calling meta()",self.value.type_tag())
32+
//PersistentListMap::Empty
33+
}
34+
// Value::IFn(val) => {
35+
// val.with_meta(meta)
36+
// }
37+
}
38+
}
39+
}
40+
impl traits::IObj for IObj {
41+
fn with_meta(&self,meta: PersistentListMap) -> IObj {
42+
match &*self.value {
43+
Value::PersistentList(val) => {
44+
val.with_meta(meta).to_rc_value().as_protocol::<IObj>()
45+
}
46+
Value::PersistentVector(val) => {
47+
val.with_meta(meta).to_rc_value().as_protocol::<IObj>()
48+
}
49+
Value::PersistentListMap(val) => {
50+
val.with_meta(meta).to_rc_value().as_protocol::<IObj>()
51+
}
52+
Value::Symbol(val) => {
53+
val.with_meta(meta).to_rc_value().as_protocol::<IObj>()
54+
}
55+
_ => {
56+
panic!("protocols::IMeta was wrapping an invalid type {} when calling meta()",self.value.type_tag())
57+
}
58+
// Value::IFn(val) => {
59+
// val.with_meta(meta)
60+
// }
61+
}
62+
}
63+
}
64+
mod tests {
65+
}

src/traits.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pub(crate) mod iobj;
2+
pub use self::iobj::*;
3+
4+
pub(crate) mod ifn;
5+
pub use self::ifn::*;
6+
7+
pub(crate) mod imeta;
8+
pub use self::imeta::*;

src/traits/ifn.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//! Trait for function-like things
2+
//!
3+
//! An IFn is something that can be invoked on arguments, like:
4+
//! a function,
5+
//! (+ 1 2)
6+
//! a macro
7+
//! (-> 1 (+ 5) (* 10)))
8+
//! a keyword
9+
//! (:name {:name "Blah" :age 20})
10+
//! a map
11+
//! ({:name "Blah" :age 20} :name)
12+
//! As well as a few more types.
13+
use crate::value::Value;
14+
15+
use dyn_clone::DynClone;
16+
17+
use std::fmt::Debug;
18+
use std::rc::Rc;
19+
20+
//
21+
// Based on: clojure.lang.IFn
22+
//
23+
// Naming this is a bit difficult, as
24+
// 1. Rust already has a Fn trait
25+
// 2. Naming this IFn or not naming this IFn introduces consistency and inconsistency;
26+
//
27+
// Keeping 'IFn' introduces consistency because not just does the
28+
// original ClojureJVM have an IFn in the Java underneath, but
29+
// Clojure itself carries on this idea even as we leave the JVM (as,
30+
// for instance, ifn is implemented in Clojurescript via)
31+
//
32+
// Inconsistency, because Rust surely does not name traits 'ITrait'.
33+
//
34+
// I've regardless kept it as IFn, and you might say IFn here is
35+
// referring to the Clojure idea of an IFn, implemented in Rust with a
36+
// trait, rather than saying 'this is an interface called Fn'
37+
//
38+
39+
pub trait IFn: Debug + DynClone {
40+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value;
41+
}
42+
dyn_clone::clone_trait_object!(IFn);

src/traits/imeta.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use std::fmt::Debug;
2+
use crate::persistent_list_map::PersistentListMap;
3+
4+
pub trait IMeta: Debug {
5+
fn meta(&self) -> PersistentListMap;
6+
}

src/traits/iobj.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::traits::imeta::IMeta;
2+
use std::fmt::Debug;
3+
use crate::persistent_list_map::PersistentListMap;
4+
5+
// @TODO start swapping PersistentListMap signatures for protocol::IPersistentMap or
6+
// with_meta<I: traits::IPersistentMap>(meta: I)
7+
8+
pub trait IObj: IMeta + Debug {
9+
fn with_meta(&self,meta: PersistentListMap) -> Self;
10+
}

0 commit comments

Comments
 (0)