One step closer to functions
This commit is contained in:
parent
977c6b0e4e
commit
59bae011a3
3 changed files with 158 additions and 65 deletions
197
src/executor.rs
197
src/executor.rs
|
@ -1,12 +1,14 @@
|
||||||
use std::{collections::HashMap, fmt};
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
|
use crate::PreLispValue;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{parse, LispState, LispValue, Tokenizer, TokenizerError};
|
use crate::{parse, LispState, LispValue, Tokenizer};
|
||||||
|
|
||||||
use super::add_function;
|
use super::add_function;
|
||||||
|
|
||||||
fn get_exec_result(source: &str) -> Result<Vec<LispValue>, TokenizerError> {
|
fn get_exec_result(source: &str) -> Result<Vec<LispValue>, Box<dyn std::error::Error>> {
|
||||||
let mut state = LispState::new();
|
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));
|
||||||
|
@ -15,13 +17,13 @@ mod tests {
|
||||||
v.push(LispValue::List(args, false))
|
v.push(LispValue::List(args, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![LispValue::Nil]
|
Ok(vec![LispValue::Nil])
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut tokenizer = Tokenizer::new(String::from(source));
|
let mut tokenizer = Tokenizer::new(String::from(source));
|
||||||
let instructions = parse(tokenizer.tokenize()?);
|
let instructions = parse(tokenizer.tokenize()?);
|
||||||
|
|
||||||
state.execute(instructions);
|
state.execute(instructions)?;
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
if let LispValue::List(outerlist, _) = &state.table["output"] {
|
if let LispValue::List(outerlist, _) = &state.table["output"] {
|
||||||
|
@ -38,7 +40,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hello_world() -> Result<(), TokenizerError> {
|
fn test_hello_world() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
LispValue::String(String::from("Hello, World!"))
|
LispValue::String(String::from("Hello, World!"))
|
||||||
|
@ -51,7 +53,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_math() -> Result<(), TokenizerError> {
|
fn test_math() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
LispValue::Float(16.05)
|
LispValue::Float(16.05)
|
||||||
|
@ -72,16 +74,26 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::PreLispValue;
|
|
||||||
|
|
||||||
pub struct LispState {
|
pub struct LispState {
|
||||||
table: HashMap<String, LispValue>,
|
table: HashMap<String, LispValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_function<T: Into<String> + Clone>(table: &mut HashMap<String, LispValue>, name: T, func: fn(&mut LispState, Vec<LispValue>) -> Vec<LispValue>) {
|
|
||||||
table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func));
|
#[derive(Debug)]
|
||||||
|
pub struct RuntimeError {
|
||||||
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RuntimeError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Runtime Error: {}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for RuntimeError {}
|
||||||
|
|
||||||
|
type RustFunctionType = fn(&mut LispState, Vec<LispValue>) -> Result<Vec<LispValue>, RuntimeError>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum LispValue {
|
pub enum LispValue {
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -89,8 +101,9 @@ pub enum LispValue {
|
||||||
Integer(i32),
|
Integer(i32),
|
||||||
Float(f32),
|
Float(f32),
|
||||||
List(Vec<LispValue>, bool),
|
List(Vec<LispValue>, bool),
|
||||||
LispFunction(String, Vec<LispValue>),
|
LispFunction(String, Vec<String>, Vec<LispValue>),
|
||||||
RustFunction(String, fn(&mut LispState, Vec<LispValue>) -> Vec<LispValue>),
|
RustFunction(String, RustFunctionType),
|
||||||
|
Var(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for LispValue {
|
impl fmt::Display for LispValue {
|
||||||
|
@ -99,7 +112,7 @@ impl fmt::Display for LispValue {
|
||||||
match self {
|
match self {
|
||||||
LispValue::Nil => write!(f, "nil"),
|
LispValue::Nil => write!(f, "nil"),
|
||||||
LispValue::String(str) => write!(f, "\"{}\"", str),
|
LispValue::String(str) => write!(f, "\"{}\"", str),
|
||||||
LispValue::LispFunction(name, _) => write!(f, "<function {}>", name),
|
LispValue::LispFunction(name, _, _) => write!(f, "<function {}>", name),
|
||||||
LispValue::RustFunction(name, _) => write!(f, "<function {}>", name),
|
LispValue::RustFunction(name, _) => write!(f, "<function {}>", name),
|
||||||
LispValue::Integer(num) => write!(f, "{}", num),
|
LispValue::Integer(num) => write!(f, "{}", num),
|
||||||
LispValue::Float(num) => write!(f, "{}", num),
|
LispValue::Float(num) => write!(f, "{}", num),
|
||||||
|
@ -123,6 +136,19 @@ impl fmt::Display for LispValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type(v: &LispValue) -> String {
|
||||||
|
match v {
|
||||||
|
LispValue::Nil => String::from("nil"),
|
||||||
|
LispValue::Integer(_) => String::from("int"),
|
||||||
|
LispValue::Float(_) => String::from("float"),
|
||||||
|
LispValue::String(_) => String::from("string"),
|
||||||
|
LispValue::List(_, _) => String::from("list"),
|
||||||
|
LispValue::LispFunction(_, _, _) => String::from("function"),
|
||||||
|
LispValue::RustFunction(_, _) => String::from("function"),
|
||||||
|
LispValue::Var(_) => String::from("symbol")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&str> for LispValue {
|
impl From<&str> for LispValue {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &str) -> Self {
|
||||||
LispValue::String(value.to_string())
|
LispValue::String(value.to_string())
|
||||||
|
@ -143,6 +169,15 @@ impl From<f32> for LispValue {
|
||||||
LispValue::Float(value)
|
LispValue::Float(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<Vec<LispValue>> for LispValue {
|
||||||
|
fn from(value: Vec<LispValue>) -> Self {
|
||||||
|
LispValue::List(value, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_function<T: Into<String> + Clone>(table: &mut HashMap<String, LispValue>, name: T, func: RustFunctionType) {
|
||||||
|
table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func));
|
||||||
|
}
|
||||||
|
|
||||||
impl LispState {
|
impl LispState {
|
||||||
pub fn new() -> LispState {
|
pub fn new() -> LispState {
|
||||||
|
@ -157,7 +192,7 @@ impl LispState {
|
||||||
let str = strings.join(" ");
|
let str = strings.join(" ");
|
||||||
println!("{}", str);
|
println!("{}", str);
|
||||||
|
|
||||||
vec![LispValue::Nil]
|
Ok(vec![LispValue::Nil])
|
||||||
});
|
});
|
||||||
|
|
||||||
add_function(&mut table, "concat", |_, args| {
|
add_function(&mut table, "concat", |_, args| {
|
||||||
|
@ -167,14 +202,14 @@ impl LispState {
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = strings.concat();
|
let str = strings.concat();
|
||||||
vec![LispValue::String(str)]
|
Ok(vec![LispValue::String(str)])
|
||||||
});
|
});
|
||||||
|
|
||||||
add_function(&mut table, "add", |_, args| {
|
add_function(&mut table, "add", |_, args| {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return vec![LispValue::Nil]
|
return Ok(vec![LispValue::Nil])
|
||||||
} else if args.len() == 1 {
|
} else if args.len() == 1 {
|
||||||
return vec![args[0].clone()];
|
return Ok(vec![args[0].clone()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut t = "int";
|
let mut t = "int";
|
||||||
|
@ -182,7 +217,9 @@ impl LispState {
|
||||||
match v {
|
match v {
|
||||||
LispValue::Float(_) => t = "float",
|
LispValue::Float(_) => t = "float",
|
||||||
LispValue::Integer(_) => (),
|
LispValue::Integer(_) => (),
|
||||||
_ => return vec![LispValue::Nil]
|
_ => return Err(RuntimeError {
|
||||||
|
message: format!("Invalid argument to 'add' (expected float or int, got {}", get_type(v))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +233,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Integer(sum)];
|
return Ok(vec![LispValue::Integer(sum)]);
|
||||||
},
|
},
|
||||||
"float" => {
|
"float" => {
|
||||||
let mut sum = 0.0 as f32;
|
let mut sum = 0.0 as f32;
|
||||||
|
@ -209,7 +246,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(sum)];
|
return Ok(vec![LispValue::Float(sum)]);
|
||||||
},
|
},
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -217,9 +254,9 @@ impl LispState {
|
||||||
|
|
||||||
add_function(&mut table, "sub", |_, args| {
|
add_function(&mut table, "sub", |_, args| {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return vec![LispValue::Nil]
|
return Ok(vec![LispValue::Nil]);
|
||||||
} else if args.len() == 1 {
|
} else if args.len() == 1 {
|
||||||
return vec![args[0].clone()];
|
return Ok(vec![args[0].clone()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut t = "int";
|
let mut t = "int";
|
||||||
|
@ -227,7 +264,9 @@ impl LispState {
|
||||||
match v {
|
match v {
|
||||||
LispValue::Float(_) => t = "float",
|
LispValue::Float(_) => t = "float",
|
||||||
LispValue::Integer(_) => (),
|
LispValue::Integer(_) => (),
|
||||||
_ => return vec![LispValue::Nil]
|
_ => return Err(RuntimeError {
|
||||||
|
message: format!("Invalid argument to 'sub' (expected float or int, got {}", get_type(v))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +281,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Integer(sum)];
|
return Ok(vec![LispValue::Integer(sum)]);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -259,7 +298,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(sum)];
|
return Ok(vec![LispValue::Float(sum)]);
|
||||||
} else if let LispValue::Integer(n) = args[0] {
|
} else if let LispValue::Integer(n) = args[0] {
|
||||||
let mut sum = n as f32;
|
let mut sum = n as f32;
|
||||||
for i in 1..args.len() {
|
for i in 1..args.len() {
|
||||||
|
@ -271,7 +310,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(sum)];
|
return Ok(vec![LispValue::Float(sum)]);
|
||||||
} {
|
} {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -282,9 +321,9 @@ impl LispState {
|
||||||
|
|
||||||
add_function(&mut table, "mul", |_, args| {
|
add_function(&mut table, "mul", |_, args| {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return vec![LispValue::Nil]
|
return Ok(vec![LispValue::Nil]);
|
||||||
} else if args.len() == 1 {
|
} else if args.len() == 1 {
|
||||||
return vec![args[0].clone()];
|
return Ok(vec![args[0].clone()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut t = "int";
|
let mut t = "int";
|
||||||
|
@ -292,7 +331,9 @@ impl LispState {
|
||||||
match v {
|
match v {
|
||||||
LispValue::Float(_) => t = "float",
|
LispValue::Float(_) => t = "float",
|
||||||
LispValue::Integer(_) => (),
|
LispValue::Integer(_) => (),
|
||||||
_ => return vec![LispValue::Nil]
|
_ => return Err(RuntimeError {
|
||||||
|
message: format!("Invalid argument to 'mul' (expected float or int, got {}", get_type(v))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +348,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Integer(sum)];
|
return Ok(vec![LispValue::Integer(sum)]);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -324,7 +365,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(product)];
|
return Ok(vec![LispValue::Float(product)]);
|
||||||
} else if let LispValue::Integer(n) = args[0] {
|
} else if let LispValue::Integer(n) = args[0] {
|
||||||
let mut product = n as f32;
|
let mut product = n as f32;
|
||||||
for i in 1..args.len() {
|
for i in 1..args.len() {
|
||||||
|
@ -336,7 +377,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(product)];
|
return Ok(vec![LispValue::Float(product)]);
|
||||||
} {
|
} {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -347,9 +388,9 @@ impl LispState {
|
||||||
|
|
||||||
add_function(&mut table, "div", |_, args| {
|
add_function(&mut table, "div", |_, args| {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return vec![LispValue::Nil]
|
return Ok(vec![LispValue::Nil]);
|
||||||
} else if args.len() == 1 {
|
} else if args.len() == 1 {
|
||||||
return vec![args[0].clone()];
|
return Ok(vec![args[0].clone()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut t = "int";
|
let mut t = "int";
|
||||||
|
@ -357,7 +398,9 @@ impl LispState {
|
||||||
match v {
|
match v {
|
||||||
LispValue::Float(_) => t = "float",
|
LispValue::Float(_) => t = "float",
|
||||||
LispValue::Integer(_) => (),
|
LispValue::Integer(_) => (),
|
||||||
_ => return vec![LispValue::Nil]
|
_ => return Err(RuntimeError {
|
||||||
|
message: format!("Invalid argument to 'div' (expected float or int, got {}", get_type(v))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,7 +415,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Integer(sum)];
|
return Ok(vec![LispValue::Integer(sum)]);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -389,7 +432,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(product)];
|
return Ok(vec![LispValue::Float(product)]);
|
||||||
} else if let LispValue::Integer(n) = args[0] {
|
} else if let LispValue::Integer(n) = args[0] {
|
||||||
let mut product = n as f32;
|
let mut product = n as f32;
|
||||||
for i in 1..args.len() {
|
for i in 1..args.len() {
|
||||||
|
@ -401,7 +444,7 @@ impl LispState {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vec![LispValue::Float(product)];
|
return Ok(vec![LispValue::Float(product)]);
|
||||||
} {
|
} {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -427,11 +470,11 @@ impl LispState {
|
||||||
PreLispValue::List(list, quoted) => {
|
PreLispValue::List(list, quoted) => {
|
||||||
LispValue::List(Self::handle_prevalues(self, list), quoted)
|
LispValue::List(Self::handle_prevalues(self, list), quoted)
|
||||||
},
|
},
|
||||||
PreLispValue::LispFunction(name, instructions) => {
|
PreLispValue::LispFunction(name, arg_names, instructions) => {
|
||||||
LispValue::LispFunction(name, Self::handle_prevalues(self, instructions))
|
LispValue::LispFunction(name, arg_names, Self::handle_prevalues(self, instructions))
|
||||||
},
|
},
|
||||||
PreLispValue::Var(name) => {
|
PreLispValue::Var(name) => {
|
||||||
self.table.get(&name).unwrap_or(&LispValue::Nil).to_owned()
|
LispValue::Var(name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -439,16 +482,19 @@ impl LispState {
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_list(&mut self, list: &Vec<LispValue>, quoted: bool) -> (Vec<LispValue>, bool) {
|
fn eval_list(&mut self, env: &mut HashMap<String, LispValue>, list: &Vec<LispValue>, quoted: bool) -> Result<(Vec<LispValue>, bool), RuntimeError> {
|
||||||
if list.len() < 1 {
|
if list.len() < 1 {
|
||||||
return (vec![LispValue::List(Vec::new(), quoted)], false);
|
return Ok((vec![LispValue::List(Vec::new(), quoted)], false));
|
||||||
}
|
}
|
||||||
|
|
||||||
let list = &mut list.clone();
|
let list = &mut list.clone();
|
||||||
|
|
||||||
for i in 0..list.len() {
|
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();
|
||||||
|
}
|
||||||
if let LispValue::List(elements, quoted) = &list[i] {
|
if let LispValue::List(elements, quoted) = &list[i] {
|
||||||
let (elems, astuple) = self.eval_list(elements, *quoted);
|
if let Ok((elems, astuple)) = self.eval_list(env, elements, *quoted) {
|
||||||
if astuple {
|
if astuple {
|
||||||
list[i] = elems.get(0).unwrap_or(&LispValue::Nil).to_owned();
|
list[i] = elems.get(0).unwrap_or(&LispValue::Nil).to_owned();
|
||||||
for j in 1..elems.len() {
|
for j in 1..elems.len() {
|
||||||
|
@ -459,30 +505,75 @@ impl LispState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if quoted {
|
if quoted {
|
||||||
return (list.to_vec(), false);
|
return Ok((list.to_vec(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let LispValue::RustFunction(_name, f) = &list[0] {
|
if let LispValue::RustFunction(_name, f) = &list[0] {
|
||||||
(f(self, list[1..].to_vec()), true)
|
Ok((f(self, list[1..].to_vec())?, true))
|
||||||
} else if let LispValue::LispFunction(_name, _) = &list[0] {
|
} else if let LispValue::LispFunction(_name, _, _) = &list[0] {
|
||||||
(self.call_lisp_func(&list[0], list[1..].to_vec()), true)
|
Ok((self.call_lisp_func(env, &list[0], list[1..].to_vec())?, true))
|
||||||
} else {
|
} else {
|
||||||
(list.to_vec(), false)
|
Ok((list.to_vec(), false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_lisp_func(&mut self, f: &LispValue, args: Vec<LispValue>) -> Vec<LispValue> {
|
fn call_lisp_func(&mut self, env: &mut HashMap<String, LispValue>, f: &LispValue, args: Vec<LispValue>) -> Result<Vec<LispValue>, RuntimeError> {
|
||||||
todo!("Calling lisp function {} with args {:?}", f, args)
|
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 (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());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&mut self, instructions: Vec<PreLispValue>) {
|
let mut out = Vec::new();
|
||||||
|
for l in instructions {
|
||||||
|
if let LispValue::List(elements, quoted) = l {
|
||||||
|
let (values, astuple) = self.eval_list(env, &elements, *quoted)?;
|
||||||
|
if values.len() > 0 && values[0] != LispValue::Nil {
|
||||||
|
if astuple {
|
||||||
|
for v in values {
|
||||||
|
out.push(v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.push(values.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execute(&mut self, instructions: Vec<PreLispValue>) -> Result<Vec<LispValue>, RuntimeError> {
|
||||||
let instructions = Self::handle_prevalues(self, instructions);
|
let instructions = Self::handle_prevalues(self, instructions);
|
||||||
|
|
||||||
|
let mut outs = Vec::new();
|
||||||
|
|
||||||
|
let mut env = HashMap::new();
|
||||||
|
|
||||||
for val in instructions {
|
for val in instructions {
|
||||||
if let LispValue::List(elements, quoted) = val {
|
if let LispValue::List(elements, quoted) = val {
|
||||||
self.eval_list(&elements, quoted);
|
let (vals, astuple) = self.eval_list(&mut env, &elements, quoted)?;
|
||||||
|
if astuple {
|
||||||
|
for val in vals {
|
||||||
|
outs.push(val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outs.push(vals.into())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outs.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(outs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub enum PreLispValue {
|
||||||
Integer(i32),
|
Integer(i32),
|
||||||
Float(f32),
|
Float(f32),
|
||||||
List(Vec<PreLispValue>, bool), // Values, Quoted
|
List(Vec<PreLispValue>, bool), // Values, Quoted
|
||||||
LispFunction(String, Vec<PreLispValue>),
|
LispFunction(String, Vec<String>, Vec<PreLispValue>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PreLispValue {
|
impl fmt::Display for PreLispValue {
|
||||||
|
@ -101,7 +101,7 @@ impl fmt::Display for PreLispValue {
|
||||||
match self {
|
match self {
|
||||||
PreLispValue::Nil => write!(f, "nil"),
|
PreLispValue::Nil => write!(f, "nil"),
|
||||||
PreLispValue::String(str) => write!(f, "{}", str),
|
PreLispValue::String(str) => write!(f, "{}", str),
|
||||||
PreLispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name),
|
PreLispValue::LispFunction(name, _, _) => write!(f, "<'{}': Lisp Function>", name),
|
||||||
PreLispValue::Integer(num) => write!(f, "{}", num),
|
PreLispValue::Integer(num) => write!(f, "{}", num),
|
||||||
PreLispValue::Float(num) => write!(f, "{}", num),
|
PreLispValue::Float(num) => write!(f, "{}", num),
|
||||||
_ => todo!()
|
_ => todo!()
|
||||||
|
|
|
@ -118,6 +118,8 @@ impl fmt::Display for TokenizerError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for TokenizerError {}
|
||||||
|
|
||||||
pub struct Tokenizer {
|
pub struct Tokenizer {
|
||||||
code: String,
|
code: String,
|
||||||
line: u64,
|
line: u64,
|
||||||
|
|
Reference in a new issue