Skip to content

Commit cd4c050

Browse files
committed
Started a real clojure core, written just in clojure, and now read it
into environment on start
1 parent 0dc1bc2 commit cd4c050

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

src/clojure/core.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(def list (fn [& ls] ls))
2+
3+
(defmacro defn [name args & body]
4+
(list (quote def) name
5+
(list (quote fn) args
6+
(concat (list (quote do)) body))))
7+
8+
(defn apply [f args]
9+
(lexical-eval (concat (list f) args)))
10+
11+
(defn println [& more]
12+
(print-string (apply str more)))

src/main.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod lambda;
1212
mod reader;
1313
mod persistent_list;
1414
mod persistent_vector;
15+
mod repl;
1516

1617
use environment::Environment;
1718

@@ -29,15 +30,25 @@ use crate::persistent_list::{PersistentList,ToPersistentList};
2930
use crate::persistent_vector::{PersistentVector,ToPersistentVector};
3031
use crate::value::Value;
3132

33+
use nom::Err::Incomplete;
34+
use nom::error::convert_error;
35+
use nom::Needed::Size;
36+
37+
3238
fn main()
3339
{
40+
println!("Clojure RS 0.0.1");
41+
3442
// Register our macros / functions ahead of time
3543
let add_fn = rust_core::AddFn{};
3644
let str_fn = rust_core::StrFn{};
3745
let do_fn = rust_core::DoFn{};
3846
let nth_fn = rust_core::NthFn{};
3947
let do_macro = rust_core::DoMacro{};
4048
let concat_fn = rust_core::ConcatFn{};
49+
let print_string_fn = rust_core::PrintStringFn{};
50+
// Hardcoded fns
51+
let lexical_eval_fn = Value::LexicalEvalFn{};
4152
// Hardcoded macros
4253
let let_macro = Value::LetMacro{};
4354
let quote_macro = Value::QuoteMacro{};
@@ -59,24 +70,38 @@ fn main()
5970
environment.insert(Symbol::intern("fn"),fn_macro.to_rc_value());
6071
environment.insert(Symbol::intern("defmacro"),defmacro_macro.to_rc_value());
6172
environment.insert(Symbol::intern("eval"),eval_fn.to_rc_value());
73+
environment.insert(Symbol::intern("lexical-eval"),lexical_eval_fn.to_rc_value());
6274
environment.insert(Symbol::intern("nth"),nth_fn.to_rc_value());
6375
environment.insert(Symbol::intern("concat"),concat_fn.to_rc_value());
76+
environment.insert(Symbol::intern("print-string"),print_string_fn.to_rc_value());
77+
//
78+
// Read in clojure.core
79+
//
80+
repl::try_eval_file(&environment,"./src/clojure/core.clj");
6481
//
6582
// Start repl
6683
//
6784
let stdin = io::stdin();
6885
print!("user=> ");
86+
let mut remaining_input_buffer = String::from("");
6987
for line in stdin.lock().lines() {
7088
let line = line.unwrap();
71-
let mut remaining_input = line.as_bytes();
89+
remaining_input_buffer.push_str(&line);
90+
let mut remaining_input_bytes = remaining_input_buffer.as_bytes();
7291
loop {
73-
let next_read_parse = reader::try_read(remaining_input);
92+
let next_read_parse = reader::try_read(remaining_input_bytes);
7493
match next_read_parse {
75-
Ok((_remaining_input,value)) => {
94+
Ok((_remaining_input_bytes,value)) => {
7695
print!("{} ",value.eval(Rc::clone(&environment)).to_string_explicit());
77-
remaining_input = _remaining_input;
96+
remaining_input_bytes = _remaining_input_bytes;
97+
},
98+
Err(Incomplete(_)) => {
99+
remaining_input_buffer = String::from_utf8(remaining_input_bytes.to_vec()).unwrap();
100+
break;
78101
},
79-
_ => {
102+
err => {
103+
print!("{}",Value::Condition(format!("Reader Error: {:?}",err)));
104+
remaining_input_buffer = String::from("");
80105
break;
81106
}
82107
}

src/repl.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::fs::File;
2+
use std::io::{self,Read};
3+
use std::str::FromStr;
4+
use std::io::BufRead;
5+
use std::io::BufReader;
6+
7+
use crate::reader;
8+
use crate::environment::Environment;
9+
use crate::value::Value;
10+
use crate::value::Evaluable;
11+
use std::rc::Rc;
12+
13+
use nom::Err::Incomplete;
14+
use nom::error::convert_error;
15+
use nom::Needed::Size;
16+
17+
//
18+
// Will possibly just add this to our environment, or turn this into a parallel of clojure.lang.RT
19+
//
20+
21+
pub fn try_eval_file(environment: &Rc<Environment>,filepath: &str) -> Result<(),io::Error>{
22+
let core = File::open(filepath)?;
23+
24+
25+
let reader = BufReader::new(core);
26+
27+
let mut remaining_input_buffer = String::from("");
28+
for line in reader.lines() {
29+
let line = line?;
30+
remaining_input_buffer.push_str(&line);
31+
let mut remaining_input_bytes = remaining_input_buffer.as_bytes();
32+
loop {
33+
let next_read_parse = reader::try_read(remaining_input_bytes);
34+
match next_read_parse {
35+
Ok((_remaining_input,value)) => {
36+
//print!("{} ",value.eval(Rc::clone(&environment)).to_string_explicit());
37+
value.eval(Rc::clone(&environment));
38+
remaining_input_bytes = _remaining_input;
39+
},
40+
Err(Incomplete(Size(1))) => {
41+
remaining_input_buffer = String::from_utf8(remaining_input_bytes.to_vec()).unwrap();
42+
break;
43+
},
44+
err => {
45+
println!("Error evaluating file {}; {}",filepath,Value::Condition(format!("Reader Error: {:?}",err)));
46+
remaining_input_buffer = String::from("");
47+
break;
48+
}
49+
}
50+
}
51+
}
52+
53+
Ok(())
54+
55+
}

src/rust_core.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,23 @@ impl IFn for ConcatFn {
237237
Value::PersistentList(concatted_vec.into_iter().collect::<PersistentList>())
238238
}
239239
}
240+
241+
/// Primitive printing function;
242+
/// (defn print-string [string] .. prints single string .. )
243+
#[derive(Debug,Clone)]
244+
pub struct PrintStringFn {
245+
}
246+
impl ToValue for PrintStringFn {
247+
fn to_value(&self) -> Value {
248+
Value::IFn(Rc::new(self.clone()))
249+
}
250+
}
251+
impl IFn for PrintStringFn {
252+
fn invoke(&self,args: Vec<&Value>) -> Value {
253+
if args.len() != 1 {
254+
return Value::Condition(format!("Wrong number of arguments given to function (Given: {}, Expected: {})",args.len(),args.len()));
255+
}
256+
println!("{}",args.get(0).unwrap().to_string());
257+
Value::Nil
258+
}
259+
}

0 commit comments

Comments
 (0)