From c0b776401a7b41fb3240c6a510dec47a6e9dc081631f2672bbf33019ab477059 Mon Sep 17 00:00:00 2001 From: Apache <93100547+Apachedrag427@users.noreply.github.com> Date: Sat, 29 Jun 2024 02:17:06 -0500 Subject: [PATCH] Add bools and instants, add a few functions Light formatting as well --- src/executor.rs | 356 ++++++++++++++++++++++++++++++++++++------------ src/main.rs | 12 +- src/parser.rs | 162 +++++++++++----------- src/test.lisp | 16 ++- 4 files changed, 369 insertions(+), 177 deletions(-) diff --git a/src/executor.rs b/src/executor.rs index b199986..d54a1dd 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,17 +1,19 @@ -use std::{collections::HashMap, fmt}; +use std::{collections::HashMap, fmt, time::Instant}; use crate::PreLispValue; #[cfg(test)] mod tests { - use crate::{Parser, LispState, LispValue, Tokenizer}; + use crate::{LispState, LispValue, Parser, Tokenizer}; - use super::add_function; + use super::add_function; fn get_exec_result(source: &str) -> Result, Box> { let mut state = LispState::new(); - state.table.insert(String::from("output"), LispValue::List(vec![], false)); + state + .table + .insert(String::from("output"), LispValue::List(vec![], false)); add_function(&mut state.table, "print", |st, args| { if let LispValue::List(v, _) = st.table.get_mut("output").unwrap() { v.push(LispValue::List(args, false)) @@ -43,12 +45,12 @@ mod tests { #[test] fn test_hello_world() -> Result<(), Box> { assert_eq!( - vec![ - LispValue::String(String::from("Hello, World!")) - ], - get_exec_result(" + vec![LispValue::String(String::from("Hello, World!"))], + get_exec_result( + " (print \"Hello, World!\") - ")? + " + )? ); Ok(()) } @@ -56,10 +58,9 @@ mod tests { #[test] fn test_math() -> Result<(), Box> { assert_eq!( - vec![ - LispValue::Float(16.05) - ], - get_exec_result(" + vec![LispValue::Float(16.05)], + get_exec_result( + " (print (add (div @@ -69,7 +70,8 @@ mod tests { (mul 21 0.05) ) ) - ")? + " + )? ); Ok(()) } @@ -79,7 +81,6 @@ pub struct LispState { table: HashMap, } - #[derive(Debug)] pub struct RuntimeError { message: String, @@ -98,10 +99,13 @@ type RustFunctionType = fn(&mut LispState, Vec) -> Result, bool), + Instant(Instant), LispFunction(String, Vec, Vec), RustFunction(String, RustFunctionType), Map(HashMap), @@ -113,6 +117,8 @@ impl fmt::Display for LispValue { #[allow(unreachable_patterns)] match self { LispValue::Nil => write!(f, "nil"), + LispValue::True => write!(f, "true"), + LispValue::False => write!(f, "false"), LispValue::String(str) => write!(f, "\"{}\"", str), LispValue::LispFunction(name, _, _) => write!(f, "", name), LispValue::RustFunction(name, _) => write!(f, "", name), @@ -130,7 +136,7 @@ impl fmt::Display for LispValue { } else { write!(f, "({})", strs.join(" ")) } - }, + } val => { write!(f, "{}", format!("{:?}", val)) } @@ -142,6 +148,8 @@ fn lisp_display(v: LispValue) -> String { #[allow(unreachable_patterns)] match v { LispValue::Nil => String::from("nil"), + LispValue::True => String::from("true"), + LispValue::False => String::from("false"), LispValue::String(str) => str, LispValue::LispFunction(name, _, _) => format!("", name), LispValue::RustFunction(name, _) => format!("", name), @@ -159,7 +167,7 @@ fn lisp_display(v: LispValue) -> String { } else { format!("({})", strs.join(" ")) } - }, + } val => { format!("{}", val) } @@ -169,10 +177,13 @@ fn lisp_display(v: LispValue) -> String { fn get_type(v: &LispValue) -> String { match v { LispValue::Nil => String::from("nil"), + LispValue::True => String::from("bool"), + LispValue::False => String::from("bool"), LispValue::Integer(_) => String::from("int"), LispValue::Float(_) => String::from("float"), LispValue::String(_) => String::from("string"), LispValue::List(_, _) => String::from("list"), + LispValue::Instant(_) => String::from("instant"), LispValue::LispFunction(_, _, _) => String::from("function"), LispValue::RustFunction(_, _) => String::from("function"), LispValue::Map(_) => String::from("map"), @@ -180,6 +191,18 @@ fn get_type(v: &LispValue) -> String { } } +fn is_falsy(v: &LispValue) -> bool { + match v { + LispValue::Nil => true, + LispValue::False => true, + _ => false, + } +} + +fn is_truthy(v: &LispValue) -> bool { + !is_falsy(v) +} + impl From<&str> for LispValue { fn from(value: &str) -> Self { LispValue::String(value.to_string()) @@ -200,20 +223,117 @@ impl From for LispValue { LispValue::Float(value) } } +impl From for LispValue { + fn from(value: bool) -> Self { + match value { + true => LispValue::True, + false => LispValue::False, + } + } +} impl From> for LispValue { fn from(value: Vec) -> Self { LispValue::List(value, false) } } -fn add_function + Clone>(table: &mut HashMap, name: T, func: RustFunctionType) { - table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func)); +fn add_function + Clone>( + table: &mut HashMap, + name: T, + func: RustFunctionType, +) { + table.insert( + name.clone().into(), + LispValue::RustFunction(name.into(), func), + ); } impl LispState { pub fn new() -> LispState { let mut table = HashMap::new(); + add_function(&mut table, "now", |_, _| { + Ok(vec![LispValue::Instant(Instant::now())]) + }); + + add_function(&mut table, "since", |_, args| { + if args.len() != 1 { + return Err(RuntimeError { + message: format!("Bad arguments to since (expected 1, got {})", args.len()), + }); + } + if let LispValue::Instant(i) = args[0] { + Ok(vec![LispValue::Float( + Instant::now().duration_since(i).as_secs_f32(), + )]) + } else { + Err(RuntimeError { + message: format!( + "Bad arguments to since (expected instant, got {})", + get_type(&args[0]) + ), + }) + } + }); + + add_function(&mut table, "type", |_, args| { + if args.len() != 1 { + return Err(RuntimeError { + message: format!("Bad arguments to type (expected 1, got {})", args.len()), + }); + } + Ok(vec![LispValue::String(get_type(&args[0]))]) + }); + + add_function(&mut table, "sleep", |_, args| { + if args.len() != 1 { + return Err(RuntimeError { + message: format!("Bad arguments to sleep (expected 1, got {})", args.len()), + }); + } + + if let LispValue::Float(n) = args[0] { + std::thread::sleep(std::time::Duration::from_secs_f32(n)); + } else if let LispValue::Integer(n) = args[0] { + std::thread::sleep(std::time::Duration::from_secs(n as u64)); + } else { + return Err(RuntimeError { + message: format!( + "Bad arguments to sleep (expected float or int, got {})", + get_type(&args[0]) + ), + }); + } + + Ok(vec![LispValue::Nil]) + }); + + add_function(&mut table, "or", |_, args| { + if args.len() != 2 { + return Err(RuntimeError { + message: format!("Bad arguments to or (expected 2, got {})", args.len()), + }); + } + if is_truthy(&args[0]) { + Ok(vec![args[0].clone()]) + } else { + Ok(vec![args[1].clone()]) + } + }); + + add_function(&mut table, "and", |_, args| { + if args.len() != 2 { + return Err(RuntimeError { + message: format!("Bad arguments to and (expected 2, got {})", args.len()), + }); + } + if is_truthy(&args[0]) { + Ok(vec![args[1].clone()]) + } else { + Ok(vec![args[0].clone()]) + } + }); + add_function(&mut table, "echo", |_, args| { return Ok(args); }); @@ -221,26 +341,29 @@ impl LispState { add_function(&mut table, "set", |state, args| { if args.len() != 2 { return Err(RuntimeError { - message: format!("Bad arguments to set (expected 2, got {})", args.len()) - }) + message: format!("Bad arguments to set (expected 2, got {})", args.len()), + }); } if let LispValue::String(name) = &args[0] { state.table.insert(name.to_owned(), args[1].clone()); } else { return Err(RuntimeError { - message: format!("Bad argument 1 to set (expected string, got {})", get_type(&args[0])) - }) + message: format!( + "Bad argument 1 to set (expected string, got {})", + get_type(&args[0]) + ), + }); } Ok(vec![args[1].clone()]) }); - add_function(&mut table, "get", |_,args| { + add_function(&mut table, "get", |_, args| { if args.len() != 2 { return Err(RuntimeError { - message: format!("Bad arguments to get (expected 2, got {})", args.len()) - }) + message: format!("Bad arguments to get (expected 2, got {})", args.len()), + }); } if let LispValue::Map(map) = &args[0] { @@ -248,13 +371,19 @@ impl LispState { return Ok(vec![map.get(str).unwrap_or(&LispValue::Nil).to_owned()]); } else { return Err(RuntimeError { - message: format!("Bad argument 2 to get (expected string, got {})", get_type(&args[0])) - }) + message: format!( + "Bad argument 2 to get (expected string, got {})", + get_type(&args[0]) + ), + }); } } else { return Err(RuntimeError { - message: format!("Bad argument 1 to get (expected map, got {})", get_type(&args[0])) - }) + message: format!( + "Bad argument 1 to get (expected map, got {})", + get_type(&args[0]) + ), + }); } }); @@ -282,7 +411,7 @@ impl LispState { add_function(&mut table, "add", |_, args| { if args.len() < 1 { - return Ok(vec![LispValue::Nil]) + return Ok(vec![LispValue::Nil]); } else if args.len() == 1 { return Ok(vec![args[0].clone()]); } @@ -292,9 +421,14 @@ impl LispState { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), - _ => return Err(RuntimeError { - message: format!("Invalid argument to 'add' (expected float or int, got {}", get_type(v)) - }) + _ => { + return Err(RuntimeError { + message: format!( + "Invalid argument to 'add' (expected float or int, got {}", + get_type(v) + ), + }) + } } } @@ -309,21 +443,21 @@ impl LispState { } } return Ok(vec![LispValue::Integer(sum)]); - }, + } "float" => { let mut sum = 0.0 as f32; for v in &args { if let LispValue::Float(n) = v { sum += n; - } else if let LispValue::Integer(n) = v{ + } else if let LispValue::Integer(n) = v { sum += *n as f32; } else { unreachable!() } } return Ok(vec![LispValue::Float(sum)]); - }, - _ => unreachable!() + } + _ => unreachable!(), } }); @@ -339,9 +473,14 @@ impl LispState { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), - _ => return Err(RuntimeError { - message: format!("Invalid argument to 'sub' (expected float or int, got {}", get_type(v)) - }) + _ => { + return Err(RuntimeError { + message: format!( + "Invalid argument to 'sub' (expected float or int, got {}", + get_type(v) + ), + }) + } } } @@ -360,7 +499,7 @@ impl LispState { } else { unreachable!() } - }, + } "float" => { if let LispValue::Float(n) = args[0] { let mut sum = n; @@ -386,11 +525,12 @@ impl LispState { } } return Ok(vec![LispValue::Float(sum)]); - } { + } + { unreachable!() } - }, - _ => unreachable!() + } + _ => unreachable!(), } }); @@ -406,9 +546,14 @@ impl LispState { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), - _ => return Err(RuntimeError { - message: format!("Invalid argument to 'mul' (expected float or int, got {}", get_type(v)) - }) + _ => { + return Err(RuntimeError { + message: format!( + "Invalid argument to 'mul' (expected float or int, got {}", + get_type(v) + ), + }) + } } } @@ -427,7 +572,7 @@ impl LispState { } else { unreachable!() } - }, + } "float" => { if let LispValue::Float(n) = args[0] { let mut product = n; @@ -453,11 +598,12 @@ impl LispState { } } return Ok(vec![LispValue::Float(product)]); - } { + } + { unreachable!() } - }, - _ => unreachable!() + } + _ => unreachable!(), } }); @@ -473,9 +619,14 @@ impl LispState { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), - _ => return Err(RuntimeError { - message: format!("Invalid argument to 'div' (expected float or int, got {}", get_type(v)) - }) + _ => { + return Err(RuntimeError { + message: format!( + "Invalid argument to 'div' (expected float or int, got {}", + get_type(v) + ), + }) + } } } @@ -494,7 +645,7 @@ impl LispState { } else { unreachable!() } - }, + } "float" => { if let LispValue::Float(n) = args[0] { let mut product = n; @@ -520,17 +671,16 @@ impl LispState { } } return Ok(vec![LispValue::Float(product)]); - } { + } + { unreachable!() } - }, - _ => unreachable!() + } + _ => unreachable!(), } }); - LispState { - table - } + LispState { table } } fn handle_prevalues(&self, input: Vec) -> Vec { @@ -539,25 +689,34 @@ impl LispState { for v in input { out.push(match v { PreLispValue::Nil => LispValue::Nil, + PreLispValue::True => LispValue::True, + PreLispValue::False => LispValue::False, PreLispValue::String(str) => LispValue::String(str), PreLispValue::Integer(num) => LispValue::Integer(num), PreLispValue::Float(num) => LispValue::Float(num), PreLispValue::List(list, quoted) => { LispValue::List(Self::handle_prevalues(self, list), quoted) - }, - PreLispValue::LispFunction(name, arg_names, instructions) => { - LispValue::LispFunction(name, arg_names, Self::handle_prevalues(self, instructions)) - }, - PreLispValue::Var(name) => { - LispValue::Var(name) } + PreLispValue::LispFunction(name, arg_names, instructions) => { + LispValue::LispFunction( + name, + arg_names, + Self::handle_prevalues(self, instructions), + ) + } + PreLispValue::Var(name) => LispValue::Var(name), }) } out } - fn eval_list(&mut self, env: &mut HashMap, list: &Vec, quoted: bool) -> Result<(Vec, bool), RuntimeError> { + fn eval_list( + &mut self, + env: &mut HashMap, + list: &Vec, + quoted: bool, + ) -> Result<(Vec, bool), RuntimeError> { if list.len() < 1 { return Ok((vec![LispValue::List(Vec::new(), quoted)], false)); } @@ -566,7 +725,10 @@ impl LispState { for i in 0..list.len() { if let LispValue::Var(name) = &list[i] { - list[i] = env.get(name).unwrap_or_else(|| self.table.get(name).unwrap_or(&LispValue::Nil)).to_owned(); + list[i] = env + .get(name) + .unwrap_or_else(|| self.table.get(name).unwrap_or(&LispValue::Nil)) + .to_owned(); } if let LispValue::List(elements, quoted) = &list[i] { let (elems, astuple) = self.eval_list(env, elements, *quoted)?; @@ -588,24 +750,38 @@ impl LispState { if let LispValue::RustFunction(_name, f) = &list[0] { Ok((f(self, list[1..].to_vec())?, true)) } else if let LispValue::LispFunction(_name, _, _) = &list[0] { - Ok((self.call_lisp_func_internal(env, &list[0], list[1..].to_vec())?, true)) + Ok(( + self.call_lisp_func_internal(env, &list[0], list[1..].to_vec())?, + true, + )) } else { Ok((list.to_vec(), false)) } } - fn call_lisp_func_internal(&mut self, env: &mut HashMap, f: &LispValue, args: Vec) -> Result, RuntimeError> { + fn call_lisp_func_internal( + &mut self, + env: &mut HashMap, + f: &LispValue, + args: Vec, + ) -> Result, RuntimeError> { let (arg_names, instructions) = match f { - LispValue::LispFunction(_, arg_names, i) => { - (arg_names, i) - }, - _ => return Err(RuntimeError { - message: format!("Invalid argument to call_lisp_func_internal (expected function, got {})", get_type(f)) - }) + LispValue::LispFunction(_, arg_names, i) => (arg_names, i), + _ => { + return Err(RuntimeError { + message: format!( + "Invalid argument to call_lisp_func_internal (expected function, got {})", + get_type(f) + ), + }) + } }; for i in 0..arg_names.len() { - env.insert(arg_names[i].to_owned(), args.get(i).unwrap_or(&LispValue::Nil).to_owned()); + env.insert( + arg_names[i].to_owned(), + args.get(i).unwrap_or(&LispValue::Nil).to_owned(), + ); } let mut out = Vec::new(); @@ -626,18 +802,25 @@ impl LispState { Ok(out) } - pub fn call_lisp_func(&mut self, f: &LispValue, args: Vec>) -> Result, RuntimeError> { + pub fn call_lisp_func( + &mut self, + f: &LispValue, + args: Vec>, + ) -> Result, RuntimeError> { if !matches!(f, LispValue::LispFunction(_, _, _)) { return Err(RuntimeError { - message: format!("Invalid argument to call_lisp_func_internal (expected function, got {})", get_type(&f)) - }) + message: format!( + "Invalid argument to call_lisp_func_internal (expected function, got {})", + get_type(&f) + ), + }); } let mut vargs = Vec::new(); for v in args { vargs.push(v.into()); } - + self.call_lisp_func_internal(&mut HashMap::new(), &f, vargs) } @@ -649,9 +832,12 @@ impl LispState { } } - pub fn execute(&mut self, instructions: Vec) -> Result, RuntimeError> { + pub fn execute( + &mut self, + instructions: Vec, + ) -> Result, RuntimeError> { let instructions = Self::handle_prevalues(self, instructions); - + let mut outs = Vec::new(); let mut env = HashMap::new(); diff --git a/src/main.rs b/src/main.rs index 3e54dea..439682c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,24 +8,16 @@ mod executor; use executor::*; fn main() -> Result<(), Box> { - let source = std::fs::read_to_string("src/test.lisp").unwrap(); + let source = std::fs::read_to_string("src/test.lisp").unwrap(); - let mut tokenizer = Tokenizer::new(source); + let mut tokenizer = Tokenizer::new(source); let tokens = tokenizer.tokenize()?; let mut parser = Parser::new(tokens); let instructions = parser.parse(); let mut state = LispState::new(); - let mut some_map = std::collections::HashMap::new(); - some_map.insert(String::from("x"), LispValue::Float(0.0)); - some_map.insert(String::from("y"), LispValue::Float(0.0)); - state.execute(instructions)?; - let f = state.get_func("takevalue").unwrap(); - - state.call_lisp_func(&f, vec![LispValue::Map(some_map)])?; - Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index 3554951..151d5f9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt}; #[cfg(test)] mod tests { - use crate::{Parser, PreLispValue, Tokenizer, TokenizerError}; + use crate::{Parser, PreLispValue, Tokenizer, TokenizerError}; fn quick_parse(source: &str) -> Result, TokenizerError> { let mut tokenizer = Tokenizer::new(String::from(source)); @@ -30,15 +30,12 @@ mod tests { #[test] fn test_hello_world() -> Result<(), TokenizerError> { assert_eq!( - vec![ - list(vec![ - var("print"), - string("Hello, World!") - ], false) - ], - quick_parse(" + vec![list(vec![var("print"), string("Hello, World!")], false)], + quick_parse( + " (print \"Hello, World!\") - ")? + " + )? ); Ok(()) } @@ -46,29 +43,29 @@ mod tests { #[test] fn test_math() -> Result<(), TokenizerError> { assert_eq!( - vec![ - list(vec![ + vec![list( + vec![ var("print"), - list(vec![ - var("add"), - list(vec![ - var("div"), - float(4.5), - list(vec![ - var("sub"), - float(0.5), - float(0.2) - ], false) - ], false), - list(vec![ - var("mul"), - int(21), - float(0.05) - ], false) - ], false) - ], false) - ], - quick_parse(" + list( + vec![ + var("add"), + list( + vec![ + var("div"), + float(4.5), + list(vec![var("sub"), float(0.5), float(0.2)], false) + ], + false + ), + list(vec![var("mul"), int(21), float(0.05)], false) + ], + false + ) + ], + false + )], + quick_parse( + " (print (add (div @@ -78,7 +75,8 @@ mod tests { (mul 21 0.05) ) ) - ")? + " + )? ); Ok(()) } @@ -89,6 +87,8 @@ use crate::Token; #[derive(Debug, Clone, PartialEq)] pub enum PreLispValue { Nil, + True, + False, String(String), Var(String), Integer(i32), @@ -101,11 +101,13 @@ impl fmt::Display for PreLispValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PreLispValue::Nil => write!(f, "nil"), + PreLispValue::True => write!(f, "true"), + PreLispValue::False => write!(f, "false"), PreLispValue::String(str) => write!(f, "{}", str), - PreLispValue::LispFunction(name, _, _) => write!(f, "<'{}': Lisp Function>", name), + PreLispValue::LispFunction(name, _, _) => write!(f, "", name), PreLispValue::Integer(num) => write!(f, "{}", num), PreLispValue::Float(num) => write!(f, "{}", num), - _ => todo!() + _ => todo!(), } } } @@ -137,7 +139,8 @@ impl From> for PreLispValue { } // TODO: Handle failure -fn read_exp(open_paren_idx: usize, tokens: &Vec) -> Option<(Vec, usize)> /* Option */ { +fn read_exp(open_paren_idx: usize, tokens: &Vec) -> Option<(Vec, usize)> /* Option */ +{ let mut tkns = Vec::new(); let mut depth = 0; @@ -168,57 +171,66 @@ fn read_exp(open_paren_idx: usize, tokens: &Vec) -> Option<(Vec, u fn parse_exp(tokens: Vec, quoted: bool) -> PreLispValue { let mut values = Vec::new(); - + if tokens.len() < 1 { return PreLispValue::List(values, false); } let mut quote_next_list = false; let mut unquote_next_list = false; - + let mut i = 0; while i < tokens.len() { let tkn = &tokens[i]; match tkn { Token::Quote => { quote_next_list = true; - }, + } Token::Unquote => { unquote_next_list = true; } Token::OpenParen => { let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap(); - values.push(parse_exp(tkns, if unquote_next_list {false} else {quote_next_list || quoted})); + values.push(parse_exp( + tkns, + if unquote_next_list { + false + } else { + quote_next_list || quoted + }, + )); i = close_paren_idx; quote_next_list = false; unquote_next_list = false; - }, - Token::Identifier(name) => { - if name == &String::from("nil") { - values.push(PreLispValue::Nil); - } else { - values.push(PreLispValue::Var(name.to_owned())); - } + } + Token::Identifier(name) => match name.as_str() { + "nil" => values.push(PreLispValue::Nil), + "true" => values.push(PreLispValue::True), + "false" => values.push(PreLispValue::False), + _ => values.push(PreLispValue::Var(name.to_owned())), }, Token::Index(map, idx) => { - values.push(PreLispValue::List(vec![ - PreLispValue::Var(String::from("get")), - PreLispValue::Var(map.to_owned()), - PreLispValue::String(idx.to_owned()) - ], false)); + values.push(PreLispValue::List( + vec![ + PreLispValue::Var(String::from("get")), + PreLispValue::Var(map.to_owned()), + PreLispValue::String(idx.to_owned()), + ], + false, + )); } Token::Integer(num) => { values.push(PreLispValue::Integer(*num)); - }, + } Token::Float(num) => { values.push(PreLispValue::Float(*num)); - }, + } Token::String(str) => { values.push(PreLispValue::String(str.to_owned())); - }, + } Token::CloseParen => { panic!("Unexpected closing parenthesis"); - }, + } } i += 1; } @@ -234,9 +246,9 @@ pub struct Parser { fn add_macro( macros: &mut HashMap) -> Vec>, name: impl Into, - mac: fn(Vec) -> Vec) { - - macros.insert(name.into(), mac); + mac: fn(Vec) -> Vec, +) { + macros.insert(name.into(), mac); } impl Parser { @@ -244,11 +256,10 @@ impl Parser { let mut macros = HashMap::new(); add_macro(&mut macros, "set", |x| { - if x.len() != 3 || - ( - !matches!(x[1], PreLispValue::Var(_)) && - !matches!(x[1], PreLispValue::String(_)) - ) { + if x.len() != 3 + || (!matches!(x[1], PreLispValue::Var(_)) + && !matches!(x[1], PreLispValue::String(_))) + { return x; } @@ -271,9 +282,8 @@ impl Parser { let mut list: &Vec = &Vec::new(); if x.len() == 3 { - if - !matches!(x[1], PreLispValue::List(_, _)) || - !matches!(x[2], PreLispValue::List(_, _)) + if !matches!(x[1], PreLispValue::List(_, _)) + || !matches!(x[2], PreLispValue::List(_, _)) { return x; } @@ -285,10 +295,9 @@ impl Parser { list = l; } } else if x.len() == 4 { - if - !matches!(x[1], PreLispValue::Var(_)) || - !matches!(x[2], PreLispValue::List(_, _)) || - !matches!(x[3], PreLispValue::List(_, _)) + if !matches!(x[1], PreLispValue::Var(_)) + || !matches!(x[2], PreLispValue::List(_, _)) + || !matches!(x[3], PreLispValue::List(_, _)) { return x; } @@ -315,16 +324,13 @@ impl Parser { let func = PreLispValue::LispFunction(name.clone(), arg_names, list.to_owned()); if x.len() == 4 { - return vec![PreLispValue::Var(String::from("set")), name.into(), func] + return vec![PreLispValue::Var(String::from("set")), name.into(), func]; } return vec![PreLispValue::Var(String::from("echo")), func]; }); - Parser { - tokens, - macros - } + Parser { tokens, macros } } fn macro_check(&mut self, input: Vec, quoted: bool) -> Vec { @@ -351,7 +357,7 @@ impl Parser { pub fn parse(&mut self) -> Vec { let mut values = Vec::new(); - + let mut i = 0; while i < self.tokens.len() { match &self.tokens[i] { @@ -367,7 +373,7 @@ impl Parser { } i += 1; } - + self.macro_check(values, false) } -} \ No newline at end of file +} diff --git a/src/test.lisp b/src/test.lisp index b6856e2..e54897a 100644 --- a/src/test.lisp +++ b/src/test.lisp @@ -1,5 +1,13 @@ -(fn takevalue(origin) ( - (print (concat "Origin: (" origin.x ", " origin.y ")")) ; => Origin: (0, 0) - (print origin) ; => Map({"x": Float(0.0), "y": Float(0.0)}) -)) +(fn countuntil(until n) ( + (set n (add (or n 0) 1)) + + )) + + +(set start (now)) + +(countuntil 100) + +(print (since start)) +