Clean up
This commit is contained in:
parent
2df86c58bf
commit
71a68c54e4
139
Cargo.lock
generated
139
Cargo.lock
generated
@ -322,10 +322,10 @@ dependencies = [
|
|||||||
"clap 4.5.20",
|
"clap 4.5.20",
|
||||||
"color-print",
|
"color-print",
|
||||||
"dust-lang",
|
"dust-lang",
|
||||||
"env_logger",
|
|
||||||
"log",
|
|
||||||
"postcard",
|
"postcard",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -336,12 +336,12 @@ dependencies = [
|
|||||||
"colored",
|
"colored",
|
||||||
"criterion",
|
"criterion",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"log",
|
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"smartstring",
|
"smartstring",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -350,29 +350,6 @@ version = "1.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "env_filter"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"regex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "env_logger"
|
|
||||||
version = "0.11.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
|
|
||||||
dependencies = [
|
|
||||||
"anstream",
|
|
||||||
"anstyle",
|
|
||||||
"env_filter",
|
|
||||||
"humantime",
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.10"
|
version = "0.3.10"
|
||||||
@ -440,12 +417,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "humantime"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -532,6 +503,16 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@ -553,6 +534,18 @@ version = "11.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plotters"
|
name = "plotters"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@ -789,6 +782,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
@ -867,6 +869,16 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinytemplate"
|
name = "tinytemplate"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -877,6 +889,63 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-attributes",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-attributes"
|
||||||
|
version = "0.1.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
|
dependencies = [
|
||||||
|
"nu-ansi-term",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
@ -895,6 +964,12 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
@ -22,7 +22,7 @@ clap = { version = "4.5.14", features = [
|
|||||||
] }
|
] }
|
||||||
color-print = "0.3.7"
|
color-print = "0.3.7"
|
||||||
dust-lang = { path = "../dust-lang" }
|
dust-lang = { path = "../dust-lang" }
|
||||||
env_logger = "0.11.5"
|
|
||||||
log = "0.4.22"
|
|
||||||
postcard = "1.0.10"
|
postcard = "1.0.10"
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.133"
|
||||||
|
tracing = "0.1.41"
|
||||||
|
tracing-subscriber = "0.3.19"
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
use std::io::{self, stdout, Read, Write};
|
use std::fmt::Write;
|
||||||
|
use std::io::{self, stdout, Read};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{fs::read_to_string, path::PathBuf};
|
use std::{fs::read_to_string, path::PathBuf};
|
||||||
|
|
||||||
use clap::builder::StyledStr;
|
use clap::builder::StyledStr;
|
||||||
use clap::Args;
|
use clap::error::ErrorKind;
|
||||||
use clap::{
|
use clap::{
|
||||||
builder::{styling::AnsiColor, Styles},
|
builder::{styling::AnsiColor, Styles},
|
||||||
crate_authors, crate_description, crate_version, ColorChoice, Parser, Subcommand, ValueHint,
|
crate_authors, crate_description, crate_version, ColorChoice, Parser, Subcommand, ValueHint,
|
||||||
};
|
};
|
||||||
|
use clap::{Args, Error};
|
||||||
use color_print::cstr;
|
use color_print::cstr;
|
||||||
use dust_lang::{CompileError, Compiler, DustError, DustString, Lexer, Span, Token, Vm};
|
use dust_lang::{CompileError, Compiler, DustError, DustString, Lexer, Span, Token, Vm};
|
||||||
use log::{Level, LevelFilter};
|
use tracing::subscriber::set_global_default;
|
||||||
|
use tracing::{span, warn, Level};
|
||||||
|
use tracing_subscriber::fmt::format::Writer;
|
||||||
|
use tracing_subscriber::fmt::{FmtContext, MakeWriter};
|
||||||
|
use tracing_subscriber::FmtSubscriber;
|
||||||
|
|
||||||
const CLI_HELP_TEMPLATE: &str = cstr!(
|
const CLI_HELP_TEMPLATE: &str = cstr!(
|
||||||
r#"
|
r#"
|
||||||
@ -18,10 +24,10 @@ const CLI_HELP_TEMPLATE: &str = cstr!(
|
|||||||
────────</bold>
|
────────</bold>
|
||||||
{about}</bright-magenta>
|
{about}</bright-magenta>
|
||||||
|
|
||||||
☑ Version: {version}
|
{tab}☑ Version: {version}
|
||||||
✎ Author: {author}
|
{tab}✎ Author: {author}
|
||||||
⚖️ License: GPL-3.0
|
{tab}⚖️ License: GPL-3.0
|
||||||
🌐 Repository: git.jeffa.io/jeff/dust
|
{tab}🌐 Repository: git.jeffa.io/jeff/dust
|
||||||
|
|
||||||
<bright-magenta,bold>Usage
|
<bright-magenta,bold>Usage
|
||||||
─────</bright-magenta,bold>
|
─────</bright-magenta,bold>
|
||||||
@ -43,10 +49,10 @@ const MODE_HELP_TEMPLATE: &str = cstr!(
|
|||||||
────────</bold>
|
────────</bold>
|
||||||
{about}</bright-magenta>
|
{about}</bright-magenta>
|
||||||
|
|
||||||
☑ Version: {version}
|
{tab}☑ Version: {version}
|
||||||
✎ Author: {author}
|
{tab}✎ Author: {author}
|
||||||
⚖️ License: GPL-3.0
|
{tab}⚖️ License: GPL-3.0
|
||||||
🌐 Repository: git.jeffa.io/jeff/dust
|
{tab}🌐 Repository: git.jeffa.io/jeff/dust
|
||||||
|
|
||||||
<bright-magenta,bold>Usage
|
<bright-magenta,bold>Usage
|
||||||
─────</bright-magenta,bold>
|
─────</bright-magenta,bold>
|
||||||
@ -78,11 +84,25 @@ const STYLES: Styles = Styles::styled()
|
|||||||
)]
|
)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
/// Overrides the DUST_LOG environment variable
|
/// Overrides the DUST_LOG environment variable
|
||||||
#[arg(short, long, value_name = "LOG_LEVEL")]
|
#[arg(
|
||||||
log: Option<LevelFilter>,
|
short,
|
||||||
|
long,
|
||||||
|
value_parser = |input: &str| match input.to_uppercase().as_str() {
|
||||||
|
"TRACE" => Ok(Level::TRACE),
|
||||||
|
"DEBUG" => Ok(Level::DEBUG),
|
||||||
|
"INFO" => Ok(Level::INFO),
|
||||||
|
"WARN" => Ok(Level::WARN),
|
||||||
|
"ERROR" => Ok(Level::ERROR),
|
||||||
|
_ => Err(Error::new(ErrorKind::ValueValidation)),
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
log_level: Option<Level>,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
mode: Mode,
|
mode: Option<Mode>,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
run: Run,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
@ -100,30 +120,33 @@ struct Input {
|
|||||||
file: Option<PathBuf>,
|
file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compile and run the program (default)
|
||||||
|
#[derive(Args)]
|
||||||
|
#[command(
|
||||||
|
short_flag = 'r',
|
||||||
|
help_template = MODE_HELP_TEMPLATE
|
||||||
|
)]
|
||||||
|
struct Run {
|
||||||
|
/// Print the time taken for compilation and execution
|
||||||
|
#[arg(long)]
|
||||||
|
time: bool,
|
||||||
|
|
||||||
|
/// Do not print the program's return value
|
||||||
|
#[arg(long)]
|
||||||
|
no_output: bool,
|
||||||
|
|
||||||
|
/// Custom program name, overrides the file name
|
||||||
|
#[arg(long)]
|
||||||
|
name: Option<DustString>,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
input: Input,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
#[clap(subcommand_value_name = "MODE", flatten_help = true)]
|
#[clap(subcommand_value_name = "MODE", flatten_help = true)]
|
||||||
enum Mode {
|
enum Mode {
|
||||||
/// Compile and run the program (default)
|
Run(Run),
|
||||||
#[command(
|
|
||||||
short_flag = 'r',
|
|
||||||
help_template = MODE_HELP_TEMPLATE
|
|
||||||
)]
|
|
||||||
Run {
|
|
||||||
/// Print the time taken for compilation and execution
|
|
||||||
#[arg(long)]
|
|
||||||
time: bool,
|
|
||||||
|
|
||||||
/// Do not print the program's return value
|
|
||||||
#[arg(long)]
|
|
||||||
no_output: bool,
|
|
||||||
|
|
||||||
/// Custom program name, overrides the file name
|
|
||||||
#[arg(long)]
|
|
||||||
name: Option<DustString>,
|
|
||||||
|
|
||||||
#[command(flatten)]
|
|
||||||
input: Input,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Compile and print the bytecode disassembly
|
/// Compile and print the bytecode disassembly
|
||||||
#[command(
|
#[command(
|
||||||
@ -185,29 +208,18 @@ fn get_source_and_file_name(input: Input) -> (String, Option<DustString>) {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let mut logger = env_logger::builder();
|
let Cli {
|
||||||
|
log_level,
|
||||||
|
mode,
|
||||||
|
run,
|
||||||
|
} = Cli::parse();
|
||||||
|
let mode = mode.unwrap_or(Mode::Run(run));
|
||||||
|
let subscriber = FmtSubscriber::builder()
|
||||||
|
.with_max_level(log_level)
|
||||||
|
.with_thread_names(true)
|
||||||
|
.finish();
|
||||||
|
|
||||||
logger.format(move |buf, record| {
|
set_global_default(subscriber).expect("Failed to set tracing subscriber");
|
||||||
let elapsed = format!("T+{:.04}", start_time.elapsed().as_secs_f32());
|
|
||||||
let level_display = match record.level() {
|
|
||||||
Level::Info => cstr!("<bright-magenta,bold>INFO<bright-magenta,bold>"),
|
|
||||||
Level::Trace => cstr!("<bright-cyan,bold>TRACE<bright-cyan,bold>"),
|
|
||||||
Level::Debug => cstr!("<bright-blue,bold>DEBUG<bright-blue,bold>"),
|
|
||||||
Level::Warn => cstr!("<bright-yellow,bold>WARN<bright-yellow,bold>"),
|
|
||||||
Level::Error => cstr!("<bright-red,bold>ERROR<bright-red,bold>"),
|
|
||||||
};
|
|
||||||
let display = format!("[{elapsed}] {level_display:5} {args}", args = record.args());
|
|
||||||
|
|
||||||
writeln!(buf, "{display}")
|
|
||||||
});
|
|
||||||
|
|
||||||
let Cli { log, mode } = Cli::parse();
|
|
||||||
|
|
||||||
if let Some(level) = log {
|
|
||||||
logger.filter_level(level).init();
|
|
||||||
} else {
|
|
||||||
logger.parse_env("DUST_LOG").init();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Mode::Disassemble { style, name, input } = mode {
|
if let Mode::Disassemble { style, name, input } = mode {
|
||||||
let (source, file_name) = get_source_and_file_name(input);
|
let (source, file_name) = get_source_and_file_name(input);
|
||||||
@ -235,9 +247,9 @@ fn main() {
|
|||||||
|
|
||||||
chunk
|
chunk
|
||||||
.disassembler(&mut stdout)
|
.disassembler(&mut stdout)
|
||||||
|
.width(65)
|
||||||
.style(style)
|
.style(style)
|
||||||
.source(&source)
|
.source(&source)
|
||||||
.width(65)
|
|
||||||
.disassemble()
|
.disassemble()
|
||||||
.expect("Failed to write disassembly to stdout");
|
.expect("Failed to write disassembly to stdout");
|
||||||
|
|
||||||
@ -290,13 +302,16 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Mode::Run {
|
if let Mode::Run(Run {
|
||||||
name,
|
|
||||||
time,
|
time,
|
||||||
no_output,
|
no_output,
|
||||||
|
name,
|
||||||
input,
|
input,
|
||||||
} = mode
|
}) = mode
|
||||||
{
|
{
|
||||||
|
let run_span = span!(Level::TRACE, "CLI Run Mode");
|
||||||
|
let _run_guard = run_span.enter();
|
||||||
|
|
||||||
let (source, file_name) = get_source_and_file_name(input);
|
let (source, file_name) = get_source_and_file_name(input);
|
||||||
let lexer = Lexer::new(&source);
|
let lexer = Lexer::new(&source);
|
||||||
let mut compiler = match Compiler::new(lexer) {
|
let mut compiler = match Compiler::new(lexer) {
|
||||||
|
@ -11,7 +11,6 @@ version.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
annotate-snippets = "0.11.4"
|
annotate-snippets = "0.11.4"
|
||||||
colored = "2.1.0"
|
colored = "2.1.0"
|
||||||
log = "0.4.22"
|
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
@ -22,6 +21,7 @@ smallvec = { version = "1.13.2", features = ["const_generics", "serde"] }
|
|||||||
smartstring = { version = "1.0.1", features = [
|
smartstring = { version = "1.0.1", features = [
|
||||||
"serde",
|
"serde",
|
||||||
], default-features = false }
|
], default-features = false }
|
||||||
|
tracing = "0.1.41"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = { version = "0.3.4", features = ["html_reports"] }
|
criterion = { version = "0.3.4", features = ["html_reports"] }
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
//! │ │
|
//! │ │
|
||||||
//! │ write_line("Hello world!") │
|
//! │ write_line("Hello world!") │
|
||||||
//! │ │
|
//! │ │
|
||||||
//! │ 3 instructions, 1 constants, 0 locals, returns str │
|
//! │ 3 instructions, 1 constants, 0 locals, returns none │
|
||||||
//! │ │
|
//! │ │
|
||||||
//! │ Instructions │
|
//! │ Instructions │
|
||||||
//! │ ╭─────┬────────────┬─────────────────┬────────────────────────╮ │
|
//! │ ╭─────┬────────────┬─────────────────┬────────────────────────╮ │
|
||||||
@ -39,10 +39,7 @@
|
|||||||
//! │ ╰─────┴──────────────────────────┴──────────────────────────╯ │
|
//! │ ╰─────┴──────────────────────────┴──────────────────────────╯ │
|
||||||
//! ╰─────────────────────────────────────────────────────────────────╯
|
//! ╰─────────────────────────────────────────────────────────────────╯
|
||||||
//! ```
|
//! ```
|
||||||
use std::{
|
use std::io::{self, Write};
|
||||||
env::current_exe,
|
|
||||||
io::{self, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use colored::{ColoredString, Colorize};
|
use colored::{ColoredString, Colorize};
|
||||||
|
|
||||||
@ -397,26 +394,9 @@ impl<'a, W: Write> Disassembler<'a, W> {
|
|||||||
pub fn disassemble(&mut self) -> Result<(), io::Error> {
|
pub fn disassemble(&mut self) -> Result<(), io::Error> {
|
||||||
self.write_page_border(TOP_BORDER)?;
|
self.write_page_border(TOP_BORDER)?;
|
||||||
|
|
||||||
let name_display = self
|
if let Some(name) = &self.chunk.name {
|
||||||
.chunk
|
self.write_center_border_bold(name)?;
|
||||||
.name()
|
}
|
||||||
.map(|identifier| identifier.to_string())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
current_exe()
|
|
||||||
.map(|path| {
|
|
||||||
let path_string = path.to_string_lossy();
|
|
||||||
let file_name = path_string
|
|
||||||
.split('/')
|
|
||||||
.last()
|
|
||||||
.map(|slice| slice.to_string())
|
|
||||||
.unwrap_or(path_string.to_string());
|
|
||||||
|
|
||||||
file_name
|
|
||||||
})
|
|
||||||
.unwrap_or("Dust Chunk Disassembly".to_string())
|
|
||||||
});
|
|
||||||
|
|
||||||
self.write_center_border_bold(&name_display)?;
|
|
||||||
|
|
||||||
if self.show_type {
|
if self.show_type {
|
||||||
let type_display = self.chunk.r#type.to_string();
|
let type_display = self.chunk.r#type.to_string();
|
||||||
|
@ -211,9 +211,6 @@ impl Eq for Chunk {}
|
|||||||
|
|
||||||
impl PartialEq for Chunk {
|
impl PartialEq for Chunk {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
// Do not compare stack size because the chunks created for testing will not have one due to
|
|
||||||
// not being compiled.
|
|
||||||
|
|
||||||
self.name == other.name
|
self.name == other.name
|
||||||
&& self.r#type == other.r#type
|
&& self.r#type == other.r#type
|
||||||
&& self.instructions == other.instructions
|
&& self.instructions == other.instructions
|
||||||
|
@ -25,11 +25,11 @@ mod type_checks;
|
|||||||
|
|
||||||
pub use error::CompileError;
|
pub use error::CompileError;
|
||||||
use parse_rule::{ParseRule, Precedence};
|
use parse_rule::{ParseRule, Precedence};
|
||||||
|
use tracing::{debug, info};
|
||||||
use type_checks::{check_math_type, check_math_types};
|
use type_checks::{check_math_type, check_math_types};
|
||||||
|
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
|
||||||
use colored::Colorize;
|
|
||||||
use optimize::control_flow_register_consolidation;
|
use optimize::control_flow_register_consolidation;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
@ -58,8 +58,7 @@ pub fn compile(source: &str) -> Result<Chunk, DustError> {
|
|||||||
.compile()
|
.compile()
|
||||||
.map_err(|error| DustError::compile(error, source))?;
|
.map_err(|error| DustError::compile(error, source))?;
|
||||||
|
|
||||||
let name = DustString::from("main");
|
let chunk = compiler.finish(None::<DustString>);
|
||||||
let chunk = compiler.finish(Some(name));
|
|
||||||
|
|
||||||
Ok(chunk)
|
Ok(chunk)
|
||||||
}
|
}
|
||||||
@ -136,9 +135,9 @@ impl<'src> Compiler<'src> {
|
|||||||
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, CompileError> {
|
pub fn new(mut lexer: Lexer<'src>) -> Result<Self, CompileError> {
|
||||||
let (current_token, current_position) = lexer.next_token()?;
|
let (current_token, current_position) = lexer.next_token()?;
|
||||||
|
|
||||||
log::info!(
|
info!(
|
||||||
"Begin chunk with {} at {}",
|
"Begin chunk with {} at {}",
|
||||||
current_token.to_string().bold(),
|
current_token.to_string(),
|
||||||
current_position.to_string()
|
current_position.to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -173,7 +172,7 @@ impl<'src> Compiler<'src> {
|
|||||||
/// will allow [`Compiler::function_name`] to be both the name used for recursive calls and the
|
/// will allow [`Compiler::function_name`] to be both the name used for recursive calls and the
|
||||||
/// name of the function when it is compiled. The name can later be seen in the VM's call stack.
|
/// name of the function when it is compiled. The name can later be seen in the VM's call stack.
|
||||||
pub fn finish(self, name: Option<impl Into<DustString>>) -> Chunk {
|
pub fn finish(self, name: Option<impl Into<DustString>>) -> Chunk {
|
||||||
log::info!("End chunk");
|
info!("End chunk");
|
||||||
|
|
||||||
let (instructions, positions): (SmallVec<[Instruction; 32]>, SmallVec<[Span; 32]>) = self
|
let (instructions, positions): (SmallVec<[Instruction; 32]>, SmallVec<[Span; 32]>) = self
|
||||||
.instructions
|
.instructions
|
||||||
@ -210,6 +209,10 @@ impl<'src> Compiler<'src> {
|
|||||||
self.parse(Precedence::None)?;
|
self.parse(Precedence::None)?;
|
||||||
|
|
||||||
if matches!(self.current_token, Token::Eof | Token::RightBrace) {
|
if matches!(self.current_token, Token::Eof | Token::RightBrace) {
|
||||||
|
if self.get_last_operation() == Some(Operation::RETURN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
self.parse_implicit_return()?;
|
self.parse_implicit_return()?;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -244,9 +247,9 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
let (new_token, position) = self.lexer.next_token()?;
|
let (new_token, position) = self.lexer.next_token()?;
|
||||||
|
|
||||||
log::info!(
|
info!(
|
||||||
"Parsing {} at {}",
|
"Parsing {} at {}",
|
||||||
new_token.to_string().bold(),
|
new_token.to_string(),
|
||||||
position.to_string()
|
position.to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -299,7 +302,7 @@ impl<'src> Compiler<'src> {
|
|||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
) -> (u8, u8) {
|
) -> (u8, u8) {
|
||||||
log::info!("Declaring local {identifier}");
|
info!("Declaring local {identifier}");
|
||||||
|
|
||||||
let identifier = Value::Concrete(ConcreteValue::string(identifier));
|
let identifier = Value::Concrete(ConcreteValue::string(identifier));
|
||||||
let identifier_index = self.push_or_get_constant(identifier);
|
let identifier_index = self.push_or_get_constant(identifier);
|
||||||
@ -447,9 +450,9 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit_instruction(&mut self, instruction: Instruction, r#type: Type, position: Span) {
|
fn emit_instruction(&mut self, instruction: Instruction, r#type: Type, position: Span) {
|
||||||
log::debug!(
|
debug!(
|
||||||
"Emitting {} at {}",
|
"Emitting {} at {}",
|
||||||
instruction.operation().to_string().bold(),
|
instruction.operation().to_string(),
|
||||||
position.to_string()
|
position.to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -965,11 +968,11 @@ impl<'src> Compiler<'src> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let jump = &mut instructions[1].0;
|
let old_jump = &mut instructions[1].0;
|
||||||
let jump_index = instructions_length - group_index * 3 - 1;
|
let jump_index = instructions_length - group_index * 3 - 1;
|
||||||
let short_circuit_distance = (instructions_length - jump_index) as u8;
|
let short_circuit_distance = (instructions_length - jump_index) as u8;
|
||||||
|
|
||||||
*jump = Instruction::jump(short_circuit_distance, true);
|
*old_jump = Instruction::jump(short_circuit_distance, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1681,9 +1684,9 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
fn parse(&mut self, precedence: Precedence) -> Result<(), CompileError> {
|
fn parse(&mut self, precedence: Precedence) -> Result<(), CompileError> {
|
||||||
if let Some(prefix_parser) = ParseRule::from(&self.current_token).prefix {
|
if let Some(prefix_parser) = ParseRule::from(&self.current_token).prefix {
|
||||||
log::debug!(
|
debug!(
|
||||||
"{} is prefix with precedence {precedence}",
|
"{} is prefix with precedence {precedence}",
|
||||||
self.current_token.to_string().bold(),
|
self.current_token.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
prefix_parser(self)?;
|
prefix_parser(self)?;
|
||||||
@ -1693,9 +1696,9 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
while precedence <= infix_rule.precedence {
|
while precedence <= infix_rule.precedence {
|
||||||
if let Some(infix_parser) = infix_rule.infix {
|
if let Some(infix_parser) = infix_rule.infix {
|
||||||
log::debug!(
|
debug!(
|
||||||
"{} is infix with precedence {precedence}",
|
"{} is infix with precedence {precedence}",
|
||||||
self.current_token.to_string().bold(),
|
self.current_token.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.current_token == Token::Equal {
|
if self.current_token == Token::Equal {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! Functions used by the compiler to optimize a chunk's bytecode during compilation.
|
//! Functions used by the compiler to optimize a chunk's bytecode during compilation.
|
||||||
|
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::{Compiler, Instruction, Operation};
|
use crate::{Compiler, Instruction, Operation};
|
||||||
|
|
||||||
/// Optimizes a control flow pattern to use fewer registers and avoid using a `POINT` instruction.
|
/// Optimizes a control flow pattern to use fewer registers and avoid using a `POINT` instruction.
|
||||||
@ -44,7 +46,7 @@ pub fn control_flow_register_consolidation(compiler: &mut Compiler) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("Consolidating registers for control flow optimization");
|
debug!("Consolidating registers for control flow optimization");
|
||||||
|
|
||||||
let first_loader_index = compiler.instructions.len() - 2;
|
let first_loader_index = compiler.instructions.len() - 2;
|
||||||
let (first_loader, _, _) = &mut compiler.instructions.get_mut(first_loader_index).unwrap();
|
let (first_loader, _, _) = &mut compiler.instructions.get_mut(first_loader_index).unwrap();
|
||||||
|
@ -2,6 +2,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smartstring::{LazyCompact, SmartString};
|
use smartstring::{LazyCompact, SmartString};
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{Type, Value, ValueError};
|
use crate::{Type, Value, ValueError};
|
||||||
|
|
||||||
@ -281,7 +282,7 @@ impl ConcreteValue {
|
|||||||
|
|
||||||
impl Clone for ConcreteValue {
|
impl Clone for ConcreteValue {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
log::trace!("Cloning concrete value {}", self);
|
trace!("Cloning concrete value {}", self);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ConcreteValue::Boolean(boolean) => ConcreteValue::Boolean(*boolean),
|
ConcreteValue::Boolean(boolean) => ConcreteValue::Boolean(*boolean),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{DustString, Function, FunctionType, Local, Span, Value};
|
use crate::{DustString, Function, FunctionType, Local, Span, Value};
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn follow_pointer(&self, pointer: Pointer) -> &Value {
|
pub(crate) fn follow_pointer(&self, pointer: Pointer) -> &Value {
|
||||||
log::trace!("Follow pointer {pointer}");
|
trace!("Follow pointer {pointer}");
|
||||||
|
|
||||||
match pointer {
|
match pointer {
|
||||||
Pointer::Stack(register_index) => self.open_register(register_index),
|
Pointer::Stack(register_index) => self.open_register(register_index),
|
||||||
@ -88,7 +89,7 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_register(&self, register_index: u8) -> &Register {
|
pub fn get_register(&self, register_index: u8) -> &Register {
|
||||||
log::trace!("Get register R{register_index}");
|
trace!("Get register R{register_index}");
|
||||||
|
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
|
|
||||||
@ -113,7 +114,7 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_register(&self, register_index: u8) -> &Value {
|
pub fn open_register(&self, register_index: u8) -> &Value {
|
||||||
log::trace!("Open register R{register_index}");
|
trace!("Open register R{register_index}");
|
||||||
|
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_register_allow_empty(&self, register_index: u8) -> Option<&Value> {
|
pub fn open_register_allow_empty(&self, register_index: u8) -> Option<&Value> {
|
||||||
log::trace!("Open register R{register_index}");
|
trace!("Open register R{register_index}");
|
||||||
|
|
||||||
let register_index = register_index as usize;
|
let register_index = register_index as usize;
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::{
|
instruction::{
|
||||||
Call, CallNative, Close, LoadBoolean, LoadConstant, LoadFunction, LoadList, LoadSelf, Point,
|
Call, CallNative, Close, LoadBoolean, LoadConstant, LoadFunction, LoadList, LoadSelf, Point,
|
||||||
@ -119,7 +121,7 @@ pub fn load_constant(instruction_data: InstructionData, record: &mut Record) ->
|
|||||||
} = instruction_data.into();
|
} = instruction_data.into();
|
||||||
let register = Register::Pointer(Pointer::Constant(constant_index));
|
let register = Register::Pointer(Pointer::Constant(constant_index));
|
||||||
|
|
||||||
log::trace!("Load constant {constant_index} into R{destination}");
|
trace!("Load constant {constant_index} into R{destination}");
|
||||||
|
|
||||||
record.set_register(destination, register);
|
record.set_register(destination, register);
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use tracing::{info, trace};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
vm::{FunctionCall, Register},
|
vm::{FunctionCall, Register},
|
||||||
Chunk, DustString, Value,
|
Chunk, DustString, Value,
|
||||||
@ -26,7 +28,7 @@ impl Thread {
|
|||||||
pub fn run(&mut self) -> Option<Value> {
|
pub fn run(&mut self) -> Option<Value> {
|
||||||
let mut active = &mut self.records[0];
|
let mut active = &mut self.records[0];
|
||||||
|
|
||||||
log::info!(
|
info!(
|
||||||
"Starting thread with {}",
|
"Starting thread with {}",
|
||||||
active
|
active
|
||||||
.as_function()
|
.as_function()
|
||||||
@ -44,7 +46,7 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
log::trace!(
|
trace!(
|
||||||
"Run \"{}\" | Record = {} | IP = {}",
|
"Run \"{}\" | Record = {} | IP = {}",
|
||||||
active
|
active
|
||||||
.name()
|
.name()
|
||||||
@ -78,7 +80,7 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if record_index == active.index() as usize {
|
if record_index == active.index() as usize {
|
||||||
log::trace!("Recursion detected");
|
trace!("Recursion detected");
|
||||||
|
|
||||||
self.call_stack.last_mut_or_panic().ip = active.ip;
|
self.call_stack.last_mut_or_panic().ip = active.ip;
|
||||||
active.ip = 0;
|
active.ip = 0;
|
||||||
@ -134,7 +136,7 @@ impl Thread {
|
|||||||
let outer_call = self.call_stack.last_or_panic();
|
let outer_call = self.call_stack.last_or_panic();
|
||||||
let record_index = outer_call.record_index as usize;
|
let record_index = outer_call.record_index as usize;
|
||||||
|
|
||||||
log::trace!("Return from {returning_call} to {outer_call}");
|
trace!("Return from {returning_call} to {outer_call}");
|
||||||
|
|
||||||
if should_return_value {
|
if should_return_value {
|
||||||
let return_register = active
|
let return_register = active
|
||||||
|
Loading…
Reference in New Issue
Block a user