Small update
This commit is contained in:
parent
66e7ab5b21
commit
b67ac42cee
3 changed files with 120 additions and 63 deletions
|
@ -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();
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in a new issue