Small update

This commit is contained in:
Apache 2024-06-16 14:29:46 -05:00
parent 66e7ab5b21
commit b67ac42cee
Signed by: apache
GPG key ID: 6B10F3EAF14F4C77
3 changed files with 120 additions and 63 deletions

View file

@ -1,6 +1,6 @@
use std::collections::HashMap; use std::{collections::HashMap, fmt};
use crate::{OpCode, LispValue}; use crate::{OpCode, PreLispValue};
pub struct LispState { pub struct LispState {
table: HashMap<String, LispValue>, table: HashMap<String, LispValue>,
@ -10,6 +10,54 @@ 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>),
LispFunction(String, Vec<OpCode>),
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();

View file

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

View file

@ -4,6 +4,8 @@ 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),
@ -164,6 +166,8 @@ 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;