Functionality

This commit is contained in:
Apache 2024-06-20 16:55:21 -05:00
parent b67ac42cee
commit bf3e784b42
Signed by: apache
GPG key ID: 6B10F3EAF14F4C77
5 changed files with 70 additions and 43 deletions

View file

@ -1,6 +1,6 @@
use std::{collections::HashMap, fmt}; use std::{collections::HashMap, fmt};
use crate::{OpCode, PreLispValue}; use crate::PreLispValue;
pub struct LispState { pub struct LispState {
table: HashMap<String, LispValue>, table: HashMap<String, LispValue>,
@ -16,8 +16,8 @@ pub enum LispValue {
String(String), String(String),
Integer(i32), Integer(i32),
Float(f32), Float(f32),
List(Vec<LispValue>), List(Vec<LispValue>, bool),
LispFunction(String, Vec<OpCode>), LispFunction(String, Vec<LispValue>),
RustFunction(String, fn(Vec<LispValue>) -> Vec<LispValue>), RustFunction(String, fn(Vec<LispValue>) -> Vec<LispValue>),
} }
@ -329,47 +329,73 @@ impl LispState {
} }
} }
fn do_call(&self, opcode: &OpCode) -> Vec<LispValue> { fn handle_prevalues(&self, input: Vec<PreLispValue>) -> Vec<LispValue> {
if let OpCode::Call(func, args) = opcode { let mut out = Vec::new();
let f = self.table.get(func).unwrap();
let mut args: Vec<LispValue> = args.clone(); for v in input {
for i in 0..args.len() { out.push(match v {
let arg = &args[i]; PreLispValue::Nil => LispValue::Nil,
if let LispValue::Eval(OpCode::Exp(opcodes)) = arg { PreLispValue::String(str) => LispValue::String(str),
if opcodes.len() < 1 { PreLispValue::Integer(num) => LispValue::Integer(num),
args[i] = LispValue::Nil; PreLispValue::Float(num) => LispValue::Float(num),
continue; PreLispValue::List(list, quoted) => {
} LispValue::List(Self::handle_prevalues(self, list), quoted)
let call_opcode = opcodes.last().unwrap();
let mut res = self.do_call(call_opcode);
args.remove(i);
for j in 0..res.len() {
args.insert(i + j, res.remove(0));
}
}
}
if let LispValue::RustFunction(_, f) = f {
return f(args.to_vec());
} else {
todo!();
}
} else {
panic!("Bad OpCode: expected OpCode::Call")
}
}
pub fn execute(&self, instructions: Vec<OpCode>) {
for op in instructions {
match op {
OpCode::Call(func, args) => {
self.do_call(&OpCode::Call(func, args));
}, },
OpCode::Exp(ins) => { PreLispValue::LispFunction(name, instructions) => {
self.execute(ins); LispValue::LispFunction(name, Self::handle_prevalues(self, instructions))
} },
PreLispValue::Var(name) => {
self.table.get(&name).unwrap_or(&LispValue::Nil).to_owned()
}
})
}
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 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 {
(list.to_vec(), false)
}
}
fn call_lisp_func(f: &LispValue, args: Vec<LispValue>) -> Vec<LispValue> {
todo!()
}
pub fn execute(&self, instructions: Vec<PreLispValue>) {
let instructions = Self::handle_prevalues(self, instructions);
for val in instructions {
if let LispValue::List(elements, quoted) = val {
Self::eval_list(&elements, quoted);
} }
} }
} }

View file

@ -9,6 +9,7 @@ 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

@ -10,8 +10,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<LispValue>), LispFunction(String, Vec<PreLispValue>),
RustFunction(String, fn(Vec<PreLispValue>) -> Vec<PreLispValue>),
} }
impl fmt::Display for PreLispValue { impl fmt::Display for PreLispValue {
@ -20,7 +19,6 @@ impl fmt::Display for PreLispValue {
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::RustFunction(name, _) => write!(f, "<'{}': Rust 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!()
@ -94,7 +92,7 @@ fn parse_exp(tokens: Vec<Token>, quoted: bool) -> PreLispValue {
let mut quote_next_list = false; let mut quote_next_list = false;
let mut unquote_next_list = false; let mut unquote_next_list = false;
let mut i = 1; let mut i = 0;
while i < tokens.len() { while i < tokens.len() {
let tkn = &tokens[i]; let tkn = &tokens[i];
match tkn { match tkn {
@ -133,15 +131,15 @@ fn parse_exp(tokens: Vec<Token>, quoted: bool) -> PreLispValue {
PreLispValue::List(values, quoted) PreLispValue::List(values, quoted)
} }
pub fn parse(tokens: Vec<Token>) -> Vec<OpCode> { pub fn parse(tokens: Vec<Token>) -> Vec<PreLispValue> {
let mut opcodes = Vec::new(); let mut values = 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();
opcodes.push(parse_exp(tkns, false)); values.push(parse_exp(tkns, false));
i = close_paren_idx; i = close_paren_idx;
} }
tkn => { tkn => {
@ -152,5 +150,5 @@ pub fn parse(tokens: Vec<Token>) -> Vec<OpCode> {
i += 1; i += 1;
} }
opcodes values
} }

View file

@ -115,6 +115,8 @@ 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 == '.' {