From cdd76618cb99fe44fa51553a70181c0601e0d2a1 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 10 Dec 2024 16:04:36 -0500 Subject: [PATCH] Add time feature to CLI --- README.md | 2 +- dust-cli/src/main.rs | 59 ++++++++++++++++++++++++++++++--- dust-lang/src/chunk/mod.rs | 3 +- dust-lang/src/compiler/error.rs | 5 +++ dust-lang/src/compiler/mod.rs | 24 ++++++++++++++ dust-lang/src/dust_error.rs | 2 +- wl-copy | 7 ---- 7 files changed, 88 insertions(+), 14 deletions(-) delete mode 100644 wl-copy diff --git a/README.md b/README.md index 2ef4bef..71f90a6 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ Dust supports the following basic values: - Float: A 64-bit floating-point number - Function: An executable chunk of code - Integer: A signed 64-bit integer -- String: A UTF-8 encoded string +- String: A UTF-8 encoded byte sequence Dust's "basic" values are conceptually similar because they are singular as opposed to composite. Most of these values are stored on the stack but some are heap-allocated. A Dust string is a diff --git a/dust-cli/src/main.rs b/dust-cli/src/main.rs index 3e4c7b4..cd6c812 100644 --- a/dust-cli/src/main.rs +++ b/dust-cli/src/main.rs @@ -4,11 +4,12 @@ use std::{fs::read_to_string, path::PathBuf}; use clap::{Args, Parser}; use colored::Colorize; -use dust_lang::{compile, run, CompileError, DustError, Lexer, Span, Token}; +use dust_lang::{compile, CompileError, Compiler, DustError, Lexer, Span, Token, Vm}; use log::{Level, LevelFilter}; #[derive(Parser)] #[clap( + name = env!("CARGO_PKG_NAME"), version = env!("CARGO_PKG_VERSION"), author = env!("CARGO_PKG_AUTHORS"), about = env!("CARGO_PKG_DESCRIPTION"), @@ -34,6 +35,10 @@ struct ModeFlags { #[arg(short, long)] run: bool, + /// Print the time taken to compile and run the source code + #[arg(long, requires("run"))] + time: bool, + #[arg(long, requires("run"))] /// Do not print the run result no_output: bool, @@ -172,9 +177,31 @@ fn main() { return; } - let run_result = run(&source); + let lexer = Lexer::new(&source); + let mut compiler = match Compiler::new(lexer) { + Ok(compiler) => compiler, + Err(error) => { + handle_compile_error(error, &source); - match run_result { + return; + } + }; + + match compiler.compile() { + Ok(()) => {} + Err(error) => { + handle_compile_error(error, &source); + + return; + } + } + + let compile_end = start_time.elapsed(); + + let chunk = compiler.finish(None, None); + let mut vm = Vm::new(&source, &chunk, None); + + match vm.run() { Ok(Some(value)) => { if !mode.no_output { println!("{}", value) @@ -182,9 +209,33 @@ fn main() { } Ok(None) => {} Err(error) => { - eprintln!("{}", error); + let dust_error = DustError::runtime(error, &source); + let report = dust_error.report(); + + eprintln!("{report}"); } } + + let run_end = start_time.elapsed(); + + if mode.time { + let compile_time = compile_end.as_micros(); + let run_time = run_end - compile_end; + + println!( + "Compile time: {compile_time}µs Run time: {}s{}ms{}µs", + run_time.as_secs(), + run_time.subsec_millis(), + run_time.subsec_micros() + ); + } +} + +fn handle_compile_error(error: CompileError, source: &str) { + let dust_error = DustError::compile(error, source); + let report = dust_error.report(); + + eprintln!("{report}"); } #[cfg(test)] diff --git a/dust-lang/src/chunk/mod.rs b/dust-lang/src/chunk/mod.rs index bde6c2a..a988b5e 100644 --- a/dust-lang/src/chunk/mod.rs +++ b/dust-lang/src/chunk/mod.rs @@ -94,13 +94,14 @@ impl Chunk { self.instructions() .iter() .rev() - .find_map(|(instruction, _)| { + .filter_map(|(instruction, _)| { if instruction.yields_value() { Some(instruction.a as usize + 1) } else { None } }) + .max() .unwrap_or(0) } diff --git a/dust-lang/src/compiler/error.rs b/dust-lang/src/compiler/error.rs index e6ac5f1..39dc8c1 100644 --- a/dust-lang/src/compiler/error.rs +++ b/dust-lang/src/compiler/error.rs @@ -23,6 +23,10 @@ pub enum CompileError { CannotChainComparison { position: Span, }, + ExpectedBoolean { + found: TokenOwned, + position: Span, + }, ExpectedExpression { found: TokenOwned, position: Span, @@ -185,6 +189,7 @@ impl AnnotatedError for CompileError { Self::CannotSubtractType { .. } => "Cannot subtract from this type", Self::CannotSubtractArguments { .. } => "Cannot subtract these types", Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds", + Self::ExpectedBoolean { .. } => "Expected a boolean", Self::ExpectedExpression { .. } => "Expected an expression", Self::ExpectedFunction { .. } => "Expected a function", Self::ExpectedFunctionType { .. } => "Expected a function type", diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 505129a..6cda5c1 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -1249,6 +1249,30 @@ impl<'src> Compiler<'src> { self.parse_expression()?; + let (expression_instruction, expression_type, expression_position) = + self.instructions.last().unwrap(); + + if expression_type != &Type::Boolean { + return Err(CompileError::ExpectedFunction { + found: self.previous_token.to_owned(), + actual_type: expression_type.clone(), + position: *expression_position, + }); + } + + let test_argument = match expression_instruction.as_argument() { + Some(argument) => argument, + None => { + return Err(CompileError::ExpectedExpression { + found: self.previous_token.to_owned(), + position: *expression_position, + }) + } + }; + let test = Instruction::test(test_argument, true); + + self.emit_instruction(test, Type::None, self.current_position); + if matches!( self.get_last_operations(), Some([ diff --git a/dust-lang/src/dust_error.rs b/dust-lang/src/dust_error.rs index a7c851f..f272316 100644 --- a/dust-lang/src/dust_error.rs +++ b/dust-lang/src/dust_error.rs @@ -2,7 +2,7 @@ //! annotations. use std::fmt::{self, Display, Formatter}; -use annotate_snippets::{Annotation, Level, Renderer, Snippet}; +use annotate_snippets::{Level, Renderer, Snippet}; use smallvec::SmallVec; use crate::{CompileError, Span, VmError}; diff --git a/wl-copy b/wl-copy deleted file mode 100644 index 7051543..0000000 --- a/wl-copy +++ /dev/null @@ -1,7 +0,0 @@ - Finished `dev` profile [optimized + debuginfo] target(s) in 0.02s - Running `target/debug/dust -c '42 + true'` -error: Compilation Error: Cannot add to this type - | -1 | 42 + true - | ^^^^ While parsing this code - |