Add time feature to CLI
This commit is contained in:
parent
a8960b0f70
commit
cdd76618cb
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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([
|
||||
|
@ -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};
|
||||
|
7
wl-copy
7
wl-copy
@ -1,7 +0,0 @@
|
||||
Finished `dev` profile [optimized + debuginfo] target(s) in 0.02s
|
||||
Running `target/debug/dust -c '42 + true'`
|
||||
[1m[91merror[0m: [1mCompilation Error: Cannot add to this type[0m
|
||||
[1m[94m |[0m
|
||||
[1m[94m1 |[0m 42 + true
|
||||
[1m[94m |[0m[1m[91m ^^^^[0m [1m[91mWhile parsing this code[0m
|
||||
[1m[94m |[0m
|
Loading…
Reference in New Issue
Block a user