Skip to content

Commit e2c860d

Browse files
committed
refactoring, functions new-line, pr, prn, print, println, flush, getenv
1 parent eab3a5f commit e2c860d

File tree

9 files changed

+143
-43
lines changed

9 files changed

+143
-43
lines changed

src/clojure/core.clj

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
(def *flush-on-newline* true)
2+
(def *print-readably* true)
3+
14
(def list (fn [& ls] ls))
25

36
(defmacro defn [name args & body]
@@ -8,11 +11,27 @@
811
(defn apply [f args]
912
(lexical-eval (concat (list f) args)))
1013

11-
(defn print [& more]
14+
(defn newline
15+
[]
16+
(system-newline))
17+
18+
(defn flush
19+
[]
20+
(flush-stdout))
21+
22+
(defn pr [& more]
1223
(print-string (apply str more)))
1324

25+
(defn prn [& more]
26+
(apply pr more)
27+
(newline)
28+
(flush))
29+
30+
(defn print [& more]
31+
(apply pr more))
32+
1433
(defn println [& more]
15-
(println-string (apply str more)))
34+
(apply prn more))
1635

1736
(defn inc [x]
1837
(+ x 1))
@@ -23,7 +42,7 @@
2342
(defmacro time [expr]
2443
(list (quote let) [(quote start) (quote (System_nanotime)) (quote ret) expr]
2544
(quote (do
26-
(println (str "Elapsed time: " (_slash_ (- (System_nanotime) start) 1000000.0) " msecs"))
45+
(println (str "Elapsed time: " (_slash_ (- (System_nanoTime) start) 1000000.0) " msecs"))
2746
ret))))
2847

2948
(defn slurp [f & opts]

src/clojure_std.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
pub(crate) mod thread;
2-
pub(crate) mod time;
1+
pub (crate) mod thread;
2+
pub (crate) mod time;
3+
pub (crate) mod env;

src/clojure_std/env.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::error_message;
2+
use crate::ifn::IFn;
3+
use crate::value::{ToValue, Value};
4+
use std::rc::Rc;
5+
6+
use std::env;
7+
use crate::type_tag::TypeTag;
8+
9+
/// provides a function to return env variables
10+
/// similair to Clojure (System/getenv [key])
11+
#[derive(Debug, Clone)]
12+
pub struct GetEnvFn {}
13+
impl ToValue for GetEnvFn {
14+
fn to_value(&self) -> Value {
15+
Value::IFn(Rc::new(self.clone()))
16+
}
17+
}
18+
19+
impl IFn for GetEnvFn {
20+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
21+
if args.len() == 1 {
22+
match args.get(0).unwrap().to_value() {
23+
Value::String(key) => {
24+
match env::var(key) {
25+
Ok(val) => Value::String(val),
26+
Err(_) => Value::Nil
27+
}
28+
}
29+
_a => error_message::type_mismatch(TypeTag::String, &_a)
30+
}
31+
} else {
32+
return error_message::wrong_arg_count(1, args.len());
33+
}
34+
}
35+
}

src/environment.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ use Environment::*;
7070
impl Environment {
7171
pub fn change_namespace(&self,symbol: Symbol) {
7272
let symbol = symbol.unqualified();
73-
73+
7474
match self.get_main_environment() {
7575
MainEnvironment(EnvironmentVal { curr_ns_sym, ..}) => {
7676
curr_ns_sym.replace(symbol);
@@ -162,9 +162,9 @@ impl Environment {
162162
match self {
163163
MainEnvironment(env_val) => {
164164
// If we've recieved a qualified symbol like
165-
// clojure.core/+
165+
// clojure.core/+
166166
if sym.ns != "" {
167-
// Use that namespace
167+
// Use that namespace
168168
env_val.get_from_namespace(&Symbol::intern(&sym.ns),sym)
169169
}
170170
else {
@@ -198,8 +198,9 @@ impl Environment {
198198
let nth_fn = rust_core::NthFn {};
199199
let do_macro = rust_core::DoMacro {};
200200
let concat_fn = rust_core::ConcatFn {};
201+
let flush_stdout_fn = rust_core::FlushStdoutFn {};
202+
let system_newline_fn = rust_core::SystemNewlineFn {};
201203
let print_string_fn = rust_core::PrintStringFn {};
202-
let println_string_fn = rust_core::PrintlnStringFn {};
203204
let read_line_fn = rust_core::ReadLineFn {};
204205
let assoc_fn = rust_core::AssocFn {};
205206

@@ -209,6 +210,7 @@ impl Environment {
209210
// clojure.std functions
210211
let thread_sleep_fn = clojure_std::thread::SleepFn {};
211212
let nanotime_fn = clojure_std::time::NanoTimeFn {};
213+
let get_env_fn = clojure_std::env::GetEnvFn {};
212214

213215
// Hardcoded fns
214216
let lexical_eval_fn = Value::LexicalEvalFn {};
@@ -248,10 +250,9 @@ impl Environment {
248250
thread_sleep_fn.to_rc_value(),
249251
);
250252

251-
environment.insert(
252-
Symbol::intern("System_nanotime"),
253-
nanotime_fn.to_rc_value()
254-
);
253+
environment.insert(Symbol::intern("System_nanoTime"), nanotime_fn.to_rc_value());
254+
255+
environment.insert(Symbol::intern("System_getenv"), get_env_fn.to_rc_value());
255256

256257
// core.clj wraps calls to the rust implementations
257258
// @TODO add this to clojure.rs.core namespace as clojure.rs.core/slurp
@@ -275,13 +276,19 @@ impl Environment {
275276
environment.insert(Symbol::intern("nth"), nth_fn.to_rc_value());
276277
environment.insert(Symbol::intern("assoc"), assoc_fn.to_rc_value());
277278
environment.insert(Symbol::intern("concat"), concat_fn.to_rc_value());
279+
280+
// input and output
278281
environment.insert(
279-
Symbol::intern("print-string"),
280-
print_string_fn.to_rc_value(),
282+
Symbol::intern("system-newline"),
283+
system_newline_fn.to_rc_value(),
281284
);
282285
environment.insert(
283-
Symbol::intern("println-string"),
284-
println_string_fn.to_rc_value(),
286+
Symbol::intern("flush-stdout"),
287+
flush_stdout_fn.to_rc_value(),
288+
);
289+
environment.insert(
290+
Symbol::intern("print-string"),
291+
print_string_fn.to_rc_value(),
285292
);
286293
environment.insert(Symbol::intern("read-line"), read_line_fn.to_rc_value());
287294

@@ -330,16 +337,16 @@ mod tests {
330337
// env_val.change_namespace(Symbol::intern_with_ns("not-ns","ns"));
331338
// assert_eq!(Symbol::intern("ns"),env_val.get_current_namespace())
332339
;
333-
334-
// @TODO add case for local environment
340+
341+
// @TODO add case for local environment
335342
}
336-
343+
337344
/////////////////////////////////////////////////////////////////////////////
338345
//
339346
// fn get_from_namespace(&self,namespace: &Symbol,sym: &Symbol) -> Rc<Value>
340347
//
341348
//////////////////////////////////////////////////////////////////////////////
342-
349+
343350
#[test]
344351
fn test_get_from_namespace() {
345352
let env_val = EnvironmentVal::new_main_val();

src/rust_core.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,18 @@ pub(crate) mod assoc;
4444
pub use self::assoc::*;
4545

4646
// input and output
47+
pub(crate) mod system_newline;
48+
pub use self::system_newline::*;
49+
pub(crate) mod flush_stdout;
50+
pub use self::flush_stdout::*;
4751
pub(crate) mod print_string;
4852
pub use self::print_string::*;
4953
pub(crate) mod string_print;
5054
pub use self::string_print::*;
5155
pub(crate) mod read_line;
5256
pub use self::read_line::*;
5357

58+
5459
// other
5560
pub(crate) mod slurp;
5661
pub use self::slurp::*;

src/rust_core/flush_stdout.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{Value, ToValue, Evaluable};
3+
use std::rc::Rc;
4+
5+
use std::io;
6+
7+
use crate::error_message;
8+
use nom::lib::std::convert::TryFrom;
9+
use std::io::{Read, Write};
10+
11+
/// Read a line from stdin TODO: should be aware of *in*
12+
/// (defn read-line [])
13+
#[derive(Debug, Clone)]
14+
pub struct FlushStdoutFn {}
15+
impl ToValue for FlushStdoutFn {
16+
fn to_value(&self) -> Value {
17+
Value::IFn(Rc::new(self.clone()))
18+
}
19+
}
20+
impl IFn for FlushStdoutFn {
21+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
22+
if args.len() != 0 {
23+
return error_message::wrong_arg_count(0, args.len())
24+
}
25+
io::stdout().flush();
26+
Value::Nil
27+
}
28+
}

src/rust_core/print_string.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,7 @@ use std::rc::Rc;
44

55
use crate::error_message;
66

7-
/// Primitive printing function;
8-
/// (defn println-string [string] .. prints single string with linebreak.. )
9-
#[derive(Debug, Clone)]
10-
pub struct PrintlnStringFn {}
11-
impl ToValue for PrintlnStringFn {
12-
fn to_value(&self) -> Value {
13-
Value::IFn(Rc::new(self.clone()))
14-
}
15-
}
16-
impl IFn for PrintlnStringFn {
17-
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
18-
if args.len() != 1 {
19-
return error_message::wrong_arg_count(1, args.len())
20-
}
21-
println!("{}", args.get(0).unwrap().to_string());
22-
Value::Nil
23-
}
24-
}
25-
26-
/// Primitive printing function;
7+
/// Primitive printing function; TODO: should be aware of *out*
278
/// (defn print-string [string] .. prints single string without linebreak.. )
289
#[derive(Debug, Clone)]
2910
pub struct PrintStringFn {}

src/rust_core/read_line.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::error_message;
88
use nom::lib::std::convert::TryFrom;
99
use std::io::{Read, Write};
1010

11-
/// Read a line from stdin
11+
/// Read a line from stdin TODO: should be aware of *in*
1212
/// (defn read-line [])
1313
#[derive(Debug, Clone)]
1414
pub struct ReadLineFn {}
@@ -23,7 +23,6 @@ impl IFn for ReadLineFn {
2323
return error_message::wrong_arg_count(0, args.len())
2424
}
2525
let mut input = String::new();
26-
io::stdout().flush();
2726
match io::stdin().read_line(&mut input) {
2827
Ok(_) => {
2928
input.pop();

src/rust_core/system_newline.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{ToValue, Value};
3+
use std::rc::Rc;
4+
5+
use crate::error_message;
6+
7+
/// Prints system newline, `\n` in rust on all platforms to stdout
8+
/// TODO: should be aware of *out*
9+
/// (defn print-string [string] .. prints single string without linebreak.. )
10+
#[derive(Debug, Clone)]
11+
pub struct SystemNewlineFn {}
12+
impl ToValue for SystemNewlineFn {
13+
fn to_value(&self) -> Value {
14+
Value::IFn(Rc::new(self.clone()))
15+
}
16+
}
17+
impl IFn for SystemNewlineFn {
18+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
19+
if args.len() != 0 {
20+
return error_message::wrong_arg_count(0, args.len());
21+
}
22+
print!("\n");
23+
Value::Nil
24+
}
25+
}

0 commit comments

Comments
 (0)