1
0

Add time feature to CLI

This commit is contained in:
Jeff 2024-12-10 16:04:36 -05:00
parent a8960b0f70
commit cdd76618cb
7 changed files with 88 additions and 14 deletions

View File

@ -157,7 +157,7 @@ Dust supports the following basic values:
- Float: A 64-bit floating-point number - Float: A 64-bit floating-point number
- Function: An executable chunk of code - Function: An executable chunk of code
- Integer: A signed 64-bit integer - 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. 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 Most of these values are stored on the stack but some are heap-allocated. A Dust string is a

View File

@ -4,11 +4,12 @@ use std::{fs::read_to_string, path::PathBuf};
use clap::{Args, Parser}; use clap::{Args, Parser};
use colored::Colorize; 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}; use log::{Level, LevelFilter};
#[derive(Parser)] #[derive(Parser)]
#[clap( #[clap(
name = env!("CARGO_PKG_NAME"),
version = env!("CARGO_PKG_VERSION"), version = env!("CARGO_PKG_VERSION"),
author = env!("CARGO_PKG_AUTHORS"), author = env!("CARGO_PKG_AUTHORS"),
about = env!("CARGO_PKG_DESCRIPTION"), about = env!("CARGO_PKG_DESCRIPTION"),
@ -34,6 +35,10 @@ struct ModeFlags {
#[arg(short, long)] #[arg(short, long)]
run: bool, run: bool,
/// Print the time taken to compile and run the source code
#[arg(long, requires("run"))]
time: bool,
#[arg(long, requires("run"))] #[arg(long, requires("run"))]
/// Do not print the run result /// Do not print the run result
no_output: bool, no_output: bool,
@ -172,9 +177,31 @@ fn main() {
return; 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)) => { Ok(Some(value)) => {
if !mode.no_output { if !mode.no_output {
println!("{}", value) println!("{}", value)
@ -182,9 +209,33 @@ fn main() {
} }
Ok(None) => {} Ok(None) => {}
Err(error) => { 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)] #[cfg(test)]

View File

@ -94,13 +94,14 @@ impl Chunk {
self.instructions() self.instructions()
.iter() .iter()
.rev() .rev()
.find_map(|(instruction, _)| { .filter_map(|(instruction, _)| {
if instruction.yields_value() { if instruction.yields_value() {
Some(instruction.a as usize + 1) Some(instruction.a as usize + 1)
} else { } else {
None None
} }
}) })
.max()
.unwrap_or(0) .unwrap_or(0)
} }

View File

@ -23,6 +23,10 @@ pub enum CompileError {
CannotChainComparison { CannotChainComparison {
position: Span, position: Span,
}, },
ExpectedBoolean {
found: TokenOwned,
position: Span,
},
ExpectedExpression { ExpectedExpression {
found: TokenOwned, found: TokenOwned,
position: Span, position: Span,
@ -185,6 +189,7 @@ impl AnnotatedError for CompileError {
Self::CannotSubtractType { .. } => "Cannot subtract from this type", Self::CannotSubtractType { .. } => "Cannot subtract from this type",
Self::CannotSubtractArguments { .. } => "Cannot subtract these types", Self::CannotSubtractArguments { .. } => "Cannot subtract these types",
Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds", Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
Self::ExpectedBoolean { .. } => "Expected a boolean",
Self::ExpectedExpression { .. } => "Expected an expression", Self::ExpectedExpression { .. } => "Expected an expression",
Self::ExpectedFunction { .. } => "Expected a function", Self::ExpectedFunction { .. } => "Expected a function",
Self::ExpectedFunctionType { .. } => "Expected a function type", Self::ExpectedFunctionType { .. } => "Expected a function type",

View File

@ -1249,6 +1249,30 @@ impl<'src> Compiler<'src> {
self.parse_expression()?; 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!( if matches!(
self.get_last_operations(), self.get_last_operations(),
Some([ Some([

View File

@ -2,7 +2,7 @@
//! annotations. //! annotations.
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use annotate_snippets::{Annotation, Level, Renderer, Snippet}; use annotate_snippets::{Level, Renderer, Snippet};
use smallvec::SmallVec; use smallvec::SmallVec;
use crate::{CompileError, Span, VmError}; use crate::{CompileError, Span, VmError};

View File

@ -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
 |