Compare commits

..

No commits in common. "bf3e784b423ac948930b8e611f955af8914220dadeb9ce9b4b4ad34780df6fd8" and "66e7ab5b219d0961fb4032c7a57c822c2a2a29b092a2f19930427af98f559cc8" have entirely different histories.

5 changed files with 99 additions and 183 deletions

View file

@ -1,6 +1,6 @@
use std::{collections::HashMap, fmt}; use std::collections::HashMap;
use crate::PreLispValue; use crate::{OpCode, LispValue};
pub struct LispState { pub struct LispState {
table: HashMap<String, LispValue>, table: HashMap<String, LispValue>,
@ -10,54 +10,6 @@ fn add_function<T: Into<String> + Clone>(table: &mut HashMap<String, LispValue>,
table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func)); table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func));
} }
#[derive(Debug, Clone)]
pub enum LispValue {
Nil,
String(String),
Integer(i32),
Float(f32),
List(Vec<LispValue>, bool),
LispFunction(String, Vec<LispValue>),
RustFunction(String, fn(Vec<LispValue>) -> Vec<LispValue>),
}
impl fmt::Display for LispValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LispValue::Nil => write!(f, "nil"),
LispValue::String(str) => write!(f, "{}", str),
LispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name),
LispValue::RustFunction(name, _) => write!(f, "<'{}': Rust Function>", name),
LispValue::Integer(num) => write!(f, "{}", num),
LispValue::Float(num) => write!(f, "{}", num),
val => {
write!(f, "{}", format!("{:?}", val))
}
}
}
}
impl From<&str> for LispValue {
fn from(value: &str) -> Self {
LispValue::String(value.to_string())
}
}
impl From<String> for LispValue {
fn from(value: String) -> Self {
LispValue::String(value)
}
}
impl From<i32> for LispValue {
fn from(value: i32) -> Self {
LispValue::Integer(value)
}
}
impl From<f32> for LispValue {
fn from(value: f32) -> Self {
LispValue::Float(value)
}
}
impl LispState { impl LispState {
pub fn new() -> LispState { pub fn new() -> LispState {
let mut table = HashMap::new(); let mut table = HashMap::new();
@ -329,73 +281,47 @@ impl LispState {
} }
} }
fn handle_prevalues(&self, input: Vec<PreLispValue>) -> Vec<LispValue> { fn do_call(&self, opcode: &OpCode) -> Vec<LispValue> {
let mut out = Vec::new(); if let OpCode::Call(func, args) = opcode {
let f = self.table.get(func).unwrap();
for v in input { let mut args: Vec<LispValue> = args.clone();
out.push(match v { for i in 0..args.len() {
PreLispValue::Nil => LispValue::Nil, let arg = &args[i];
PreLispValue::String(str) => LispValue::String(str), if let LispValue::Eval(OpCode::Exp(opcodes)) = arg {
PreLispValue::Integer(num) => LispValue::Integer(num), if opcodes.len() < 1 {
PreLispValue::Float(num) => LispValue::Float(num), args[i] = LispValue::Nil;
PreLispValue::List(list, quoted) => { continue;
LispValue::List(Self::handle_prevalues(self, list), quoted) }
},
PreLispValue::LispFunction(name, instructions) => { let call_opcode = opcodes.last().unwrap();
LispValue::LispFunction(name, Self::handle_prevalues(self, instructions)) let mut res = self.do_call(call_opcode);
}, args.remove(i);
PreLispValue::Var(name) => { for j in 0..res.len() {
self.table.get(&name).unwrap_or(&LispValue::Nil).to_owned() args.insert(i + j, res.remove(0));
}
})
}
out
}
fn eval_list(list: &Vec<LispValue>, quoted: bool) -> (Vec<LispValue>, bool) {
if list.len() < 1 {
return (vec![LispValue::List(Vec::new(), quoted)], false);
}
let list = &mut list.clone();
for i in 0..list.len() {
if let LispValue::List(elements, quoted) = &list[i] {
let (elems, astuple) = Self::eval_list(elements, *quoted);
if astuple {
list[i] = elems.get(0).unwrap_or(&LispValue::Nil).to_owned();
for j in 1..elems.len() {
list.insert(i, elems[j].to_owned());
} }
} else {
list[i] = LispValue::List(elems, *quoted);
} }
} }
} if let LispValue::RustFunction(_, f) = f {
return f(args.to_vec());
} else {
todo!();
}
if quoted {
return (list.to_vec(), false);
}
if let LispValue::RustFunction(_name, f) = &list[0] {
(f(list[1..].to_vec()), true)
} else if let LispValue::LispFunction(_name, ins) = &list[0] {
(Self::call_lisp_func(&list[0], list[1..].to_vec()), true)
} else { } else {
(list.to_vec(), false) panic!("Bad OpCode: expected OpCode::Call")
} }
} }
fn call_lisp_func(f: &LispValue, args: Vec<LispValue>) -> Vec<LispValue> { pub fn execute(&self, instructions: Vec<OpCode>) {
todo!() for op in instructions {
} match op {
OpCode::Call(func, args) => {
pub fn execute(&self, instructions: Vec<PreLispValue>) { self.do_call(&OpCode::Call(func, args));
let instructions = Self::handle_prevalues(self, instructions); },
for val in instructions { OpCode::Exp(ins) => {
if let LispValue::List(elements, quoted) = val { self.execute(ins);
Self::eval_list(&elements, quoted); }
} }
} }
} }

View file

@ -9,7 +9,6 @@ use executor::*;
fn main() { fn main() {
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 = match tokenizer.tokenize() { let tokens = match tokenizer.tokenize() {
Ok(tokens) => tokens, Ok(tokens) => tokens,

View file

@ -3,53 +3,54 @@ use std::fmt;
use crate::Token; use crate::Token;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum PreLispValue { pub enum LispValue {
Nil, Nil,
String(String), String(String),
Var(String),
Integer(i32), Integer(i32),
Float(f32), Float(f32),
List(Vec<PreLispValue>, bool), // Values, Quoted LispFunction(String, Vec<OpCode>),
LispFunction(String, Vec<PreLispValue>), RustFunction(String, fn(Vec<LispValue>) -> Vec<LispValue>),
Ref(String),
Eval(OpCode)
} }
impl fmt::Display for PreLispValue { impl fmt::Display for LispValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
PreLispValue::Nil => write!(f, "nil"), LispValue::Nil => write!(f, "nil"),
PreLispValue::String(str) => write!(f, "{}", str), LispValue::String(str) => write!(f, "{}", str),
PreLispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name), LispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name),
PreLispValue::Integer(num) => write!(f, "{}", num), LispValue::RustFunction(name, _) => write!(f, "<'{}': Rust Function>", name),
PreLispValue::Float(num) => write!(f, "{}", num), LispValue::Integer(num) => write!(f, "{}", num),
LispValue::Float(num) => write!(f, "{}", num),
LispValue::Ref(name) => write!(f, "<'{}': Reference>", name),
_ => todo!() _ => todo!()
} }
} }
} }
impl From<&str> for PreLispValue { impl From<&str> for LispValue {
fn from(value: &str) -> Self { fn from(value: &str) -> Self {
PreLispValue::String(value.to_string()) LispValue::String(value.to_string())
} }
} }
impl From<String> for PreLispValue {
impl From<String> for LispValue {
fn from(value: String) -> Self { fn from(value: String) -> Self {
PreLispValue::String(value) LispValue::String(value)
} }
} }
impl From<i32> for PreLispValue {
impl From<i32> for LispValue {
fn from(value: i32) -> Self { fn from(value: i32) -> Self {
PreLispValue::Integer(value) LispValue::Integer(value)
} }
} }
impl From<f32> for PreLispValue {
fn from(value: f32) -> Self { #[derive(Debug, Clone)]
PreLispValue::Float(value) pub enum OpCode {
} Call(String, Vec<LispValue>),
} Exp(Vec<OpCode>)
impl From<Vec<PreLispValue>> for PreLispValue {
fn from(value: Vec<PreLispValue>) -> Self {
PreLispValue::List(value, false)
}
} }
// TODO: Handle failure // TODO: Handle failure
@ -82,64 +83,60 @@ fn read_exp(open_paren_idx: usize, tokens: &Vec<Token>) -> Option<(Vec<Token>, u
None None
} }
fn parse_exp(tokens: Vec<Token>, quoted: bool) -> PreLispValue { fn parse_exp(tokens: Vec<Token>) -> Vec<OpCode> {
let mut values = Vec::new(); let mut opcodes = Vec::new();
if tokens.len() < 1 { if tokens.len() < 1 {
return PreLispValue::List(values, false); return opcodes;
} }
let mut quote_next_list = false; if let Token::Identifier(name) = &tokens[0] {
let mut unquote_next_list = false; let mut args = Vec::new();
let mut i = 0; let mut i = 1;
while i < tokens.len() { while i < tokens.len() {
let tkn = &tokens[i]; let tkn = &tokens[i];
match tkn { match tkn {
Token::Quote => { Token::OpenParen => {
quote_next_list = true; let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap();
}, args.push(LispValue::Eval(OpCode::Exp(parse_exp(tkns))));
Token::Unquote => { i = close_paren_idx;
unquote_next_list = true; },
Token::Identifier(name) => {
args.push(LispValue::Ref(name.to_owned()));
},
Token::Integer(num) => {
args.push(LispValue::Integer(*num));
},
Token::Float(num) => {
args.push(LispValue::Float(*num));
},
Token::String(str) => {
args.push(LispValue::String(str.to_owned()));
},
Token::CloseParen => {
panic!("Unexpected closing parenthesis");
},
} }
Token::OpenParen => {
let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap(); i += 1;
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) => {
values.push(PreLispValue::Var(name.to_owned()));
},
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;
opcodes.push(OpCode::Call(name.to_owned(), args))
} }
PreLispValue::List(values, quoted) opcodes
} }
pub fn parse(tokens: Vec<Token>) -> Vec<PreLispValue> { pub fn parse(tokens: Vec<Token>) -> Vec<OpCode> {
let mut values = Vec::new(); let mut opcodes = Vec::new();
let mut i = 0; let mut i = 0;
while i < tokens.len() { while i < tokens.len() {
match &tokens[i] { match &tokens[i] {
Token::OpenParen => { Token::OpenParen => {
let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap(); let (tkns, close_paren_idx) = read_exp(i, &tokens).unwrap();
values.push(parse_exp(tkns, false)); opcodes.push(OpCode::Exp(parse_exp(tkns)));
i = close_paren_idx; i = close_paren_idx;
} }
tkn => { tkn => {
@ -150,5 +147,5 @@ pub fn parse(tokens: Vec<Token>) -> Vec<PreLispValue> {
i += 1; i += 1;
} }
values opcodes
} }

View file

@ -11,4 +11,4 @@
; LispValue::Float(1.0), ; LispValue::Float(1.0),
; LispValue::Integer(3) ; LispValue::Integer(3)
; }) ; })
; }) ; })

View file

@ -4,8 +4,6 @@ use std::fmt;
pub enum Token { pub enum Token {
OpenParen, OpenParen,
CloseParen, CloseParen,
Quote,
Unquote,
Identifier(String), Identifier(String),
String(String), String(String),
Integer(i32), Integer(i32),
@ -115,8 +113,6 @@ impl Tokenizer {
tokens.push(Token::Integer(self.storage.iter().collect::<String>().parse().unwrap())); tokens.push(Token::Integer(self.storage.iter().collect::<String>().parse().unwrap()));
} }
self.is_float = false;
self.storage.clear(); self.storage.clear();
} else { } else {
if char == '.' { if char == '.' {
@ -168,8 +164,6 @@ impl Tokenizer {
self.reading_string = true; self.reading_string = true;
self.storage.clear(); self.storage.clear();
}, },
'\'' => tokens.push(Token::Quote),
',' => tokens.push(Token::Unquote),
c => { c => {
if c.is_alphabetic() { if c.is_alphabetic() {
self.reading_identifier = true; self.reading_identifier = true;