Skip to content

Commit 47225d4

Browse files
committed
Merge branch 'milestone/develop_core'
2 parents bc604db + 98c1b60 commit 47225d4

File tree

14 files changed

+339
-19
lines changed

14 files changed

+339
-19
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,4 @@ Session.vim
6363
tags
6464

6565
.idea
66-
6766
Cargo.lock

src/environment.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ impl Environment {
208208
let thread_sleep_fn = clojure_std::thread::SleepFn {};
209209
let nanotime_fn = clojure_std::time::NanoTimeFn {};
210210

211+
let get_fn = rust_core::GetFn {};
212+
let map_fn = rust_core::MapFn {};
213+
211214
// Hardcoded fns
212215
let lexical_eval_fn = Value::LexicalEvalFn {};
213216
// Hardcoded macros
@@ -216,15 +219,17 @@ impl Environment {
216219
let def_macro = Value::DefMacro {};
217220
let fn_macro = Value::FnMacro {};
218221
let defmacro_macro = Value::DefmacroMacro {};
222+
let if_macro = Value::IfMacro {};
219223
let environment = Rc::new(Environment::new_main_environment());
220224

221-
let eval_fn = rust_core::EvalFn::new(Rc::clone(&environment));
222-
let ns_macro = rust_core::NsMacro::new(Rc::clone(&environment));
225+
let eval_fn = rust_core::EvalFn::new(Rc::clone(&environment));
226+
let ns_macro = rust_core::NsMacro::new(Rc::clone(&environment));
227+
let load_file_fn = rust_core::LoadFileFn::new(Rc::clone(&environment));
228+
// @TODO after we merge this with all the other commits we have,
229+
// just change all the `insert`s here to use insert_in_namespace
230+
// I prefer explicity and the non-dependence-on-environmental-factors
231+
environment.change_namespace(Symbol::intern("clojure.core"));
223232

224-
// @TODO after we merge this with all the other commits we have,
225-
// just change all the `insert`s here to use insert_in_namespace
226-
// I prefer explicity and the non-dependence-on-environmental-factors
227-
environment.change_namespace(Symbol::intern("clojure.core"));
228233

229234
environment.insert(Symbol::intern("+"), add_fn.to_rc_value());
230235
environment.insert(Symbol::intern("-"), subtract_fn.to_rc_value());
@@ -258,20 +263,25 @@ impl Environment {
258263
environment.insert(Symbol::intern("+"), add_fn.to_rc_value());
259264
environment.insert(Symbol::intern("let"), let_macro.to_rc_value());
260265
environment.insert(Symbol::intern("str"), str_fn.to_rc_value());
266+
environment.insert(Symbol::intern("map"), map_fn.to_rc_value());
267+
261268
environment.insert(Symbol::intern("quote"), quote_macro.to_rc_value());
262269
environment.insert(Symbol::intern("do-fn*"), do_fn.to_rc_value());
263270
environment.insert(Symbol::intern("do"), do_macro.to_rc_value());
264271
environment.insert(Symbol::intern("def"), def_macro.to_rc_value());
265272
environment.insert(Symbol::intern("fn"), fn_macro.to_rc_value());
273+
environment.insert(Symbol::intern("if"), if_macro.to_rc_value());
266274
environment.insert(Symbol::intern("defmacro"), defmacro_macro.to_rc_value());
267275
environment.insert(Symbol::intern("ns"), ns_macro.to_rc_value());
268276
environment.insert(Symbol::intern("eval"), eval_fn.to_rc_value());
269277
environment.insert(
270278
Symbol::intern("lexical-eval"),
271279
lexical_eval_fn.to_rc_value(),
272280
);
281+
environment.insert(Symbol::intern("load-file"), load_file_fn.to_rc_value());
273282
environment.insert(Symbol::intern("nth"), nth_fn.to_rc_value());
274-
environment.insert(Symbol::intern("assoc"), assoc_fn.to_rc_value());
283+
environment.insert(Symbol::intern("assoc"), assoc_fn.to_rc_value());
284+
environment.insert(Symbol::intern("get"), get_fn.to_rc_value());
275285
environment.insert(Symbol::intern("concat"), concat_fn.to_rc_value());
276286
environment.insert(
277287
Symbol::intern("print-string"),

src/iterable.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use crate::protocol::Protocol;
2+
use crate::value::Value;
3+
use crate::value::ToValue;
4+
use crate::persistent_list_map::PersistentListMapIter;
5+
use crate::persistent_vector::PersistentVectorIter;
6+
use crate::persistent_list::PersistentListIter;
7+
use crate::persistent_list_map::ToPersistentListMapIter;
8+
use crate::persistent_vector::ToPersistentVectorIter;
9+
use crate::persistent_list::ToPersistentListIter;
10+
use crate::persistent_vector::ToPersistentVector;
11+
use std::rc::Rc;
12+
use std::iter::FromIterator;
13+
14+
//
15+
// This Protocol lives inside of Clojure RS
16+
//
17+
#[derive(Debug, Clone)]
18+
pub struct Iterable {
19+
value: Rc<Value>
20+
}
21+
impl Protocol for Iterable {
22+
fn try_as_protocol(val: &Rc<Value>) -> Option<Self> {
23+
match &**val {
24+
Value::PersistentList(_) =>
25+
Some(Iterable { value: Rc::clone(val)}),
26+
Value::PersistentVector(_) =>
27+
Some(Iterable { value: Rc::clone(val)}),
28+
Value::PersistentListMap(_) =>
29+
Some(Iterable { value: Rc::clone(val)}),
30+
_ =>
31+
None
32+
}
33+
}
34+
fn try_unwrap(&self) -> Option<Rc<Value>> {
35+
match &*self.value {
36+
Value::PersistentList(_) => Some(Rc::clone(&self.value)),
37+
Value::PersistentVector(_) => Some(Rc::clone(&self.value)),
38+
Value::PersistentListMap(_) => Some(Rc::clone(&self.value)),
39+
_ => None
40+
}
41+
}
42+
}
43+
pub enum IterableIter {
44+
PersistentList(PersistentListIter),
45+
PersistentVector(PersistentVectorIter),
46+
PersistentListMap(PersistentListMapIter),
47+
}
48+
impl Iterator for IterableIter {
49+
type Item = Rc<Value>;
50+
fn next(&mut self) -> Option<Self::Item> {
51+
match self {
52+
IterableIter::PersistentList(plist_giter) => plist_giter.next(),
53+
IterableIter::PersistentVector(pvector_iter) => pvector_iter.next(),
54+
IterableIter::PersistentListMap(plist_map_iter) => {
55+
let maybe_map_entry = plist_map_iter.next();
56+
if let Some(map_entry) = maybe_map_entry {
57+
// In Clojure: [key val]
58+
return Some(vec![map_entry.key.clone(), map_entry.val.clone()].into_vector().to_rc_value());
59+
}
60+
None
61+
}
62+
}
63+
}
64+
}
65+
impl Iterable {
66+
pub fn iter(&self) -> IterableIter
67+
{
68+
match &*self.value {
69+
Value::PersistentList(plist) => IterableIter::PersistentList(Rc::new(plist.clone()).iter()),
70+
Value::PersistentVector(pvector) => IterableIter::PersistentVector(Rc::new(pvector.clone()).iter()),
71+
Value::PersistentListMap(pmap) => IterableIter::PersistentListMap(Rc::new(pmap.clone()).iter()),
72+
// We are ok panicking in this case because an invariant on the type is the assumption
73+
// that we only have an Iterable if we were able to convert
74+
_ => panic!("Called Iterable iter on non-iterable")
75+
}
76+
77+
}
78+
}

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ mod symbol;
2020
mod type_tag;
2121
mod util;
2222
mod value;
23+
mod protocol;
24+
mod iterable;
2325

2426
fn main() {
2527
//

src/persistent_list_map.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ pub enum PersistentListMap {
3030
// Again, only using strange IBlah convention to reflect the Clojure base
3131
// @TODO really though .. just rethink this
3232
/// A PersistentListMap.
33-
pub trait IPersistentListMap {
33+
pub trait IPersistentMap {
3434
fn get(&self, key: &Rc<Value>) -> Rc<Value>;
3535
fn assoc(&self, key: Rc<Value>, value: Rc<Value>) -> Self;
3636
}
37-
impl IPersistentListMap for PersistentListMap {
37+
impl IPersistentMap for PersistentListMap {
3838
// @TODO make fn of ILookup
3939
fn get(&self, key: &Rc<Value>) -> Rc<Value> {
4040
match self {
@@ -52,7 +52,7 @@ impl IPersistentListMap for PersistentListMap {
5252
}
5353
}
5454

55-
impl IPersistentListMap for Rc<PersistentListMap> {
55+
impl IPersistentMap for Rc<PersistentListMap> {
5656
// @TODO make fn of ILookup
5757
fn get(&self, key: &Rc<Value>) -> Rc<Value> {
5858
match &**self {

src/protocol.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use crate::value::Value;
2+
use std::rc::Rc;
3+
4+
// @TODO should we just exclusively call them protocols as
5+
// we've been doing (deciding that Clojure without the host
6+
// has Protocols as its natural abstraction for interfaces)
7+
// or should interfaces, as an abstraction, exist (and perhaps
8+
// be used by Protocols even?)
9+
/// A type that implements Protocol is one that has a pseudo downcasting of
10+
///
11+
/// value.as::<ISeq>()
12+
///
13+
/// Where ISeq would implement Protocol
14+
///
15+
/// Then you can call functions on this ISeq, if you got one back, to forward
16+
/// functions to the Value inside, and unwrap() it to get your Value back when
17+
/// you're done
18+
pub trait Protocol: Sized {
19+
fn try_as_protocol(val: &Rc<Value>) -> Option<Self>; // where Self:Sized;
20+
/// Panics if your Value isn't an instance of Protocol
21+
fn as_protocol(val: &Rc<Value>) -> Self {
22+
Self::try_as_protocol(val).unwrap()
23+
}
24+
fn try_unwrap(&self) -> Option<Rc<Value>>;
25+
/// Panics if your Value isn't an instance of Protocol
26+
fn unwrap(&self) -> Rc<Value>{
27+
self.try_unwrap().unwrap()
28+
}
29+
}
30+
pub trait ProtocolCastable {
31+
fn try_as_protocol<T: Protocol>(&self) -> Option<T>;
32+
fn as_protocol<T: Protocol>(&self) -> T;
33+
}
34+
impl ProtocolCastable for Rc<Value>{
35+
fn try_as_protocol<T: Protocol>(&self) -> Option<T> {
36+
T::try_as_protocol(self)
37+
}
38+
fn as_protocol<T: Protocol>(&self) -> T {
39+
T::as_protocol(self)
40+
}
41+
}

src/reader.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,18 @@ pub fn try_read_symbol(input: &str) -> IResult<&str, Value> {
341341
to_value_parser(symbol_parser)(input)
342342
}
343343

344+
345+
/// Tries to parse a &str that says 'nil' into Value::Nil
346+
/// Example Successes:
347+
/// nil => Value::Nil
348+
pub fn try_read_nil(input: &str) -> IResult<&str, Value> {
349+
named!(nil<&str, &str>, preceded!(consume_clojure_whitespaces_parser, tag!("nil")));
350+
351+
let (rest_input, _) = nil(input)?;
352+
353+
Ok((rest_input,Value::Nil))
354+
}
355+
344356
// @TODO allow escaped strings
345357
/// Tries to parse &str into Value::String
346358
/// Example Successes:
@@ -454,6 +466,7 @@ pub fn try_read(input: &str) -> IResult<&str, Value> {
454466
consume_clojure_whitespaces_parser,
455467
alt((
456468
try_read_quoted,
469+
try_read_nil,
457470
try_read_map,
458471
try_read_string,
459472
try_read_f64,

src/rust_core.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
use crate::value::Value;
2+
use std::rc::Rc;
3+
4+
use crate::environment::Environment;
5+
use crate::ifn::IFn;
6+
use crate::persistent_list::{
7+
PersistentList,
8+
PersistentList::{Cons, Empty},
9+
ToPersistentList, ToPersistentListIter,
10+
};
11+
use crate::persistent_list_map::IPersistentMap;
12+
use crate::persistent_vector::{PersistentVector, ToPersistentVectorIter};
13+
use crate::symbol::Symbol;
14+
use crate::keyword::Keyword;
15+
use crate::type_tag::TypeTag;
16+
use crate::value::{Evaluable, ToValue};
17+
use crate::repl::Repl;
18+
use crate::error_message;
19+
use crate::util::IsEven;
20+
21+
use itertools::Itertools;
22+
23+
use crate::protocol::ProtocolCastable;
24+
use crate::protocol::Protocol;
25+
use crate::iterable::Iterable;
26+
127
// This module will hold core function and macro primitives that aren't special cases
228
// (like the quote macro, or let), and can't be implemented in clojure itself
329

@@ -42,8 +68,12 @@ pub(crate) mod concat;
4268
pub use self::concat::*;
4369
pub(crate) mod assoc;
4470
pub use self::assoc::*;
71+
pub(crate) mod get;
72+
pub use self::get::*;
73+
pub(crate) mod map;
74+
pub use self::map::*;
4575

46-
// input and output
76+
// input and outputy
4777
pub(crate) mod print_string;
4878
pub use self::print_string::*;
4979
pub(crate) mod string_print;
@@ -52,3 +82,8 @@ pub use self::string_print::*;
5282
// other
5383
pub(crate) mod slurp;
5484
pub use self::slurp::*;
85+
86+
pub(crate) mod load_file;
87+
pub use self::load_file::*;
88+
89+

src/rust_core/_divide_.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl ToValue for DivideFn {
1616
impl IFn for DivideFn {
1717
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
1818
match args.len() {
19-
0 => error_message::wrong_arg_count(1,args.len()),
19+
0 => error_message::zero_arg_count(args.len()),
2020
1 => {
2121
let val = args.get(0).unwrap().to_value();
2222
match val {

src/rust_core/assoc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::value::{Value, ToValue};
33
use std::rc::Rc;
44
use crate::util::IsEven;
55
use itertools::Itertools;
6-
use crate::persistent_list_map::IPersistentListMap;
6+
use crate::persistent_list_map::IPersistentMap;
77

88
/// (assoc map key val & kvs)
99
///

0 commit comments

Comments
 (0)