use crate::{ chunk::{Chunk, OptCode}, scanner::Scanner, token::Token, }; pub struct Compiler<'a> { pub scanner: Scanner<'a>, pub current: Option, pub previous: Option, pub had_error: bool, pub panic_mode: bool, pub chunk: Option, } impl<'a> Compiler<'a> { pub fn from_source(source: &'a String) -> Self { Compiler { scanner: Scanner::new(source), chunk: None, current: None, previous: None, had_error: false, panic_mode: false, } } pub fn compile(&mut self) -> bool { // let chunk = Chunk::new(); self.advance(); self.expression(); //self.consume(TokenType::TokenEof, "Expect end of expression"); self.emit_return(); return !self.had_error; } fn advance(&mut self) { self.previous = self.current.clone(); while let Some(r) = self.scanner.next() { match r { Ok(token) => { self.current = Some(token); break; } _ => { self.error_at_current("error as current token"); } } } } fn expression(&mut self) { () } fn emit_return(&mut self) { self.emit_byte(OptCode::OpReturn.into()); } fn consume(&mut self, expected: Token, message: &str) { match self.current { t if t == Some(expected) => { self.error_at_current(message); } _ => {} } } fn number(&mut self) { if let Some(Token::TokenNumber(v)) = self.previous { self.emit_constant(v); } } fn emit_constant(&mut self, value: f64) { let idx = self.make_constant(value); self.emit_bytes(OptCode::OpConstant.into(), idx); } fn current_chunk(&mut self) -> &mut Chunk { match &mut self.chunk { Some(chunk) => { let c: &mut Chunk = chunk; return c; } None => panic!("oh no!"), } } fn make_constant(&mut self, value: f64) -> u8 { let chunk: &mut Chunk = self.current_chunk(); chunk.write_value(value) } fn emit_byte(&mut self, byte: u8) { // self.write_byte(self.chunk, self.previous.unwrap().line); } fn emit_bytes(&mut self, first: u8, second: u8) { // self.write_byte(self.chunk, self.previous.unwrap().line); } fn error_at_current(&mut self, message: &str) { self.error_at(self.current.clone().unwrap(), message); } fn error(&mut self, message: &str) { self.error_at(self.previous.clone().unwrap(), message); } fn error_at(&mut self, token: Token, message: &str) { if self.panic_mode { return; } // print!("[line {:}] Error", token.line); // match token.token_type { // TokenType::TokenEof => { // print!(" at end") // } // TokenType::TokenError => { // todo!(); // } // _ => { // print!(" at '{:}'", token.lexeme); // } // } // println!(": {:}", message); self.had_error = true; } } // use strum_macros::Display; // #[derive(Display, PartialEq, Eq, PartialOrd, Ord)] // enum Precedence { // None, // Assignment, // Or, // And, // Equality, // Comparison, // Term, // Factor, // Unary, // Call, // Primary, // }