diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/extended_environment.rs | 76 | ||||
-rw-r--r-- | src/main.rs | 44 |
2 files changed, 112 insertions, 8 deletions
diff --git a/src/extended_environment.rs b/src/extended_environment.rs new file mode 100644 index 0000000..d13cc2b --- /dev/null +++ b/src/extended_environment.rs @@ -0,0 +1,76 @@ +use macroquad::prelude::*; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use rust_lisp::model::{Env, FloatType, RuntimeError, Symbol, Value}; +use rust_lisp::utils::{require_arg, require_typed_arg}; + +pub type HashMapRc = Rc<RefCell<HashMap<Value, Value>>>; + +pub fn extend_environment(env: &Rc<RefCell<Env>>) { + env.borrow_mut().define( + Symbol::from("mq-draw-circle"), + Value::NativeFunc( + |_env, args| { + let x = require_typed_arg::<FloatType>("mq-draw-circle", &args, 0).unwrap(); + let y = require_typed_arg::<FloatType>("mq-draw-circle", &args, 1).unwrap(); + let radius = require_typed_arg::<FloatType>("mq-draw-circle", &args, 2).unwrap(); + let color = GREEN; + + draw_circle(x, y, radius, color); + return Ok(Value::NIL); + }) + ); + + + // Hashtable functions + // TODO: convert to elisp compatible hash table command + env.borrow_mut().define( + Symbol::from("make-hash-table"), + Value::NativeFunc(|_env, args| { + let chunks = args.chunks(2); + + let mut hash = HashMap::new(); + + for pair in chunks { + let key = pair.get(0).unwrap(); + let value = pair.get(1); + + if let Some(value) = value { + hash.insert(key.clone(), value.clone()); + } else { + return Err(RuntimeError { + msg: format!("Must pass an even number of arguments to 'hash', because they're used as key/value pairs; found extra argument {}", key) + }); + } + } + + Ok(Value::HashMap(Rc::new(RefCell::new(hash)))) + }), + ); + + env.borrow_mut().define( + Symbol::from("hash_get"), + Value::NativeFunc(|_env, args| { + let hash = require_typed_arg::<&HashMapRc>("hash_get", &args, 0)?; + let key = require_arg("hash_get", &args, 1)?; + + Ok(hash + .borrow() + .get(key) + .map(|v| v.clone()) + .unwrap_or(Value::NIL)) + }), + ); + + env.borrow_mut().define( + Symbol::from("hash_set"), + Value::NativeFunc(|_env, args| { + let hash = require_typed_arg::<&HashMapRc>("hash_set", &args, 0)?; + let key = require_arg("hash_set", &args, 1)?; + let value = require_arg("hash_set", &args, 2)?; + + hash.borrow_mut().insert(key.clone(), value.clone()); + + Ok(Value::HashMap(hash.clone())) + }), + ); +} diff --git a/src/main.rs b/src/main.rs index dbc60fb..62a3562 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,33 +3,61 @@ use macroquad::prelude::*; use std::{cell::RefCell, rc::Rc}; use rust_lisp::default_env; +use rust_lisp::lisp; use rust_lisp::parser::parse; use rust_lisp::interpreter::eval; +use rust_lisp::model::{Symbol, Value}; +mod extended_environment; #[macroquad::main("BasicShapes")] async fn main() { // create a base environment let env = Rc::new(RefCell::new(default_env())); + // define new methods + extended_environment::extend_environment(&env); + // parse into an iterator of syntax trees (one for each root) - let mut ast_iter = parse("(+ \"Hello \" \"world!\")"); - let first_expression = ast_iter.next().unwrap().unwrap(); + // let mut ast_iter = parse("(+ \"Hello \" \"world!\")"); + // let first_expression = ast_iter.next().unwrap().unwrap(); // evaluate - let evaluation_result = eval(env.clone(), &first_expression).unwrap(); + // let evaluation_result = eval(env.clone(), &first_expression).unwrap(); + // let mut ast_iter = parse("(test_draw)"); + // let first_expression = ast_iter.next().unwrap().unwrap(); + + // let first_expression = lisp! {(test_draw)}; + + // let mut inc = parse("(begin (set a 0) (+ a 1))"); + // let mut inc = parse("(begin (define a 0) (set a (+ a 1)))"); + // let inc_exp = inc.next().unwrap().unwrap(); + + // let inc_exp = lisp! { + // (begin (define a 0) (set a (+ a 1))) + // }; + // eval(env.clone(), &inc_exp).unwrap(); - // use result - println!("{}", &evaluation_result); + // let inc_exp = lisp! { + // (set a (+ a 1)) + // }; + + let gol_exp = parse(include_str!("../scripts/main.el")); + for exp in gol_exp { + eval(env.clone(), &exp.unwrap()).unwrap(); + } + + // let mut inc = parse("(set a (+ a 1))"); + // let inc_exp = inc.next().unwrap().unwrap(); loop { clear_background(RED); draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE); draw_rectangle(screen_width() / 2.0 - 60.0, 100.0, 120.0, 60.0, GREEN); - draw_circle(screen_width() - 30.0, screen_height() - 30.0, 15.0, YELLOW); - - draw_text(&format!("IT WORKS! {}!", &evaluation_result), 20.0, 20.0, 30.0, DARKGRAY); + eval(env.clone(), &first_expression).unwrap(); + let inc_eval = eval(env.clone(), &inc_exp).unwrap(); + draw_text(&format!("IT WORKS! {}!", &inc_eval), 20.0, 20.0, 30.0, DARKGRAY); next_frame().await } |