From 7caf0a06f57a548f864bf2e2fbc589e0929c8e30 Mon Sep 17 00:00:00 2001 From: Patric Bucher Date: Sun, 3 Dec 2023 22:01:04 +0100 Subject: [PATCH] Replacing HashMap based parser rules with a Vector based implementation The resulting speedup in parsing performance is nearly 2x --- Cargo.toml | 2 ++ src/compiler/compiler.rs | 6 +++--- src/compiler/parser/mod.rs | 2 +- src/compiler/parser/rules.rs | 5 +++-- src/main.rs | 5 +++-- src/vm/virtual_machine.rs | 13 ++++++++++++- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d321a1b..07e5711 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ lazy_static = "1.4.0" tracing = "0.1.40" tracing-attributes = { version = "0.1.27", features = [] } tracing-subscriber = "0.3.18" +env_logger = "0.10.1" +log = "0.4.20" [features] disassemble = [] \ No newline at end of file diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index a0b4d97..1467ca5 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -16,13 +16,13 @@ impl Compiler { parser.consume(TokenType::Eof, "Expect end of expression"); parser.end(); - return if parser.had_error { - None - } else { + return if !(parser.had_error) { let block = parser.blocks.pop(); #[cfg(feature = "disassemble")] block.as_ref()?.disassemble_block(); block + } else { + None }; } } diff --git a/src/compiler/parser/mod.rs b/src/compiler/parser/mod.rs index 0a1a291..1fe7578 100644 --- a/src/compiler/parser/mod.rs +++ b/src/compiler/parser/mod.rs @@ -122,7 +122,7 @@ impl Parser { } fn get_rule(&self, token_type: TokenType) -> &ParseRule { - PARSE_RULES.get(&token_type).unwrap().clone() + PARSE_RULES.get((token_type as u8) as usize).unwrap() } fn report_error_at_current(&mut self, message: &str) { diff --git a/src/compiler/parser/rules.rs b/src/compiler/parser/rules.rs index 66f97dd..9ea22a3 100644 --- a/src/compiler/parser/rules.rs +++ b/src/compiler/parser/rules.rs @@ -28,6 +28,7 @@ impl Precedence { type ParserOp = fn(&mut Parser); +#[derive(Debug, Clone)] pub(super) struct ParseRule { pub(super) prefix: Option, pub(super) infix: Option, @@ -46,7 +47,7 @@ impl ParseRule { #[rustfmt::skip] lazy_static! { - pub(super) static ref PARSE_RULES: HashMap = vec![ + pub(super) static ref PARSE_RULES: Vec = vec![ (TokenType::LeftParen, ParseRule::new(Some(Parser::grouping), None, Precedence::None)), (TokenType::RightParen, ParseRule::new(None, None, Precedence::None)), (TokenType::LeftBrace, ParseRule::new(None, None, Precedence::None)), @@ -88,5 +89,5 @@ lazy_static! { (TokenType::While, ParseRule::new(None, None, Precedence::None)), (TokenType::Error, ParseRule::new(None, None, Precedence::None)), (TokenType::Eof, ParseRule::new(None, None, Precedence::None)), - ].into_iter().collect(); + ].into_iter().map(|(_, v)| v).collect(); } diff --git a/src/main.rs b/src/main.rs index 83408c9..76b30fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,11 +11,12 @@ use std::{env, io}; use crate::vm::VirtualMachine; fn main() { - print_tagline(); - + env_logger::init(); #[cfg(feature = "disassemble")] setup_tracing(); + print_tagline(); + let args: Vec = env::args().collect(); if args.len() == 1 { run_repl(); diff --git a/src/vm/virtual_machine.rs b/src/vm/virtual_machine.rs index 91329c8..bd8d2c2 100644 --- a/src/vm/virtual_machine.rs +++ b/src/vm/virtual_machine.rs @@ -2,6 +2,8 @@ use crate::compiler::Compiler; use crate::vm::opcodes::OpCode; use crate::vm::{Block, Result, Value, VirtualMachine}; +use log::info; + impl VirtualMachine { pub fn new() -> Self { VirtualMachine { @@ -13,10 +15,19 @@ impl VirtualMachine { pub fn interpret(&mut self, source: String) -> Result { self.reset(); + let start = std::time::Instant::now(); let mut compiler = Compiler::new(); let block = compiler.compile(source); + + info!("Compile time: {}ms", start.elapsed().as_millis()); + + let start = std::time::Instant::now(); return if let Some(block) = block { - self.run(block) + let result = self.run(block); + + info!("Run time: {}ms", start.elapsed().as_millis()); + + result } else { Result::CompileError };