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
|
- 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
|
||||||
|
@ -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)]
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -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([
|
||||||
|
@ -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};
|
||||||
|
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