Big things coming
This commit is contained in:
		
							parent
							
								
									4020536ae6
								
							
						
					
					
						commit
						d9bea76666
					
				
							
								
								
									
										183
									
								
								src/code_gen.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/code_gen.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,183 @@
 | 
				
			||||||
 | 
					use std::{collections::HashMap, ops::AddAssign};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use color_eyre::eyre::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    lexer::Keyword,
 | 
				
			||||||
 | 
					    parser::{LispAtom, SExpression},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
				
			||||||
 | 
					enum InstructionFrom {
 | 
				
			||||||
 | 
					    ROM,
 | 
				
			||||||
 | 
					    RAM,
 | 
				
			||||||
 | 
					    ALU,
 | 
				
			||||||
 | 
					    RegisterC,
 | 
				
			||||||
 | 
					    RegisterD,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RegisterSP,
 | 
				
			||||||
 | 
					    RegisterSB,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
				
			||||||
 | 
					enum InstructionTo {
 | 
				
			||||||
 | 
					    JumpAddressUpper,
 | 
				
			||||||
 | 
					    JumpAddressLower,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Jump,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RamAddressUpper,
 | 
				
			||||||
 | 
					    RamAddressLower,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RAM,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Flags,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RegisterA,
 | 
				
			||||||
 | 
					    RegisterB,
 | 
				
			||||||
 | 
					    RegisterC,
 | 
				
			||||||
 | 
					    RegisterD,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RegisterSP,
 | 
				
			||||||
 | 
					    RegisterSB,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 | 
				
			||||||
 | 
					struct Command {
 | 
				
			||||||
 | 
					    data_from: InstructionFrom,
 | 
				
			||||||
 | 
					    data_to: InstructionTo,
 | 
				
			||||||
 | 
					    data: i8,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub struct Scope {
 | 
				
			||||||
 | 
					    variables: Vec<String>,
 | 
				
			||||||
 | 
					    stack_position: usize,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub struct EightBitLang {
 | 
				
			||||||
 | 
					    instructions: Vec<Command>,
 | 
				
			||||||
 | 
					    labels: Option<HashMap<String, usize>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait GenerateCode {
 | 
				
			||||||
 | 
					    fn to_code(self, codegen_scope: &mut Scope) -> Result<EightBitLang, Self::Error>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        Self: Sized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl GenerateCode for SExpression {
 | 
				
			||||||
 | 
					    fn to_code(self, codegen_scope: &mut Scope) -> Result<EightBitLang, Self::Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            SExpression::Atom(a) => a.to_code(codegen_scope),
 | 
				
			||||||
 | 
					            _ => todo!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl GenerateCode for LispAtom {
 | 
				
			||||||
 | 
					    fn to_code(self, codegen_scope: &mut Scope) -> Result<EightBitLang, Self::Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            LispAtom::Keyword(keyword) => keyword.to_code(codegen_scope),
 | 
				
			||||||
 | 
					            LispAtom::Integer(number) => number.to_code(codegen_scope),
 | 
				
			||||||
 | 
					            _ => todo!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl GenerateCode for isize {
 | 
				
			||||||
 | 
					    fn to_code(self, codegen_scope: &mut Scope) -> Result<EightBitLang, Self::Error> {
 | 
				
			||||||
 | 
					        if let Err(_e) = i8::try_from(self) {
 | 
				
			||||||
 | 
					            return Err(Error::msg("Yo integer too big brah"));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Ok(EightBitLang::push(self as i8, codegen_scope));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl GenerateCode for Keyword {
 | 
				
			||||||
 | 
					    fn to_code(self, _codegen_scope: &mut Scope) -> Result<EightBitLang, Self::Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            _ => todo!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Error = Error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AddAssign for EightBitLang {
 | 
				
			||||||
 | 
					    fn add_assign(&mut self, mut rhs: Self) {
 | 
				
			||||||
 | 
					        let mut labels = self.labels.clone().unwrap();
 | 
				
			||||||
 | 
					        if rhs.labels.is_some() || self.labels.is_some() {
 | 
				
			||||||
 | 
					            if self.labels.is_none() {
 | 
				
			||||||
 | 
					                labels = rhs.labels.unwrap();
 | 
				
			||||||
 | 
					            } else if rhs.labels.is_none() {
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                labels = HashMap::new();
 | 
				
			||||||
 | 
					                for label in rhs.labels.unwrap() {
 | 
				
			||||||
 | 
					                    labels.insert(label.0, label.1 + self.instructions.len());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            self.labels = Some(labels);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.instructions.append(&mut rhs.instructions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<Command> for EightBitLang {
 | 
				
			||||||
 | 
					    fn from(value: Command) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            instructions: vec![value],
 | 
				
			||||||
 | 
					            labels: None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl EightBitLang {
 | 
				
			||||||
 | 
					    fn push(value: i8, codegen_scope: &mut Scope) -> Self {
 | 
				
			||||||
 | 
					        use InstructionFrom as IF;
 | 
				
			||||||
 | 
					        use InstructionTo as IT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        codegen_scope.stack_position += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut commands = Vec::new();
 | 
				
			||||||
 | 
					        commands.push(Command::new(IF::RegisterSP, IT::RegisterA, 0x00));
 | 
				
			||||||
 | 
					        commands.push(Command::new(IF::ROM, IT::RegisterB, 0x01));
 | 
				
			||||||
 | 
					        commands.push(Command::new(IF::ALU, IT::RegisterSP, 0x00));
 | 
				
			||||||
 | 
					        commands.push(Command::new(IF::RegisterSP, IT::RamAddressLower, 0x00));
 | 
				
			||||||
 | 
					        commands.push(Command::new(IF::ROM, IT::RAM, value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            instructions: commands,
 | 
				
			||||||
 | 
					            labels: None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Command {
 | 
				
			||||||
 | 
					    fn new(data_from: InstructionFrom, data_to: InstructionTo, data: i8) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            data_from,
 | 
				
			||||||
 | 
					            data_to,
 | 
				
			||||||
 | 
					            data,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Scope {
 | 
				
			||||||
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            variables: Vec::new(),
 | 
				
			||||||
 | 
					            stack_position: 0,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										253
									
								
								src/ir.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/ir.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,253 @@
 | 
				
			||||||
 | 
					use std::{
 | 
				
			||||||
 | 
					    collections::HashMap,
 | 
				
			||||||
 | 
					    ops::{Add, AddAssign},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use color_eyre::eyre::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    lexer::{Keyword, Macro},
 | 
				
			||||||
 | 
					    parser::{LispAtom, SExpression, NIL},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub struct IRepr {
 | 
				
			||||||
 | 
					    commands: Vec<Command>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					enum Command {
 | 
				
			||||||
 | 
					    PushInt(isize),
 | 
				
			||||||
 | 
					    PushSum,
 | 
				
			||||||
 | 
					    PopR1,
 | 
				
			||||||
 | 
					    PopR2,
 | 
				
			||||||
 | 
					    PopOut,
 | 
				
			||||||
 | 
					    PushRelative(usize),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Enter,
 | 
				
			||||||
 | 
					    Leave,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub struct Scope {
 | 
				
			||||||
 | 
					    stack_position: usize,
 | 
				
			||||||
 | 
					    stack_positions: Vec<usize>,
 | 
				
			||||||
 | 
					    variables: HashMap<String, usize>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn generate_code(expressions: Vec<SExpression>) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					    let mut scope = Scope {
 | 
				
			||||||
 | 
					        stack_position: 0,
 | 
				
			||||||
 | 
					        stack_positions: vec![],
 | 
				
			||||||
 | 
					        variables: HashMap::new(),
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut sum = IRepr::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for expression in expressions {
 | 
				
			||||||
 | 
					        sum += expression.to_irepr(&mut scope)?
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(sum)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait ToIR {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope) -> Result<IRepr, Error>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait ToIRMacro {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope, expressions: SExpression) -> Result<IRepr, Error>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ToIR for SExpression {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					        Ok(match self {
 | 
				
			||||||
 | 
					            Self::Atom(a) => a.to_irepr(ir_scope)?,
 | 
				
			||||||
 | 
					            Self::Pair(a, b) => match *a {
 | 
				
			||||||
 | 
					                Self::Atom(LispAtom::Macro(m)) => m.to_irepr(ir_scope, *b)?,
 | 
				
			||||||
 | 
					                a => b.to_irepr(ir_scope)? + a.to_irepr(ir_scope)?,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ToIR for LispAtom {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Integer(number) => number.to_irepr(ir_scope),
 | 
				
			||||||
 | 
					            Self::Keyword(keyword) => keyword.to_irepr(ir_scope),
 | 
				
			||||||
 | 
					            Self::Identifier(identifier) => {
 | 
				
			||||||
 | 
					                if !ir_scope.variables.contains_key(&identifier) {
 | 
				
			||||||
 | 
					                    todo!();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                ir_scope.stack_position += 1;
 | 
				
			||||||
 | 
					                Ok(IRepr {
 | 
				
			||||||
 | 
					                    commands: vec![
 | 
				
			||||||
 | 
					                        Command::PushRelative(ir_scope.variables[&identifier]),
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => todo!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ToIR for Keyword {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Nil => Ok(IRepr { commands: vec![] }),
 | 
				
			||||||
 | 
					            Self::Add => {
 | 
				
			||||||
 | 
					                ir_scope.stack_position -= 1;
 | 
				
			||||||
 | 
					                Ok(IRepr {
 | 
				
			||||||
 | 
					                    commands: vec![Command::PopR1, Command::PopR2, Command::PushSum],
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Self::Out => {
 | 
				
			||||||
 | 
					                ir_scope.stack_position -= 1;
 | 
				
			||||||
 | 
					                Ok(IRepr {
 | 
				
			||||||
 | 
					                    commands: vec![Command::PopOut],
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ToIR for isize {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					        ir_scope.stack_position += 1;
 | 
				
			||||||
 | 
					        return Ok(Command::PushInt(self).to_irepr());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ToIRMacro for Macro {
 | 
				
			||||||
 | 
					    fn to_irepr(self, ir_scope: &mut Scope, expression: SExpression) -> Result<IRepr, Error> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Let => {
 | 
				
			||||||
 | 
					                println!("Parsing a let expression");
 | 
				
			||||||
 | 
					                let (mut varlist, mut body) = match expression {
 | 
				
			||||||
 | 
					                    SExpression::Atom(_a) => todo!(),
 | 
				
			||||||
 | 
					                    SExpression::Pair(a, b) => (*a, *b),
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let mut commands = IRepr {
 | 
				
			||||||
 | 
					                    commands: vec![Command::Enter],
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ir_scope.stack_positions.push(ir_scope.stack_position);
 | 
				
			||||||
 | 
					                ir_scope.stack_position = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                while varlist != NIL {
 | 
				
			||||||
 | 
					                    let var = match varlist {
 | 
				
			||||||
 | 
					                        SExpression::Atom(_) => panic!("Let defined wrong"),
 | 
				
			||||||
 | 
					                        SExpression::Pair(a, b) => {
 | 
				
			||||||
 | 
					                            varlist = *b;
 | 
				
			||||||
 | 
					                            *a
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    match var {
 | 
				
			||||||
 | 
					                        SExpression::Atom(a) => {
 | 
				
			||||||
 | 
					                            let name = match a {
 | 
				
			||||||
 | 
					                                LispAtom::Identifier(ident) => ident,
 | 
				
			||||||
 | 
					                                _ => todo!(),
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					                            ir_scope.variables.insert(name, ir_scope.stack_position);
 | 
				
			||||||
 | 
					                            ir_scope.stack_position += 1;
 | 
				
			||||||
 | 
					                            commands += Command::PushInt(0);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        SExpression::Pair(name, car) => {
 | 
				
			||||||
 | 
					                            let name = match *name {
 | 
				
			||||||
 | 
					                                SExpression::Atom(a) => match a {
 | 
				
			||||||
 | 
					                                    LispAtom::Identifier(ident) => ident,
 | 
				
			||||||
 | 
					                                    _ => todo!(),
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                _ => todo!(),
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					                            commands += car.to_irepr(ir_scope)?;
 | 
				
			||||||
 | 
					                            ir_scope.variables.insert(name, ir_scope.stack_position);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                dbg!(&commands);
 | 
				
			||||||
 | 
					                dbg!(&ir_scope);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                while body != NIL {
 | 
				
			||||||
 | 
					                    match body {
 | 
				
			||||||
 | 
					                        SExpression::Atom(_a) => todo!(),
 | 
				
			||||||
 | 
					                        SExpression::Pair(a, b) => {
 | 
				
			||||||
 | 
					                            commands += a.to_irepr(ir_scope)?;
 | 
				
			||||||
 | 
					                            body = *b;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                dbg!(&commands);
 | 
				
			||||||
 | 
					                dbg!(&ir_scope);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                commands += Command::Leave;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                todo!()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => todo!(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Command {
 | 
				
			||||||
 | 
					    fn to_irepr(self) -> IRepr {
 | 
				
			||||||
 | 
					        IRepr {
 | 
				
			||||||
 | 
					            commands: vec![self],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl IRepr {
 | 
				
			||||||
 | 
					    fn new() -> IRepr {
 | 
				
			||||||
 | 
					        return IRepr { commands: vec![] };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AddAssign for IRepr {
 | 
				
			||||||
 | 
					    fn add_assign(&mut self, rhs: Self) {
 | 
				
			||||||
 | 
					        self.commands.extend(rhs.commands);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AddAssign<Vec<Command>> for IRepr {
 | 
				
			||||||
 | 
					    fn add_assign(&mut self, rhs: Vec<Command>) {
 | 
				
			||||||
 | 
					        self.commands.extend(rhs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Add<Vec<Command>> for IRepr {
 | 
				
			||||||
 | 
					    fn add(mut self, rhs: Vec<Command>) -> Self::Output {
 | 
				
			||||||
 | 
					        self += rhs;
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Output = Self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AddAssign<Command> for IRepr {
 | 
				
			||||||
 | 
					    fn add_assign(&mut self, rhs: Command) {
 | 
				
			||||||
 | 
					        self.commands.push(rhs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Add<Command> for IRepr {
 | 
				
			||||||
 | 
					    fn add(mut self, rhs: Command) -> Self::Output {
 | 
				
			||||||
 | 
					        self += rhs;
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Output = Self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Add for IRepr {
 | 
				
			||||||
 | 
					    fn add(mut self, rhs: Self) -> Self::Output {
 | 
				
			||||||
 | 
					        self += rhs;
 | 
				
			||||||
 | 
					        return self;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type Output = Self;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										108
									
								
								src/lexer.rs
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								src/lexer.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,27 +1,43 @@
 | 
				
			||||||
use std::str::FromStr;
 | 
					use std::{fmt::Display, str::FromStr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use thiserror::Error;
 | 
					use thiserror::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, PartialEq, Eq, Clone)]
 | 
				
			||||||
pub enum TokenType {
 | 
					pub enum TokenType {
 | 
				
			||||||
    OpenParantheses,
 | 
					    OpenParantheses,
 | 
				
			||||||
    ClosedParantheses,
 | 
					    ClosedParantheses,
 | 
				
			||||||
    Integer(usize),
 | 
					    Dot,
 | 
				
			||||||
 | 
					    Integer(isize),
 | 
				
			||||||
    String(String),
 | 
					    String(String),
 | 
				
			||||||
    Identifier(String),
 | 
					    Identifier(String),
 | 
				
			||||||
 | 
					    Keyword(Keyword),
 | 
				
			||||||
 | 
					    Macro(Macro),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
pub struct Token {
 | 
					pub struct Token {
 | 
				
			||||||
    row: usize,
 | 
					    pub row: usize,
 | 
				
			||||||
    col: usize,
 | 
					    pub col: usize,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    token_type: TokenType,
 | 
					    pub token_type: TokenType,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct TokenString {
 | 
					pub struct TokenString {
 | 
				
			||||||
    tokens: Vec<Token>,
 | 
					    pub tokens: Vec<Token>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Clone, Copy)]
 | 
				
			||||||
 | 
					pub enum Keyword {
 | 
				
			||||||
 | 
					    Add,
 | 
				
			||||||
 | 
					    Out,
 | 
				
			||||||
 | 
					    Nil,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq, Eq, Clone, Copy)]
 | 
				
			||||||
 | 
					pub enum Macro {
 | 
				
			||||||
 | 
					    Let,
 | 
				
			||||||
 | 
					    Defun,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
| 
						 | 
					@ -38,9 +54,9 @@ struct UnfinishedTokenString {
 | 
				
			||||||
#[derive(Error, Debug)]
 | 
					#[derive(Error, Debug)]
 | 
				
			||||||
#[error("Syntax error at: {row}:{col}. {message}")]
 | 
					#[error("Syntax error at: {row}:{col}. {message}")]
 | 
				
			||||||
pub struct LexerError {
 | 
					pub struct LexerError {
 | 
				
			||||||
    row: usize,
 | 
					    pub row: usize,
 | 
				
			||||||
    col: usize,
 | 
					    pub col: usize,
 | 
				
			||||||
    message: String,
 | 
					    pub message: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FromStr for TokenString {
 | 
					impl FromStr for TokenString {
 | 
				
			||||||
| 
						 | 
					@ -51,7 +67,7 @@ impl FromStr for TokenString {
 | 
				
			||||||
            tokens: Vec::new(),
 | 
					            tokens: Vec::new(),
 | 
				
			||||||
            eof: false,
 | 
					            eof: false,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            row: 0,
 | 
					            row: 1,
 | 
				
			||||||
            col: 1,
 | 
					            col: 1,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,10 +100,12 @@ impl Lexer for UnfinishedTokenString {
 | 
				
			||||||
            use TokenType as TT;
 | 
					            use TokenType as TT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let token_type = match self.input[self.position] as char {
 | 
					            let token_type = match self.input[self.position] as char {
 | 
				
			||||||
                '(' => Ok(TT::OpenParantheses),
 | 
					                '(' => { self.next_char(); Ok(TT::OpenParantheses) },
 | 
				
			||||||
                ')' => Ok(TT::ClosedParantheses),
 | 
					                ')' => { self.next_char(); Ok(TT::ClosedParantheses) },
 | 
				
			||||||
                'a'..='z' | 'A'..='Z' => Ok(TT::Identifier(self.lex_identifier())),
 | 
					                '.' => { self.next_char(); Ok(TT::Dot) },
 | 
				
			||||||
 | 
					                'a'..='z' | 'A'..='Z' | ':' => Ok(self.lex_identifier()),
 | 
				
			||||||
                '0'..='9' | '-' => Ok(TT::Integer(self.lex_integer())),
 | 
					                '0'..='9' | '-' => Ok(TT::Integer(self.lex_integer())),
 | 
				
			||||||
 | 
					                '"' => Ok(TT::String(self.lex_string())),
 | 
				
			||||||
                v => Err(format!("Expected new token, found: {v}")),
 | 
					                v => Err(format!("Expected new token, found: {v}")),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,8 +125,6 @@ impl Lexer for UnfinishedTokenString {
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.tokens.push(token);
 | 
					            self.tokens.push(token);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.next_char();
 | 
					 | 
				
			||||||
            self.skip_whitespace();
 | 
					            self.skip_whitespace();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,11 +156,61 @@ impl UnfinishedTokenString {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn lex_identifier(&mut self) -> String {
 | 
					    fn lex_identifier(&mut self) -> TokenType {
 | 
				
			||||||
        todo!()
 | 
					        let mut ident: String = String::new();
 | 
				
			||||||
 | 
					        while !self.eof && self.input[self.position].is_ascii_alphanumeric() {
 | 
				
			||||||
 | 
					            ident += &String::from_utf8_lossy(&[self.input[self.position]]);
 | 
				
			||||||
 | 
					            self.next_char();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn lex_integer(&mut self) -> usize {
 | 
					        use Keyword as K;
 | 
				
			||||||
        todo!()
 | 
					        use Macro as M;
 | 
				
			||||||
 | 
					        use TokenType as TT;
 | 
				
			||||||
 | 
					        match ident.as_str() {
 | 
				
			||||||
 | 
					            "add" => TT::Keyword(K::Add),
 | 
				
			||||||
 | 
					            "out" => TT::Keyword(K::Out),
 | 
				
			||||||
 | 
					            "nil" => TT::Keyword(K::Nil),
 | 
				
			||||||
 | 
					            "let" => TT::Macro(M::Let),
 | 
				
			||||||
 | 
					            "defun" => TT::Macro(M::Defun),
 | 
				
			||||||
 | 
					            _ => TT::Identifier(ident),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn lex_integer(&mut self) -> isize {
 | 
				
			||||||
 | 
					        let mut number: String = String::new();
 | 
				
			||||||
 | 
					        while !self.eof && self.input[self.position].is_ascii_digit() {
 | 
				
			||||||
 | 
					            number += &String::from_utf8_lossy(&[self.input[self.position]]);
 | 
				
			||||||
 | 
					            self.next_char();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        number.parse().unwrap()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn lex_string(&mut self) -> String {
 | 
				
			||||||
 | 
					        let mut string: String = String::new();
 | 
				
			||||||
 | 
					        self.next_char();
 | 
				
			||||||
 | 
					        while !self.eof && !(self.input[self.position] == '"' as u8) {
 | 
				
			||||||
 | 
					            string += &String::from_utf8_lossy(&[self.input[self.position]]);
 | 
				
			||||||
 | 
					            self.next_char();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Display for Keyword {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Add => write!(f, "add"),
 | 
				
			||||||
 | 
					            Self::Nil => write!(f, "nil"),
 | 
				
			||||||
 | 
					            Self::Out => write!(f, "out"),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Display for Macro {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Let => write!(f, "let"),
 | 
				
			||||||
 | 
					            Self::Defun => write!(f, "defun"),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/main.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,32 +1,47 @@
 | 
				
			||||||
// mod assembler;
 | 
					// mod assembler;
 | 
				
			||||||
 | 
					mod code_gen;
 | 
				
			||||||
 | 
					mod ir;
 | 
				
			||||||
mod lexer;
 | 
					mod lexer;
 | 
				
			||||||
// mod parser;
 | 
					mod parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod error;
 | 
					mod error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use color_eyre::eyre::Result;
 | 
					use color_eyre::eyre::Result;
 | 
				
			||||||
// pub use error::*;
 | 
					// pub use error::*;
 | 
				
			||||||
 | 
					use ir::IRepr;
 | 
				
			||||||
use lexer::TokenString;
 | 
					use lexer::TokenString;
 | 
				
			||||||
 | 
					use parser::SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::{
 | 
				
			||||||
 | 
					    code_gen::{EightBitLang, GenerateCode, Scope},
 | 
				
			||||||
 | 
					    ir::generate_code,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() -> Result<()> {
 | 
					fn main() -> Result<()> {
 | 
				
			||||||
    // let code = "(+ 1 (+ 5 5))".to_string();
 | 
					    // let code = "(+ 1 (+ 5 5))".to_string();
 | 
				
			||||||
    color_eyre::install()?;
 | 
					    color_eyre::install()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let code = "()".to_string();
 | 
					    // let code = r#"(mul 2 (add 3 4))"#.to_string();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let lexed: TokenString = code.parse()?;
 | 
					    // let code = "(add 3 4) (add 1 2)";
 | 
				
			||||||
 | 
					    let code = "(let ((a 3)) (out (add 1 a)) (out (add 2 a)))";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dbg!(lexed);
 | 
					    let lexed: TokenString = dbg!((code.parse())?);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    let parsed: Vec<SExpression> = (lexed.try_into())?;
 | 
				
			||||||
 | 
					    println!("{parsed:?}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let code: IRepr = generate_code(parsed)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // let code: EightBitLang = code.to_code(&mut Scope::new())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dbg!(code);
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
    let parsed = dbg!(parser::Parser::parse(code).unwrap());
 | 
					 | 
				
			||||||
    let assembled = assembler::Assembler::assemble(parsed).unwrap();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for byte in assembled {
 | 
					    for byte in assembled {
 | 
				
			||||||
        print!("{byte:#X}, ");
 | 
					        print!("{byte:#X}, ");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    println!(""); */
 | 
					    println!(""); */
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										223
									
								
								src/parser.rs
									
									
									
									
									
								
							
							
						
						
									
										223
									
								
								src/parser.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,143 +1,134 @@
 | 
				
			||||||
use crate::*;
 | 
					use std::fmt::Display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					use color_eyre::eyre::Error;
 | 
				
			||||||
pub struct Parser {
 | 
					
 | 
				
			||||||
    row: usize,
 | 
					use crate::lexer::{Keyword, Macro, Token, TokenString, TokenType};
 | 
				
			||||||
    column: usize,
 | 
					
 | 
				
			||||||
    lines: Vec<Vec<char>>,
 | 
					pub static NIL: SExpression = SExpression::Atom(LispAtom::Keyword(Keyword::Nil));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub enum SExpression {
 | 
				
			||||||
 | 
					    Pair(Box<SExpression>, Box<SExpression>),
 | 
				
			||||||
 | 
					    Atom(LispAtom),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
pub(crate) struct Instruction {
 | 
					struct State {
 | 
				
			||||||
    pub name: String,
 | 
					    expression: Vec<Token>,
 | 
				
			||||||
    pub arguments: Vec<Value>,
 | 
					    index: usize,
 | 
				
			||||||
 | 
					    _functions: Vec<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
pub(crate) enum Value {
 | 
					pub enum LispAtom {
 | 
				
			||||||
    Instruction(Instruction),
 | 
					    Integer(isize),
 | 
				
			||||||
    StringLiteral(String),
 | 
					    String(String),
 | 
				
			||||||
    IntegerLiteral(u32),
 | 
					 | 
				
			||||||
    Identifier(String),
 | 
					    Identifier(String),
 | 
				
			||||||
 | 
					    Keyword(Keyword),
 | 
				
			||||||
 | 
					    Macro(Macro),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Parser {
 | 
					impl TryFrom<TokenString> for Vec<SExpression> {
 | 
				
			||||||
    pub fn parse(stream: String) -> Result<Instruction> {
 | 
					    fn try_from(value: TokenString) -> Result<Self, Self::Error> {
 | 
				
			||||||
        let mut parser = Parser {
 | 
					        let list = value.tokens;
 | 
				
			||||||
            row: 0,
 | 
					
 | 
				
			||||||
            column: 0,
 | 
					        let mut expressions = vec![];
 | 
				
			||||||
            lines: stream
 | 
					
 | 
				
			||||||
                .split('\n')
 | 
					        let mut state = State {
 | 
				
			||||||
                .map(|a| a.chars().collect::<Vec<_>>())
 | 
					            expression: list,
 | 
				
			||||||
                .collect::<Vec<_>>(),
 | 
					            index: 0,
 | 
				
			||||||
 | 
					            _functions: Vec::new(),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        parser.instruction()
 | 
					
 | 
				
			||||||
 | 
					        while state.index != state.expression.len() {
 | 
				
			||||||
 | 
					            expressions.push(SExpression::parse_sexpression(&mut state)?);
 | 
				
			||||||
 | 
					            state.index += 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn increment(&mut self) -> Option<()> {
 | 
					        Ok(expressions)
 | 
				
			||||||
        self.column += 1;
 | 
					 | 
				
			||||||
        if self.column == self.lines[self.row].len() {
 | 
					 | 
				
			||||||
            self.row += 1;
 | 
					 | 
				
			||||||
            if self.row == self.lines.len() {
 | 
					 | 
				
			||||||
                self.row -= 1;
 | 
					 | 
				
			||||||
                self.column -= 1;
 | 
					 | 
				
			||||||
                return None;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            self.column = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return Some(());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn jump_whitespace(&mut self) -> Option<()> {
 | 
					    type Error = Error;
 | 
				
			||||||
        self.increment()?;
 | 
					}
 | 
				
			||||||
        while self.lines[self.row][self.column].is_whitespace() {
 | 
					
 | 
				
			||||||
            self.increment()?;
 | 
					impl SExpression {
 | 
				
			||||||
        }
 | 
					    fn parse_sexpression(state: &mut State) -> Result<Self, Error> {
 | 
				
			||||||
        Some(())
 | 
					        let expr = match &state.expression[state.index].token_type {
 | 
				
			||||||
 | 
					            TokenType::OpenParantheses => Self::parse_expression(state),
 | 
				
			||||||
 | 
					            TokenType::Integer(val) => Ok(Self::Atom(LispAtom::Integer(val.to_owned()))),
 | 
				
			||||||
 | 
					            TokenType::String(val) => Ok(Self::Atom(LispAtom::String(val.to_owned()))),
 | 
				
			||||||
 | 
					            TokenType::Identifier(val) => Ok(Self::Atom(LispAtom::Identifier(val.to_owned()))),
 | 
				
			||||||
 | 
					            TokenType::Keyword(val) => Ok(Self::Atom(LispAtom::Keyword(val.to_owned()))),
 | 
				
			||||||
 | 
					            TokenType::Macro(val) => Ok(Self::Atom(LispAtom::Macro(val.to_owned()))),
 | 
				
			||||||
 | 
					            _other => Err(Error::msg(format!(
 | 
				
			||||||
 | 
					                "Did not expect symbol at row {} col {}",
 | 
				
			||||||
 | 
					                state.expression[state.index].row, state.expression[state.index].col
 | 
				
			||||||
 | 
					            ))),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dbg!(expr)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn instruction(&mut self) -> Result<Instruction> {
 | 
					    fn parse_expression(state: &mut State) -> Result<Self, Error> {
 | 
				
			||||||
        if self.lines[self.row][self.column] != '(' {
 | 
					        if state.expression[state.index].token_type != TokenType::OpenParantheses {
 | 
				
			||||||
            return Err(Error::SyntaxError(SyntaxError {
 | 
					            return Err(Error::msg(format!(
 | 
				
			||||||
                row: self.row,
 | 
					                "Error: Expected ( at row {} col {}",
 | 
				
			||||||
                column: self.column,
 | 
					                state.expression[state.index].row, state.expression[state.index].col
 | 
				
			||||||
                message: "SyntaxError: Expected '('".to_string(),
 | 
					            )));
 | 
				
			||||||
            }));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        state.index += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.jump_whitespace();
 | 
					        let expression_1 = dbg!(Self::parse_sexpression(state)?);
 | 
				
			||||||
 | 
					        state.index += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let name = self.identifier()?;
 | 
					        // Is pair
 | 
				
			||||||
 | 
					        if state.expression[state.index].token_type == TokenType::Dot {
 | 
				
			||||||
        let mut arguments = Vec::new();
 | 
					            state.index += 1;
 | 
				
			||||||
 | 
					            let expression_2 = Self::parse_sexpression(state)?;
 | 
				
			||||||
        while self.lines[self.row][self.column] != ')' {
 | 
					            return Ok(Self::Pair(Box::new(expression_1), Box::new(expression_2)));
 | 
				
			||||||
            match self.lines[self.row][self.column] {
 | 
					 | 
				
			||||||
                '\"' => arguments.push(Value::StringLiteral(self.string_literal()?)),
 | 
					 | 
				
			||||||
                '(' => arguments.push(Value::Instruction(self.instruction()?)),
 | 
					 | 
				
			||||||
                character => {
 | 
					 | 
				
			||||||
                    if character.is_numeric() {
 | 
					 | 
				
			||||||
                        arguments.push(Value::IntegerLiteral(self.integer_literal()?));
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
                        arguments.push(Value::Identifier(self.identifier()?));
 | 
					            // Is list
 | 
				
			||||||
                    }
 | 
					            let mut elements = vec![expression_1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while state.expression[state.index].token_type != TokenType::ClosedParantheses {
 | 
				
			||||||
 | 
					                elements.push(Self::parse_sexpression(state)?);
 | 
				
			||||||
 | 
					                state.index += 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            elements.reverse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let pair = Self::make_pair_list(elements);
 | 
				
			||||||
 | 
					            return Ok(pair);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.jump_whitespace();
 | 
					    fn make_pair_list(mut expressions: Vec<SExpression>) -> SExpression {
 | 
				
			||||||
 | 
					        if expressions.len() == 1 {
 | 
				
			||||||
        return Ok(Instruction { name, arguments });
 | 
					            return SExpression::Pair(Box::new(expressions[0].clone()), Box::new(NIL.clone()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn string_literal(&mut self) -> Result<String> {
 | 
					        return SExpression::Pair(
 | 
				
			||||||
        self.increment();
 | 
					            Box::new(
 | 
				
			||||||
 | 
					                expressions
 | 
				
			||||||
        let mut accumulator = String::new();
 | 
					                    .pop()
 | 
				
			||||||
 | 
					                    .expect("The length should be more than one"),
 | 
				
			||||||
        while self.lines[self.row][self.column] != '"' {
 | 
					            ),
 | 
				
			||||||
            accumulator.push(self.lines[self.row][self.column]);
 | 
					            Box::new(Self::make_pair_list(expressions)),
 | 
				
			||||||
            self.increment();
 | 
					        );
 | 
				
			||||||
        }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
        self.jump_whitespace();
 | 
					
 | 
				
			||||||
 | 
					impl Display for SExpression {
 | 
				
			||||||
        Ok(accumulator)
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
    }
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Pair(a, b) => write!(f, "({a} . {b})"),
 | 
				
			||||||
    fn integer_literal(&mut self) -> Result<u32> {
 | 
					            Self::Atom(a) => match a {
 | 
				
			||||||
        let mut accumulator = String::new();
 | 
					                LispAtom::String(a) => write!(f, "\"{a}\""),
 | 
				
			||||||
 | 
					                LispAtom::Integer(a) => write!(f, "{a}"),
 | 
				
			||||||
        while self.lines[self.row][self.column].is_numeric() {
 | 
					                LispAtom::Keyword(a) => write!(f, "{a}"),
 | 
				
			||||||
            accumulator.push(self.lines[self.row][self.column]);
 | 
					                LispAtom::Identifier(a) => write!(f, "{a}"),
 | 
				
			||||||
            self.increment();
 | 
					                LispAtom::Macro(a) => write!(f, "{a}"),
 | 
				
			||||||
        }
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        self.jump_whitespace();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match accumulator.parse() {
 | 
					 | 
				
			||||||
            Ok(v) => Ok(v),
 | 
					 | 
				
			||||||
            Err(_e) => Err(Error::SyntaxError(SyntaxError {
 | 
					 | 
				
			||||||
                row: self.row,
 | 
					 | 
				
			||||||
                column: self.column,
 | 
					 | 
				
			||||||
                message: "Couldn't parse integer literal".to_string(),
 | 
					 | 
				
			||||||
            })),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn identifier(&mut self) -> Result<String> {
 | 
					 | 
				
			||||||
        let mut accumulator = String::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut current = self.lines[self.row][self.column];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while !"()\"".contains(current) && !current.is_whitespace() {
 | 
					 | 
				
			||||||
            accumulator.push(self.lines[self.row][self.column]);
 | 
					 | 
				
			||||||
            self.increment();
 | 
					 | 
				
			||||||
            current = self.lines[self.row][self.column];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.jump_whitespace();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(accumulator)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										143
									
								
								src/parser_old.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/parser_old.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,143 @@
 | 
				
			||||||
 | 
					use crate::{error::{Error, SyntaxError}, *};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct Parser {
 | 
				
			||||||
 | 
					    row: usize,
 | 
				
			||||||
 | 
					    column: usize,
 | 
				
			||||||
 | 
					    lines: Vec<Vec<char>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub(crate) struct Instruction {
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub arguments: Vec<Value>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub(crate) enum Value {
 | 
				
			||||||
 | 
					    Instruction(Instruction),
 | 
				
			||||||
 | 
					    StringLiteral(String),
 | 
				
			||||||
 | 
					    IntegerLiteral(u32),
 | 
				
			||||||
 | 
					    Identifier(String),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Parser {
 | 
				
			||||||
 | 
					    pub fn parse(stream: String) -> Result<Instruction> {
 | 
				
			||||||
 | 
					        let mut parser = Parser {
 | 
				
			||||||
 | 
					            row: 0,
 | 
				
			||||||
 | 
					            column: 0,
 | 
				
			||||||
 | 
					            lines: stream
 | 
				
			||||||
 | 
					                .split('\n')
 | 
				
			||||||
 | 
					                .map(|a| a.chars().collect::<Vec<_>>())
 | 
				
			||||||
 | 
					                .collect::<Vec<_>>(),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        parser.instruction()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn increment(&mut self) -> Option<()> {
 | 
				
			||||||
 | 
					        self.column += 1;
 | 
				
			||||||
 | 
					        if self.column == self.lines[self.row].len() {
 | 
				
			||||||
 | 
					            self.row += 1;
 | 
				
			||||||
 | 
					            if self.row == self.lines.len() {
 | 
				
			||||||
 | 
					                self.row -= 1;
 | 
				
			||||||
 | 
					                self.column -= 1;
 | 
				
			||||||
 | 
					                return None;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            self.column = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return Some(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn jump_whitespace(&mut self) -> Option<()> {
 | 
				
			||||||
 | 
					        self.increment()?;
 | 
				
			||||||
 | 
					        while self.lines[self.row][self.column].is_whitespace() {
 | 
				
			||||||
 | 
					            self.increment()?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Some(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn instruction(&mut self) -> Result<Instruction> {
 | 
				
			||||||
 | 
					        if self.lines[self.row][self.column] != '(' {
 | 
				
			||||||
 | 
					            return Err(Error::SyntaxError(SyntaxError {
 | 
				
			||||||
 | 
					                row: self.row,
 | 
				
			||||||
 | 
					                column: self.column,
 | 
				
			||||||
 | 
					                message: "SyntaxError: Expected '('".to_string(),
 | 
				
			||||||
 | 
					            }).into());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.jump_whitespace();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let name = self.identifier()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut arguments = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while self.lines[self.row][self.column] != ')' {
 | 
				
			||||||
 | 
					            match self.lines[self.row][self.column] {
 | 
				
			||||||
 | 
					                '\"' => arguments.push(Value::StringLiteral(self.string_literal()?)),
 | 
				
			||||||
 | 
					                '(' => arguments.push(Value::Instruction(self.instruction()?)),
 | 
				
			||||||
 | 
					                character => {
 | 
				
			||||||
 | 
					                    if character.is_numeric() {
 | 
				
			||||||
 | 
					                        arguments.push(Value::IntegerLiteral(self.integer_literal()?));
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        arguments.push(Value::Identifier(self.identifier()?));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.jump_whitespace();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Ok(Instruction { name, arguments });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn string_literal(&mut self) -> Result<String> {
 | 
				
			||||||
 | 
					        self.increment();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut accumulator = String::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while self.lines[self.row][self.column] != '"' {
 | 
				
			||||||
 | 
					            accumulator.push(self.lines[self.row][self.column]);
 | 
				
			||||||
 | 
					            self.increment();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.jump_whitespace();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(accumulator)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn integer_literal(&mut self) -> Result<u32> {
 | 
				
			||||||
 | 
					        let mut accumulator = String::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while self.lines[self.row][self.column].is_numeric() {
 | 
				
			||||||
 | 
					            accumulator.push(self.lines[self.row][self.column]);
 | 
				
			||||||
 | 
					            self.increment();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.jump_whitespace();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match accumulator.parse() {
 | 
				
			||||||
 | 
					            Ok(v) => Ok(v),
 | 
				
			||||||
 | 
					            Err(_e) => Err(Error::SyntaxError(SyntaxError {
 | 
				
			||||||
 | 
					                row: self.row,
 | 
				
			||||||
 | 
					                column: self.column,
 | 
				
			||||||
 | 
					                message: "Couldn't parse integer literal".to_string(),
 | 
				
			||||||
 | 
					            }).into()),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn identifier(&mut self) -> Result<String> {
 | 
				
			||||||
 | 
					        let mut accumulator = String::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut current = self.lines[self.row][self.column];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while !"()\"".contains(current) && !current.is_whitespace() {
 | 
				
			||||||
 | 
					            accumulator.push(self.lines[self.row][self.column]);
 | 
				
			||||||
 | 
					            self.increment();
 | 
				
			||||||
 | 
					            current = self.lines[self.row][self.column];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.jump_whitespace();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(accumulator)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in a new issue