Skip to content

Commit

Permalink
Replacing HashMap based parser rules with a Vector based implementation
Browse files Browse the repository at this point in the history
The resulting speedup in parsing performance is nearly 2x
  • Loading branch information
patbuc committed Dec 3, 2023
1 parent f7f8a48 commit 7caf0a0
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
6 changes: 3 additions & 3 deletions src/compiler/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
}
}
2 changes: 1 addition & 1 deletion src/compiler/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/parser/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl Precedence {

type ParserOp = fn(&mut Parser);

#[derive(Debug, Clone)]
pub(super) struct ParseRule {
pub(super) prefix: Option<ParserOp>,
pub(super) infix: Option<ParserOp>,
Expand All @@ -46,7 +47,7 @@ impl ParseRule {

#[rustfmt::skip]
lazy_static! {
pub(super) static ref PARSE_RULES: HashMap<TokenType, ParseRule> = vec![
pub(super) static ref PARSE_RULES: Vec<ParseRule> = 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)),
Expand Down Expand Up @@ -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();
}
5 changes: 3 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> = env::args().collect();
if args.len() == 1 {
run_repl();
Expand Down
13 changes: 12 additions & 1 deletion src/vm/virtual_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
};
Expand Down

0 comments on commit 7caf0a0

Please sign in to comment.