From 6caae6c9528c49d7f4e3b2c6950be4b3776f722e Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 20 Oct 2024 00:46:59 -0400 Subject: [PATCH] Add chunk names --- dust-lang/src/chunk.rs | 55 ++++++++++++++++++---------------- dust-lang/src/parser.rs | 40 ++++--------------------- dust-lang/tests/expressions.rs | 45 +++++++++++++++++++++++++++- dust-shell/src/main.rs | 2 +- examples/assets/count.js | 5 ++++ examples/count.ds | 5 ++++ 6 files changed, 91 insertions(+), 61 deletions(-) create mode 100644 examples/assets/count.js create mode 100644 examples/count.ds diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index ef97f1d..cf77ffc 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -1,6 +1,6 @@ use std::{ + env::current_exe, fmt::{self, Debug, Display}, - path::PathBuf, }; use colored::Colorize; @@ -10,6 +10,7 @@ use crate::{AnnotatedError, Identifier, Instruction, Span, Type, Value}; #[derive(Clone, PartialOrd, Ord, Serialize, Deserialize)] pub struct Chunk { + name: Option, instructions: Vec<(Instruction, Span)>, constants: Vec, locals: Vec, @@ -17,8 +18,9 @@ pub struct Chunk { } impl Chunk { - pub fn new() -> Self { + pub fn new(name: Option) -> Self { Self { + name, instructions: Vec::new(), constants: Vec::new(), locals: Vec::new(), @@ -27,11 +29,13 @@ impl Chunk { } pub fn with_data( + name: Option, instructions: Vec<(Instruction, Span)>, constants: Vec, locals: Vec, ) -> Self { Self { + name, instructions, constants, locals, @@ -39,6 +43,14 @@ impl Chunk { } } + pub fn name(&self) -> Option<&Identifier> { + self.name.as_ref() + } + + pub fn set_name(&mut self, name: Identifier) { + self.name = Some(name); + } + pub fn len(&self) -> usize { self.instructions.len() } @@ -202,34 +214,20 @@ impl Chunk { self.scope_depth -= 1; } - pub fn disassembler<'a>(&'a self, name: &'a str) -> ChunkDisassembler<'a> { - ChunkDisassembler::new(name, self) - } -} - -impl Default for Chunk { - fn default() -> Self { - Self::new() + pub fn disassembler(&self) -> ChunkDisassembler { + ChunkDisassembler::new(self) } } impl Display for Chunk { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - self.disassembler("Dust Program").styled(true).disassemble() - ) + write!(f, "{}", self.disassembler().styled(true).disassemble()) } } impl Debug for Chunk { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let executable = std::env::current_exe().unwrap_or_else(|_| PathBuf::new()); - let disassembly = self - .disassembler(&executable.to_string_lossy()) - .styled(false) - .disassemble(); + let disassembly = self.disassembler().styled(false).disassemble(); if cfg!(debug_assertions) { write!(f, "\n{}", disassembly) @@ -277,7 +275,6 @@ impl Local { } pub struct ChunkDisassembler<'a> { - name: &'a str, chunk: &'a Chunk, source: Option<&'a str>, width: usize, @@ -311,9 +308,8 @@ impl<'a> ChunkDisassembler<'a> { longest_line.chars().count().max(80) } - pub fn new(name: &'a str, chunk: &'a Chunk) -> Self { + pub fn new(chunk: &'a Chunk) -> Self { Self { - name, chunk, source: None, width: Self::default_width(), @@ -465,9 +461,18 @@ impl<'a> ChunkDisassembler<'a> { let top_border = "┌".to_string() + &"─".repeat(self.width - 2) + "┐"; let section_border = "│".to_string() + &"┈".repeat(self.width - 2) + "│"; let bottom_border = "└".to_string() + &"─".repeat(self.width - 2) + "┘"; + let name_display = self + .chunk + .name() + .map(|identifier| identifier.to_string()) + .unwrap_or_else(|| { + current_exe() + .map(|path| path.to_string_lossy().to_string()) + .unwrap_or("Chunk Disassembly".to_string()) + }); push_border(&top_border, &mut disassembly); - push_header(self.name, &mut disassembly); + push_header(&name_display, &mut disassembly); let info_line = format!( "{} instructions, {} constants, {} locals", @@ -564,7 +569,7 @@ impl<'a> ChunkDisassembler<'a> { if let Some(function_disassembly) = match value { Value::Function(function) => Some({ - let mut disassembler = function.chunk().disassembler("function"); + let mut disassembler = function.chunk().disassembler(); disassembler.indent = self.indent + 1; disassembler.styled(self.styled); diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 5bc81a3..d107a9a 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -9,8 +9,8 @@ use colored::Colorize; use serde::{Deserialize, Serialize}; use crate::{ - instruction, operation, AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Identifier, - Instruction, LexError, Lexer, Operation, Span, Token, TokenKind, TokenOwned, Type, Value, + AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Identifier, Instruction, LexError, + Lexer, Operation, Span, Token, TokenKind, TokenOwned, Type, Value, }; pub fn parse(source: &str) -> Result { @@ -59,7 +59,7 @@ impl<'src> Parser<'src> { Ok(Parser { lexer, - chunk: Chunk::new(), + chunk: Chunk::new(None), current_statement: Vec::new(), minimum_register: 0, current_token, @@ -171,36 +171,6 @@ impl<'src> Parser<'src> { Some(operations) } - fn get_previous_jump_mut(&mut self) -> Option<&mut Instruction> { - let staged_jump = self - .current_statement - .iter_mut() - .rev() - .find_map(|(instruction, _)| { - if matches!(instruction.operation(), Operation::Jump) { - Some(instruction) - } else { - None - } - }); - - if staged_jump.is_some() { - staged_jump - } else { - self.chunk - .instructions_mut() - .iter_mut() - .rev() - .find_map(|(instruction, _)| { - if matches!(instruction.operation(), Operation::Jump) { - Some(instruction) - } else { - None - } - }) - } - } - fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> { let constant_index = self.chunk.push_constant(value, position)?; let register = self.next_register(); @@ -1104,10 +1074,12 @@ impl<'src> Parser<'src> { let mut function_parser = Parser::new(self.lexer)?; let identifier = if let Token::Identifier(text) = function_parser.current_token { let position = function_parser.current_position; + let identifier = Identifier::new(text); function_parser.advance()?; + function_parser.chunk.set_name(identifier.clone()); - Some((Identifier::new(text), position)) + Some((identifier, position)) } else { None }; diff --git a/dust-lang/tests/expressions.rs b/dust-lang/tests/expressions.rs index 03ae7f6..ff3a984 100644 --- a/dust-lang/tests/expressions.rs +++ b/dust-lang/tests/expressions.rs @@ -7,6 +7,7 @@ fn add() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::add(0, 0, 1) @@ -31,6 +32,7 @@ fn add_assign() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 13)), (Instruction::define_local(0, 0, true), Span(8, 9)), @@ -53,6 +55,7 @@ fn and() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_boolean(0, true, false), Span(0, 4)), (Instruction::test(0, false), Span(5, 7)), @@ -85,6 +88,7 @@ fn block_scope() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(17, 18)), (Instruction::define_local(0, 0, false), Span(13, 14)), @@ -124,6 +128,7 @@ fn constant() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(0, 2)), (Instruction::r#return(true), Span(2, 2)) @@ -143,6 +148,7 @@ fn define_local() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(8, 10)), (Instruction::define_local(0, 0, false), Span(4, 5)), @@ -162,6 +168,7 @@ fn divide() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::divide(0, 0, 1) @@ -186,6 +193,7 @@ fn divide_assign() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 13)), (Instruction::define_local(0, 0, true), Span(8, 9)), @@ -208,7 +216,10 @@ fn divide_assign() { fn empty() { let source = ""; - assert_eq!(parse(source), Ok(Chunk::with_data(vec![], vec![], vec![])),); + assert_eq!( + parse(source), + Ok(Chunk::with_data(None, vec![], vec![], vec![])) + ); assert_eq!(run(source), Ok(None)); } @@ -219,6 +230,7 @@ fn empty_list() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_list(0, 0, 0), Span(0, 2)), (Instruction::r#return(true), Span(2, 2)), @@ -238,6 +250,7 @@ fn equal() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -265,6 +278,7 @@ fn equality_assignment_long() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -294,6 +308,7 @@ fn equality_assignment_short() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -324,6 +339,7 @@ fn function() { run(source), Ok(Some(Value::function( Chunk::with_data( + None, vec![ (Instruction::add(2, 0, 1), Span(30, 31)), (Instruction::r#return(true), Span(34, 35)), @@ -353,12 +369,14 @@ fn function_declaration() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(0, 40)), (Instruction::define_local(0, 0, false), Span(3, 6)), ], vec![Value::function( Chunk::with_data( + None, vec![ (Instruction::add(2, 0, 1), Span(35, 36)), (Instruction::r#return(true), Span(39, 40)), @@ -405,6 +423,7 @@ fn function_call() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(0, 36)), (Instruction::load_constant(1, 1, false), Span(36, 37)), @@ -415,6 +434,7 @@ fn function_call() { vec![ Value::function( Chunk::with_data( + None, vec![ (Instruction::add(2, 0, 1), Span(30, 31)), (Instruction::r#return(true), Span(34, 35)), @@ -451,6 +471,7 @@ fn greater() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::less_equal(false, 0, 1) @@ -478,6 +499,7 @@ fn greater_than_or_equal() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::less(false, 0, 1) @@ -505,6 +527,7 @@ fn if_else_expression() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -537,6 +560,7 @@ fn if_expression_false() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -562,6 +586,7 @@ fn if_expression_true() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(true, 0, 1) @@ -587,6 +612,7 @@ fn less_than() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::less(true, 0, 1) @@ -614,6 +640,7 @@ fn less_than_or_equal() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::less_equal(true, 0, 1) @@ -641,6 +668,7 @@ fn list() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(1, 2)), (Instruction::load_constant(1, 1, false), Span(4, 5)), @@ -663,6 +691,7 @@ fn list_with_complex_expression() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(1, 2)), ( @@ -703,6 +732,7 @@ fn list_with_simple_expression() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(1, 2)), ( @@ -735,6 +765,7 @@ fn math_operator_precedence() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::add(0, 0, 1) @@ -776,6 +807,7 @@ fn multiply() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::multiply(0, 0, 1) @@ -800,6 +832,7 @@ fn multiply_assign() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 13)), (Instruction::define_local(0, 0, true), Span(8, 9)), @@ -825,6 +858,7 @@ fn negate() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (*Instruction::negate(0, 0).set_b_is_constant(), Span(0, 1)), (Instruction::r#return(true), Span(5, 5)), @@ -844,6 +878,7 @@ fn not() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_boolean(0, true, false), Span(1, 5)), (Instruction::not(1, 0), Span(0, 1)), @@ -864,6 +899,7 @@ fn not_equal() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::equal(false, 0, 1) @@ -891,6 +927,7 @@ fn or() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_boolean(0, true, false), Span(0, 4)), (Instruction::test(0, true), Span(5, 7)), @@ -913,6 +950,7 @@ fn parentheses_precedence() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::add(0, 0, 1) @@ -941,6 +979,7 @@ fn set_local() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 14)), (Instruction::define_local(0, 0, true), Span(8, 9)), @@ -964,6 +1003,7 @@ fn subtract() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ ( *Instruction::subtract(0, 0, 1) @@ -988,6 +1028,7 @@ fn subtract_assign() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 14)), (Instruction::define_local(0, 0, true), Span(8, 9)), @@ -1013,6 +1054,7 @@ fn variable_and() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_boolean(0, true, false), Span(8, 12)), (Instruction::define_local(0, 0, false), Span(4, 5)), @@ -1042,6 +1084,7 @@ fn r#while() { assert_eq!( parse(source), Ok(Chunk::with_data( + None, vec![ (Instruction::load_constant(0, 0, false), Span(12, 13)), (Instruction::define_local(0, 0, true), Span(8, 9)), diff --git a/dust-shell/src/main.rs b/dust-shell/src/main.rs index 1628f1f..e8fca49 100644 --- a/dust-shell/src/main.rs +++ b/dust-shell/src/main.rs @@ -111,7 +111,7 @@ fn parse_source(source: &str, styled: bool) { match parse(source) { Ok(chunk) => { let disassembly = chunk - .disassembler("Dust CLI Input") + .disassembler() .source(source) .styled(styled) .disassemble(); diff --git a/examples/assets/count.js b/examples/assets/count.js new file mode 100644 index 0000000..ba97d27 --- /dev/null +++ b/examples/assets/count.js @@ -0,0 +1,5 @@ +var i = 0; + +while (i < 10000) { + i++; +} diff --git a/examples/count.ds b/examples/count.ds new file mode 100644 index 0000000..82ff9ac --- /dev/null +++ b/examples/count.ds @@ -0,0 +1,5 @@ +let mut i = 0; + +while i < 10000 { + i += 1; +}