From 07f8b36c994a4222bd00cd9d9e039fe12d60bbd2 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 16 Feb 2025 22:55:55 -0500 Subject: [PATCH] Decide on an optimization strategy for the VM --- Cargo.lock | 204 ++-- dust-cli/Cargo.toml | 8 +- dust-cli/src/main.rs | 16 +- dust-lang/Cargo.toml | 12 +- dust-lang/src/chunk/disassembler.rs | 67 +- dust-lang/src/chunk/mod.rs | 12 +- dust-lang/src/compiler/mod.rs | 129 +-- dust-lang/src/native_function/assert.rs | 18 +- dust-lang/src/native_function/io.rs | 42 +- dust-lang/src/native_function/random.rs | 18 +- dust-lang/src/value/abstract_list.rs | 17 +- dust-lang/src/vm/action/add.rs | 293 +++--- dust-lang/src/vm/action/less.rs | 209 ++-- dust-lang/src/vm/action/mod.rs | 1167 ++--------------------- dust-lang/src/vm/call_frame.rs | 594 ++++++++++-- dust-lang/src/vm/mod.rs | 7 +- dust-lang/src/vm/thread.rs | 811 +--------------- 17 files changed, 1229 insertions(+), 2395 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbf7cb1..1635ded 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "annotate-snippets" version = "0.11.5" @@ -18,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width 0.2.0", + "unicode-width", ] [[package]] @@ -80,17 +86,6 @@ dependencies = [ "critical-section", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -103,12 +98,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.8.0" @@ -143,21 +132,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clap" -version = "2.34.0" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "bitflags 1.3.2", - "textwrap", - "unicode-width 0.1.14", + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", ] [[package]] name = "clap" -version = "4.5.28" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" +checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" dependencies = [ "clap_builder", "clap_derive", @@ -165,9 +170,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" dependencies = [ "anstream", "anstyle", @@ -218,24 +223,24 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ - "atty", + "anes", "cast", - "clap 2.34.0", + "ciborium", + "clap", "criterion-plot", - "csv", + "is-terminal", "itertools", - "lazy_static", "num-traits", + "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_cbor", "serde_derive", "serde_json", "tinytemplate", @@ -244,9 +249,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", @@ -293,31 +298,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "csv" -version = "1.3.1" +name = "crunchy" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] -name = "csv-core" -version = "0.1.11" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "memchr", + "powerfmt", ] [[package]] name = "dust-cli" version = "0.5.0" dependencies = [ - "clap 4.5.28", + "clap", "dust-lang", "postcard", "ron", @@ -381,9 +380,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hash32" @@ -422,12 +425,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "indexmap" @@ -439,6 +439,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is-terminal" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -520,6 +531,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.19" @@ -592,6 +609,12 @@ dependencies = [ "serde", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -705,7 +728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64", - "bitflags 2.8.0", + "bitflags", "serde", "serde_derive", ] @@ -725,7 +748,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -774,16 +797,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.217" @@ -831,9 +844,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" dependencies = [ "serde", ] @@ -898,15 +911,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width 0.1.14", -] - [[package]] name = "thread_local" version = "1.1.8" @@ -917,6 +921,37 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -980,6 +1015,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", + "time", "tracing-core", "tracing-log", ] @@ -990,12 +1026,6 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode-width" version = "0.2.0" diff --git a/dust-cli/Cargo.toml b/dust-cli/Cargo.toml index e3c4e08..5a8846e 100644 --- a/dust-cli/Cargo.toml +++ b/dust-cli/Cargo.toml @@ -13,7 +13,7 @@ name = "dust" path = "src/main.rs" [dependencies] -clap = { version = "4.5.14", features = [ +clap = { version = "4.5.29", features = [ "cargo", "color", "derive", @@ -21,9 +21,9 @@ clap = { version = "4.5.14", features = [ "wrap_help", ] } dust-lang = { path = "../dust-lang" } -postcard = "1.0.10" +postcard = "1.1.1" ron = "0.8.1" -serde_json = "1.0.133" +serde_json = "1.0.138" serde_yaml = "0.9.34" tracing = "0.1.41" -tracing-subscriber = "0.3.19" +tracing-subscriber = { version = "0.3.19", features = ["time"] } diff --git a/dust-cli/src/main.rs b/dust-cli/src/main.rs index 812e69c..37d2404 100644 --- a/dust-cli/src/main.rs +++ b/dust-cli/src/main.rs @@ -1,19 +1,19 @@ use std::{ fs::read_to_string, - io::{self, Read, stdout}, + io::{self, stdout, Read}, path::PathBuf, time::{Duration, Instant}, }; use clap::{ - Args, ColorChoice, Error, Parser, Subcommand, ValueEnum, ValueHint, - builder::{Styles, styling::AnsiColor}, + builder::{styling::AnsiColor, Styles}, crate_authors, crate_description, crate_version, error::ErrorKind, + Args, ColorChoice, Error, Parser, Subcommand, ValueEnum, ValueHint, }; use dust_lang::{CompileError, Compiler, DustError, DustString, Lexer, Span, Token, Vm}; -use tracing::{Level, subscriber::set_global_default}; -use tracing_subscriber::FmtSubscriber; +use tracing::{subscriber::set_global_default, Level}; +use tracing_subscriber::{fmt::time::Uptime, FmtSubscriber}; const STYLES: Styles = Styles::styled() .header(AnsiColor::BrightMagenta.on_default().bold().underline()) @@ -180,9 +180,11 @@ fn main() { let mode = mode.unwrap_or(Command::Run(run)); let subscriber = FmtSubscriber::builder() .with_max_level(log_level) - .with_thread_names(true) + .with_ansi(true) .with_file(false) - .without_time() + .with_line_number(false) + .with_thread_names(true) + .with_timer(Uptime::from(start_time)) .finish(); set_global_default(subscriber).expect("Failed to set tracing subscriber"); diff --git a/dust-lang/Cargo.toml b/dust-lang/Cargo.toml index 810d1c6..1c240a9 100644 --- a/dust-lang/Cargo.toml +++ b/dust-lang/Cargo.toml @@ -9,11 +9,11 @@ repository.workspace = true version.workspace = true [dependencies] -annotate-snippets = "0.11.4" -colored = "2.1.0" +annotate-snippets = "0.11.5" +colored = "2.2.0" rand = "0.8.5" -serde = { version = "1.0.203", features = ["derive", "rc"] } -serde_json = "1.0.117" +serde = { version = "1.0.217", features = ["derive", "rc"] } +serde_json = "1.0.138" getrandom = { version = "0.2", features = [ "js", ] } # Indirect dependency, for WASM builds @@ -22,10 +22,10 @@ smartstring = { version = "1.0.1", features = [ ], default-features = false } tracing = "0.1.41" crossbeam-channel = "0.5.14" -smallvec = { version = "1.13.2", features = ["serde", "const_generics"] } +smallvec = { version = "1.14.0", features = ["serde", "const_generics"] } [dev-dependencies] -criterion = { version = "0.3.4", features = ["html_reports"] } +criterion = { version = "0.5.1", features = ["html_reports"] } [[bench]] name = "addictive_addition" diff --git a/dust-lang/src/chunk/disassembler.rs b/dust-lang/src/chunk/disassembler.rs index 5e87c7e..332dd03 100644 --- a/dust-lang/src/chunk/disassembler.rs +++ b/dust-lang/src/chunk/disassembler.rs @@ -41,7 +41,7 @@ use std::io::{self, Write}; use colored::{ColoredString, Colorize}; -use crate::{Chunk, Local}; +use crate::{Chunk, Local, Type}; const INSTRUCTION_COLUMNS: [(&str, usize); 4] = [("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 41)]; @@ -321,7 +321,7 @@ impl<'a, W: Write> Disassembler<'a, W> { { let identifier_display = self .chunk - .constants + .string_constants .get(*identifier_index as usize) .map(|value| value.to_string()) .unwrap_or_else(|| "unknown".to_string()); @@ -354,8 +354,56 @@ impl<'a, W: Write> Disassembler<'a, W> { self.write_center_border(&column_name_line)?; self.write_center_border(CONSTANT_BORDERS[1])?; - for (index, value) in self.chunk.constants.iter().enumerate() { - let type_display = value.r#type().to_string(); + for (index, value) in self.chunk.character_constants.iter().enumerate() { + let type_display = Type::Character.to_string(); + let value_display = { + let mut value_string = value.to_string(); + + if value_string.len() > 26 { + value_string = format!("{value_string:.23}..."); + } + + value_string + }; + let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│"); + + self.write_center_border(&constant_display)?; + } + + for (index, value) in self.chunk.float_constants.iter().enumerate() { + let type_display = Type::Float.to_string(); + let value_display = { + let mut value_string = value.to_string(); + + if value_string.len() > 26 { + value_string = format!("{value_string:.23}..."); + } + + value_string + }; + let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│"); + + self.write_center_border(&constant_display)?; + } + + for (index, value) in self.chunk.integer_constants.iter().enumerate() { + let type_display = Type::Integer.to_string(); + let value_display = { + let mut value_string = value.to_string(); + + if value_string.len() > 26 { + value_string = format!("{value_string:.23}..."); + } + + value_string + }; + let constant_display = format!("│{index:^5}│{type_display:^26}│{value_display:^26}│"); + + self.write_center_border(&constant_display)?; + } + + for (index, value) in self.chunk.string_constants.iter().enumerate() { + let type_display = Type::String.to_string(); let value_display = { let mut value_string = value.to_string(); @@ -420,7 +468,10 @@ impl<'a, W: Write> Disassembler<'a, W> { let info_line = format!( "{} instructions, {} constants, {} locals, returns {}", self.chunk.instructions.len(), - self.chunk.constants.len(), + self.chunk.character_constants.len() + + self.chunk.float_constants.len() + + self.chunk.integer_constants.len() + + self.chunk.string_constants.len(), self.chunk.locals.len(), self.chunk.r#type.return_type ); @@ -436,7 +487,11 @@ impl<'a, W: Write> Disassembler<'a, W> { self.write_local_section()?; } - if !self.chunk.constants.is_empty() { + if !self.chunk.character_constants.is_empty() + || !self.chunk.float_constants.is_empty() + || !self.chunk.integer_constants.is_empty() + || !self.chunk.string_constants.is_empty() + { self.write_constant_section()?; } diff --git a/dust-lang/src/chunk/mod.rs b/dust-lang/src/chunk/mod.rs index 94afffa..4e35e81 100644 --- a/dust-lang/src/chunk/mod.rs +++ b/dust-lang/src/chunk/mod.rs @@ -24,7 +24,7 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; -use crate::{ConcreteValue, DustString, Function, FunctionType, Instruction, Span}; +use crate::{DustString, Function, FunctionType, Instruction, Span}; /// Representation of a Dust program or function. /// @@ -36,7 +36,10 @@ pub struct Chunk { pub instructions: Vec, pub positions: Vec, - pub constants: Vec, + pub character_constants: Vec, + pub float_constants: Vec, + pub integer_constants: Vec, + pub string_constants: Vec, pub locals: Vec, pub prototypes: Vec>, @@ -107,7 +110,10 @@ impl PartialEq for Chunk { && self.r#type == other.r#type && self.instructions == other.instructions && self.positions == other.positions - && self.constants == other.constants + && self.character_constants == other.character_constants + && self.float_constants == other.float_constants + && self.integer_constants == other.integer_constants + && self.string_constants == other.string_constants && self.locals == other.locals && self.prototypes == other.prototypes } diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 6f6a210..1cfd4af 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -24,15 +24,15 @@ mod type_checks; pub use error::CompileError; use parse_rule::{ParseRule, Precedence}; -use tracing::{Level, debug, info, span}; +use tracing::{debug, info, span, Level}; use type_checks::{check_math_type, check_math_types}; use std::{mem::replace, sync::Arc}; use crate::{ - Chunk, ConcreteValue, DustError, DustString, FunctionType, Instruction, Lexer, Local, - NativeFunction, Operand, Operation, Scope, Span, Token, TokenKind, Type, instruction::{Jump, Point, Return, TypeCode}, + Chunk, DustError, DustString, FunctionType, Instruction, Lexer, Local, NativeFunction, Operand, + Operation, Scope, Span, Token, TokenKind, Type, }; /// Compiles the input and returns a chunk. @@ -83,9 +83,21 @@ pub struct Compiler<'src> { /// The types are discarded after compilation. instructions: Vec<(Instruction, Type, Span)>, - /// Constants that have been compiled. These are assigned to the chunk when [`Compiler::finish`] - /// is called. - constants: Vec, + /// Character constants that have been compiled. These are assigned to the chunk when + /// [`Compiler::finish`] is called. + character_constants: Vec, + + /// Float constants that have been compiled. These are assigned to the chunk when + /// [`Compiler::finish`] is called. + float_constants: Vec, + + /// Integer constants that have been compiled. These are assigned to the chunk when + /// [`Compiler::finish`] is called. + integer_constants: Vec, + + /// String constants that have been compiled. These are assigned to the chunk when + /// [`Compiler::finish`] is called. + string_constants: Vec, /// Block-local variables and their types. The locals are assigned to the chunk when /// [`Compiler::finish`] is called. The types are discarded after compilation. @@ -161,7 +173,10 @@ impl<'src> Compiler<'src> { function_name, r#type: FunctionType::default(), instructions: Vec::new(), - constants: Vec::new(), + character_constants: Vec::new(), + float_constants: Vec::new(), + integer_constants: Vec::new(), + string_constants: Vec::new(), locals: Vec::new(), prototypes: Vec::new(), lexer, @@ -241,7 +256,10 @@ impl<'src> Compiler<'src> { r#type: self.r#type, instructions, positions, - constants: self.constants, + character_constants: self.character_constants, + float_constants: self.float_constants, + integer_constants: self.integer_constants, + string_constants: self.string_constants, locals: self.locals, prototypes: self.prototypes, boolean_register_count, @@ -329,7 +347,10 @@ impl<'src> Compiler<'src> { .iter() .rev() .find_map(|(instruction, r#type, _)| { - if r#type == &Type::Integer { + if (instruction.operation() == Operation::LOAD_CONSTANT + && instruction.b_type() == TypeCode::INTEGER) + || r#type == &Type::Integer + { Some(instruction.a_field() + 1) } else { None @@ -416,12 +437,7 @@ impl<'src> Compiler<'src> { .enumerate() .rev() .find_map(|(index, local)| { - let constant = self.constants.get(local.identifier_index as usize)?; - let identifier = if let ConcreteValue::String(identifier) = constant { - identifier - } else { - return None; - }; + let identifier = self.string_constants.get(local.identifier_index as usize)?; if identifier == identifier_text { Some(index as u16) @@ -445,8 +461,8 @@ impl<'src> Compiler<'src> { ) -> (u16, u16) { info!("Declaring local {identifier}"); - let identifier = ConcreteValue::string(identifier); - let identifier_index = self.push_or_get_constant(identifier); + let identifier = DustString::from(identifier); + let identifier_index = self.push_or_get_constant_string(identifier); let local_index = self.locals.len() as u16; self.locals.push(Local::new( @@ -462,23 +478,23 @@ impl<'src> Compiler<'src> { fn get_identifier(&self, local_index: u16) -> Option { self.locals.get(local_index as usize).and_then(|local| { - self.constants + self.string_constants .get(local.identifier_index as usize) .map(|value| value.to_string()) }) } - fn push_or_get_constant(&mut self, value: ConcreteValue) -> u16 { + fn push_or_get_constant_string(&mut self, string: DustString) -> u16 { if let Some(index) = self - .constants + .string_constants .iter() - .position(|constant| constant == &value) + .position(|constant| constant == &string) { index as u16 } else { - let index = self.constants.len() as u16; + let index = self.string_constants.len() as u16; - self.constants.push(value); + self.string_constants.push(string); index } @@ -563,28 +579,6 @@ impl<'src> Compiler<'src> { self.instructions.push((instruction, r#type, position)); } - fn emit_constant( - &mut self, - constant: ConcreteValue, - position: Span, - ) -> Result<(), CompileError> { - let r#type = constant.r#type(); - let constant_index = self.push_or_get_constant(constant); - let destination = match r#type { - Type::Character => self.next_character_register(), - Type::Float => self.next_float_register(), - Type::Integer => self.next_integer_register(), - Type::String => self.next_string_register(), - _ => unreachable!(), - }; - let load_constant = - Instruction::load_constant(destination, constant_index, r#type.type_code(), false); - - self.emit_instruction(load_constant, r#type, position); - - Ok(()) - } - fn parse_boolean(&mut self) -> Result<(), CompileError> { let position = self.current_position; @@ -637,9 +631,13 @@ impl<'src> Compiler<'src> { if let Token::Character(character) = self.current_token { self.advance()?; - let value = ConcreteValue::Character(character); + let destination = self.next_character_register(); + let constant_index = self.character_constants.len() as u16; + let load_constant = + Instruction::load_constant(destination, constant_index, TypeCode::CHARACTER, false); - self.emit_constant(value, position)?; + self.character_constants.push(character); + self.emit_instruction(load_constant, Type::Character, position); Ok(()) } else { @@ -663,9 +661,13 @@ impl<'src> Compiler<'src> { error, position: self.previous_position, })?; - let value = ConcreteValue::Float(float); + let destination = self.next_float_register(); + let constant_index = self.float_constants.len() as u16; + let load_constant = + Instruction::load_constant(destination, constant_index, TypeCode::FLOAT, false); - self.emit_constant(value, position)?; + self.float_constants.push(float); + self.emit_instruction(load_constant, Type::Float, position); Ok(()) } else { @@ -683,7 +685,7 @@ impl<'src> Compiler<'src> { if let Token::Integer(text) = self.current_token { self.advance()?; - let mut integer_value = 0_i64; + let mut integer = 0_i64; for digit in text.chars() { let digit = if let Some(digit) = digit.to_digit(10) { @@ -692,12 +694,16 @@ impl<'src> Compiler<'src> { continue; }; - integer_value = integer_value * 10 + digit; + integer = integer * 10 + digit; } - let value = ConcreteValue::Integer(integer_value); + let constant_index = self.integer_constants.len() as u16; + let destination = self.next_integer_register(); + let load_constant = + Instruction::load_constant(destination, constant_index, TypeCode::INTEGER, false); - self.emit_constant(value, position)?; + self.integer_constants.push(integer); + self.emit_instruction(load_constant, Type::Integer, position); Ok(()) } else { @@ -715,9 +721,13 @@ impl<'src> Compiler<'src> { if let Token::String(text) = self.current_token { self.advance()?; - let value = ConcreteValue::string(text); + let string = DustString::from(text); + let constant_index = self.push_or_get_constant_string(string); + let destination = self.next_string_register(); + let load_constant = + Instruction::load_constant(destination, constant_index, TypeCode::STRING, false); - self.emit_constant(value, position)?; + self.emit_instruction(load_constant, Type::String, position); Ok(()) } else { @@ -932,13 +942,8 @@ impl<'src> Compiler<'src> { } fn parse_comparison_binary(&mut self) -> Result<(), CompileError> { - if let Some( - [ - Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, - _, - _, - ], - ) = self.get_last_operations() + if let Some([Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL, _, _]) = + self.get_last_operations() { return Err(CompileError::ComparisonChain { position: self.current_position, diff --git a/dust-lang/src/native_function/assert.rs b/dust-lang/src/native_function/assert.rs index 798c517..28d96e7 100644 --- a/dust-lang/src/native_function/assert.rs +++ b/dust-lang/src/native_function/assert.rs @@ -1,15 +1,27 @@ use std::{ops::Range, panic}; -use crate::vm::Thread; +use crate::vm::{RuntimeValue, Thread}; pub fn panic(data: &mut Thread, _: usize, argument_range: Range) { + let current_frame = data.current_frame(); let position = data.current_position(); let mut message = format!("Dust panic at {position}!"); for register_index in argument_range { - let string = data.get_string_register(register_index); + let string_value = current_frame.get_string_from_register(register_index); + + match string_value { + RuntimeValue::Raw(value) => { + message.push_str(value.as_str()); + } + RuntimeValue::Rc(rc) => { + message.push_str(rc.as_str()); + } + RuntimeValue::RefCell(ref_cell) => { + message.push_str(ref_cell.borrow().as_str()); + } + } - message.push_str(string); message.push('\n'); } diff --git a/dust-lang/src/native_function/io.rs b/dust-lang/src/native_function/io.rs index 118905f..7912926 100644 --- a/dust-lang/src/native_function/io.rs +++ b/dust-lang/src/native_function/io.rs @@ -1,10 +1,11 @@ -use std::io::{Write, stdin, stdout}; +use std::io::{stdin, stdout, Write}; use std::ops::Range; +use crate::vm::{Register, RuntimeValue, Thread}; use crate::DustString; -use crate::vm::{Register, Thread}; pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { + let current_frame = data.current_frame_mut(); let mut buffer = String::new(); if stdin().read_line(&mut buffer).is_ok() { @@ -12,30 +13,53 @@ pub fn read_line(data: &mut Thread, destination: usize, _argument_range: Range) { + let current_frame = data.current_frame(); let mut stdout = stdout(); for register_index in argument_range { - let value = data.get_string_register(register_index); - let _ = stdout.write(value.to_string().as_bytes()); + let value = current_frame.get_string_from_register(register_index); + + match value { + RuntimeValue::Raw(value) => { + let _ = stdout.write(value.as_bytes()); + } + RuntimeValue::Rc(value) => { + let _ = stdout.write(value.as_bytes()); + } + RuntimeValue::RefCell(ref_cell) => { + let _ = stdout.write(ref_cell.borrow().as_bytes()); + } + } } let _ = stdout.flush(); } pub fn write_line(data: &mut Thread, _: usize, argument_range: Range) { + let current_frame = data.current_frame(); let mut stdout = stdout().lock(); for register_index in argument_range { - let value = data.get_string_register(register_index); - let _ = stdout.write(value.to_string().as_bytes()); + let value = current_frame.get_string_from_register(register_index); + + match value { + RuntimeValue::Raw(value) => { + let _ = stdout.write(value.as_bytes()); + } + RuntimeValue::Rc(value) => { + let _ = stdout.write(value.as_bytes()); + } + RuntimeValue::RefCell(ref_cell) => { + let _ = stdout.write(ref_cell.borrow().as_bytes()); + } + } } let _ = stdout.write(b"\n"); diff --git a/dust-lang/src/native_function/random.rs b/dust-lang/src/native_function/random.rs index 90b149c..75869a7 100644 --- a/dust-lang/src/native_function/random.rs +++ b/dust-lang/src/native_function/random.rs @@ -2,9 +2,10 @@ use std::ops::Range; use rand::Rng; -use crate::vm::{Register, Thread}; +use crate::vm::{Register, RuntimeValue, Thread}; pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range) { + let current_frame = data.current_frame_mut(); let mut argument_range_iter = argument_range.into_iter(); let (min, max) = { let mut min = None; @@ -13,18 +14,23 @@ pub fn random_int(data: &mut Thread, destination: usize, argument_range: Range DustString { + let current_frame = thread.current_frame(); let mut display = DustString::new(); display.push('['); @@ -25,12 +26,14 @@ impl AbstractList { } let item_display = match self.item_type { - TypeCode::BOOLEAN => thread.get_pointer_to_boolean(pointer).to_string(), - TypeCode::BYTE => thread.get_pointer_to_byte(pointer).to_string(), - TypeCode::CHARACTER => thread.get_pointer_to_character(pointer).to_string(), - TypeCode::FLOAT => thread.get_pointer_to_float(pointer).to_string(), - TypeCode::INTEGER => thread.get_pointer_to_integer(pointer).to_string(), - TypeCode::STRING => thread.get_pointer_to_string(pointer).to_string(), + TypeCode::BOOLEAN => current_frame.get_boolean_from_pointer(pointer).to_string(), + TypeCode::BYTE => current_frame.get_byte_from_pointer(pointer).to_string(), + TypeCode::CHARACTER => current_frame + .get_character_from_pointer(pointer) + .to_string(), + TypeCode::FLOAT => current_frame.get_float_from_pointer(pointer).to_string(), + TypeCode::INTEGER => current_frame.get_integer_from_pointer(pointer).to_string(), + TypeCode::STRING => current_frame.get_string_from_pointer(pointer).to_string(), _ => todo!(), }; @@ -57,7 +60,7 @@ impl Display for AbstractList { write!(f, "[")?; for pointer in &self.item_pointers { - write!(f, "{}", pointer)?; + write!(f, "{:?}", pointer)?; } write!(f, "]") diff --git a/dust-lang/src/vm/action/add.rs b/dust-lang/src/vm/action/add.rs index 6162e83..fbbea7d 100644 --- a/dust-lang/src/vm/action/add.rs +++ b/dust-lang/src/vm/action/add.rs @@ -1,68 +1,63 @@ +use std::ops::Add; + +use tracing::trace; + use crate::{ instruction::InstructionFields, - vm::{Register, Thread}, + vm::{call_frame::RuntimeValue, Thread}, DustString, }; pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_is_constant = instruction.c_is_constant; - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let sum = left_value.saturating_add(*right_value); + let destination_index = instruction.a_field as usize; + let left_index = instruction.b_field as usize; + let right_index = instruction.c_field as usize; - thread.set_byte_register(destination, Register::Value(sum)); + let current_frame = thread.current_frame_mut(); + let left_value = current_frame.get_byte_from_register(left_index); + let right_value = current_frame.get_byte_from_register(right_index); + let sum = left_value.add(right_value); + + current_frame + .registers + .bytes + .get_mut(destination_index) + .as_value_mut() + .set_inner(sum); } pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; + let destination_index = instruction.a_field as usize; + let left_index = instruction.b_field as usize; let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_character().unwrap() - } else { - unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(left_index) } else { - thread.get_character_register(left) + current_frame.get_character_from_register(left_index) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_character().unwrap() - } else { - unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(right) } else { - thread.get_character_register(right) + current_frame.get_character_from_register(right) }; - let mut concatenated = DustString::from(String::with_capacity(2)); + let concatenated = { + let mut concatenated = DustString::from(String::with_capacity(2)); - concatenated.push(*left_value); - concatenated.push(*right_value); + concatenated.push(left_value.clone_inner()); + concatenated.push(right_value.clone_inner()); - thread.set_string_register(destination, Register::Value(concatenated)); + RuntimeValue::Raw(concatenated) + }; + + current_frame + .registers + .strings + .get_mut(destination_index) + .set(concatenated); } pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -71,27 +66,26 @@ pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut T let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } + current_frame.get_float_constant(left) } else { - thread.get_float_register(left) + current_frame.get_float_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } + current_frame.get_float_constant(right) } else { - thread.get_float_register(right) + current_frame.get_float_from_register(right) }; - let sum = left_value + *right_value; + let sum = left_value.add(right_value); - thread.set_float_register(destination, Register::Value(sum)); + current_frame + .registers + .floats + .get_mut(destination) + .as_value_mut() + .set_inner(sum); } pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -100,27 +94,26 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } + current_frame.get_integer_constant(left) } else { - thread.get_integer_register(left) + current_frame.get_integer_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } + current_frame.get_integer_constant(right) } else { - thread.get_integer_register(right) + current_frame.get_integer_from_register(right) }; - let sum = left_value.saturating_add(*right_value); + let sum = left_value.add(right_value); - thread.set_integer_register(destination, Register::Value(sum)); + current_frame + .registers + .integers + .get_mut(destination) + .as_value_mut() + .set_inner(sum); } pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -129,31 +122,26 @@ pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_string().unwrap() - } else { - unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(left) } else { - thread.get_string_register(left) + current_frame.get_string_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_string().unwrap() - } else { - unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(right) } else { - thread.get_string_register(right) + current_frame.get_string_from_register(right) }; - let mut concatenated = - DustString::from(String::with_capacity(left_value.len() + right_value.len())); + let concatenated = DustString::from(format!("{left_value}{right_value}")); - concatenated.push_str(left_value); - concatenated.push_str(right_value); - - thread.set_string_register(destination, Register::Value(concatenated)); + current_frame + .registers + .strings + .get_mut(destination) + .as_value_mut() + .set_inner(concatenated); } pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -162,30 +150,26 @@ pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thre let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_character().unwrap() - } else { - unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(left) } else { - thread.get_character_register(left) + current_frame.get_character_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_string().unwrap() - } else { - unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(right) } else { - thread.get_string_register(right) + current_frame.get_string_from_register(right) }; - let mut concatenated = DustString::from(String::with_capacity(right_value.len() + 1)); + let concatenated = DustString::from(format!("{left_value}{right_value}")); - concatenated.push(*left_value); - concatenated.push_str(right_value); - - thread.set_string_register(destination, Register::Value(concatenated)); + current_frame + .registers + .strings + .get_mut(destination) + .as_value_mut() + .set_inner(concatenated); } pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -194,28 +178,89 @@ pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thre let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_string().unwrap() - } else { - unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(left) } else { - thread.get_string_register(left) + current_frame.get_string_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_character().unwrap() - } else { - unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(right) } else { - thread.get_character_register(right) + current_frame.get_character_from_register(right) }; - let mut concatenated = DustString::from(String::with_capacity(left_value.len() + 1)); + let concatenated = DustString::from(format!("{left_value}{right_value}")); - concatenated.push_str(left_value); - concatenated.push(*right_value); - - thread.set_string_register(destination, Register::Value(concatenated)); + current_frame + .registers + .strings + .get_mut(destination) + .as_value_mut() + .set_inner(concatenated); +} + +pub fn optimized_add_integer( + instruction: &InstructionFields, + thread: &mut Thread, + cache: &mut Option<[RuntimeValue; 3]>, +) { + if let Some([destination, left, right]) = cache { + trace!("ADD_INTEGERS_OPTIMIZED using cache"); + + let sum = left.add(right); + + *destination.borrow_mut() = sum; + } else { + let destination_index = instruction.a_field as usize; + let left_index = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right_index = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let current_frame = thread.current_frame_mut(); + let left_value = if left_is_constant { + let value = current_frame.get_integer_constant_mut(left_index).to_rc(); + + current_frame.constants.integers[left_index] = value.clone(); + + value + } else { + let value = current_frame + .get_integer_from_register_mut(left_index) + .to_ref_cell(); + + current_frame.registers.integers[left_index].set(value.clone()); + + value + }; + let right_value = if right_is_constant { + let value = current_frame.get_integer_constant_mut(right_index).to_rc(); + + current_frame.constants.integers[right_index] = value.clone(); + + value + } else { + let value = current_frame + .get_integer_from_register_mut(right_index) + .to_ref_cell(); + + current_frame.registers.integers[right_index].set(value.clone()); + + value + }; + let sum = left_value.add(&right_value); + let destination = { + let mut value = current_frame + .get_integer_from_register_mut(destination_index) + .to_ref_cell(); + + value.set_inner(sum); + + current_frame.registers.integers[destination_index].set(value.clone()); + + value + }; + + *cache = Some([destination, left_value, right_value]); + } } diff --git a/dust-lang/src/vm/action/less.rs b/dust-lang/src/vm/action/less.rs index b8dd71d..32ae9d3 100644 --- a/dust-lang/src/vm/action/less.rs +++ b/dust-lang/src/vm/action/less.rs @@ -1,31 +1,20 @@ -use crate::{instruction::InstructionFields, vm::Thread}; +use tracing::trace; + +use crate::{ + instruction::InstructionFields, + vm::{RuntimeValue, Thread}, +}; pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let left = instruction.b_field as usize; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_is_constant = instruction.c_is_constant; - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(left).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(right).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(right) - }; - let is_less_than = left_value < right_value; + let left_index = instruction.b_field as usize; + let right_index = instruction.c_field as usize; let comparator = instruction.d_field; + let current_frame = thread.current_frame_mut(); + let left_value = current_frame.get_boolean_from_register(left_index); + let right_value = current_frame.get_boolean_from_register(right_index); + let is_less_than = left_value < right_value; + if is_less_than == comparator { *ip += 1; } @@ -33,60 +22,38 @@ pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &m pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { let left = instruction.b_field as usize; - let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; - let right_is_constant = instruction.c_is_constant; - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let is_less_than = left_value < right_value; let comparator = instruction.d_field; + let current_frame = thread.current_frame_mut(); + let left_value = current_frame.get_byte_from_register(left); + let right_value = current_frame.get_byte_from_register(right); + let is_less_than = left_value < right_value; + if is_less_than == comparator { *ip += 1; } } pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let left = instruction.b_field as usize; + let left_index = instruction.b_field as usize; let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; + let right_index = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + let comparator = instruction.d_field; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_character().unwrap() - } else { - unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(left_index) } else { - thread.get_character_register(left) + current_frame.get_character_from_register(left_index) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_character().unwrap() - } else { - unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } - } + current_frame.get_character_constant(right_index) } else { - thread.get_character_register(right) + current_frame.get_character_from_register(right_index) }; let is_less_than = left_value < right_value; - let comparator = instruction.d_field; if is_less_than == comparator { *ip += 1; @@ -98,26 +65,20 @@ pub fn less_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + let comparator = instruction.d_field; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } + current_frame.get_float_constant(left) } else { - thread.get_float_register(left) + current_frame.get_float_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } + current_frame.get_float_constant(right) } else { - thread.get_float_register(right) + current_frame.get_float_from_register(right) }; let is_less_than = left_value < right_value; - let comparator = instruction.d_field; if is_less_than == comparator { *ip += 1; @@ -129,26 +90,20 @@ pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &m let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + let comparator = instruction.d_field; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } + current_frame.get_integer_constant(left) } else { - thread.get_integer_register(left) + current_frame.get_integer_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } + current_frame.get_integer_constant(right) } else { - thread.get_integer_register(right) + current_frame.get_integer_from_register(right) }; let is_less_than = left_value < right_value; - let comparator = instruction.d_field; if is_less_than == comparator { *ip += 1; @@ -160,28 +115,84 @@ pub fn less_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mu let left_is_constant = instruction.b_is_constant; let right = instruction.c_field as usize; let right_is_constant = instruction.c_is_constant; + let comparator = instruction.d_field; + + let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_string().unwrap() - } else { - unsafe { thread.get_constant(left).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(left) } else { - thread.get_string_register(left) + current_frame.get_string_from_register(left) }; let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_string().unwrap() - } else { - unsafe { thread.get_constant(right).as_string().unwrap_unchecked() } - } + current_frame.get_string_constant(right) } else { - thread.get_string_register(right) + current_frame.get_string_from_register(right) }; let is_less_than = left_value < right_value; - let comparator = instruction.d_field; if is_less_than == comparator { *ip += 1; } } + +pub fn optimized_less_integers( + ip: &mut usize, + instruction: &InstructionFields, + thread: &mut Thread, + cache: &mut Option<[RuntimeValue; 2]>, +) { + if let Some([left, right]) = cache { + trace!("LESS_INTEGERS_OPTIMIZED using cache"); + + let is_less_than = left < right; + + if is_less_than { + *ip += 1; + } + } else { + let left_index = instruction.b_field as usize; + let left_is_constant = instruction.b_is_constant; + let right_index = instruction.c_field as usize; + let right_is_constant = instruction.c_is_constant; + let comparator = instruction.d_field; + + let current_frame = thread.current_frame_mut(); + let left_value = if left_is_constant { + let value = current_frame.get_integer_constant_mut(left_index).to_rc(); + + current_frame.constants.integers[left_index] = value.clone(); + + value + } else { + let value = current_frame + .get_integer_from_register_mut(left_index) + .to_ref_cell(); + + current_frame.registers.integers[left_index].set(value.clone()); + + value + }; + let right_value = if right_is_constant { + let value = current_frame.get_integer_constant_mut(right_index).to_rc(); + + current_frame.constants.integers[right_index] = value.clone(); + + value + } else { + let value = current_frame + .get_integer_from_register_mut(right_index) + .to_ref_cell(); + + current_frame.registers.integers[right_index].set(value.clone()); + + value + }; + let is_less_than = left_value < right_value; + + if is_less_than == comparator { + *ip += 1; + } + + *cache = Some([left_value, right_value]); + } +} diff --git a/dust-lang/src/vm/action/mod.rs b/dust-lang/src/vm/action/mod.rs index a77e64d..da8f1e2 100644 --- a/dust-lang/src/vm/action/mod.rs +++ b/dust-lang/src/vm/action/mod.rs @@ -4,28 +4,28 @@ mod less; use add::{ add_bytes, add_character_string, add_characters, add_floats, add_integers, - add_string_character, add_strings, + add_string_character, add_strings, optimized_add_integer, }; use jump::jump; -use less::{less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings}; - -use tracing::trace; - -use std::{ - fmt::{self, Display, Formatter}, - ptr, +use less::{ + less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings, + optimized_less_integers, }; +use tracing::info; + +use std::fmt::{self, Display, Formatter}; + use crate::{ instruction::{InstructionFields, TypeCode}, - AbstractList, ConcreteValue, Operation, Value, + Operation, Value, }; -use super::{thread::Thread, Pointer, Register}; +use super::{call_frame::RuntimeValue, thread::Thread}; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct ActionSequence { - pub actions: Vec<(Action, InstructionFields)>, + actions: Vec<(Action, InstructionFields)>, } impl ActionSequence { @@ -74,10 +74,6 @@ impl ActionSequence { ActionSequence { actions } } - pub fn len(&self) -> usize { - self.actions.len() - } - pub fn run(&mut self, thread: &mut Thread) { let mut local_ip = 0; @@ -85,7 +81,7 @@ impl ActionSequence { let (action, instruction) = &mut self.actions[local_ip]; local_ip += 1; - trace!("Run {action}"); + info!("Run {action}"); match action { Action::Unoptimized { logic, instruction } => { @@ -94,78 +90,11 @@ impl ActionSequence { Action::Loop { actions } => { actions.run(thread); } - Action::OptimizedAddIntegers { - destination_pointer, - left_pointer, - right_pointer, - } => { - let left = if left_pointer.is_null() || !left_pointer.is_aligned() { - let left_index = instruction.b_field as usize; - let left_is_constant = instruction.b_is_constant; - let left_value = thread.get_integer(left_index, left_is_constant); - - *left_pointer = left_value; - - left_value - } else { - unsafe { &ptr::read(*left_pointer) } - }; - let right = if right_pointer.is_null() || !right_pointer.is_aligned() { - let right_index = instruction.c_field as usize; - let right_is_constant = instruction.c_is_constant; - let right_value = thread.get_integer(right_index, right_is_constant); - - *right_pointer = right_value; - - right_value - } else { - unsafe { &ptr::read(*right_pointer) } - }; - let sum = left.saturating_add(*right); - - if destination_pointer.is_null() || !destination_pointer.is_aligned() { - let destination = instruction.a_field as usize; - let register = Register::Value(sum); - - thread.set_integer_register(destination, register); - } else { - unsafe { - **destination_pointer = sum; - } - } + Action::OptimizedAddIntegers(cache) => { + optimized_add_integer(instruction, thread, cache); } - Action::OptimizedLessIntegers { - left_pointer, - right_pointer, - } => { - let left = if left_pointer.is_null() || !left_pointer.is_aligned() { - let left_index = instruction.b_field as usize; - let left_is_constant = instruction.b_is_constant; - let left_value = thread.get_integer(left_index, left_is_constant); - - *left_pointer = left_value; - - left_value - } else { - unsafe { &ptr::read(*left_pointer) } - }; - let right = if right_pointer.is_null() || !right_pointer.is_aligned() { - let right_index = instruction.c_field as usize; - let right_is_constant = instruction.c_is_constant; - let right_value = thread.get_integer(right_index, right_is_constant); - - *right_pointer = right_value; - - right_value - } else { - unsafe { &ptr::read(*right_pointer) } - }; - let is_less_than = left < right; - let comparator = instruction.d_field; - - if is_less_than == comparator { - local_ip += 1; - } + Action::OptimizedLessIntegers(cache) => { + optimized_less_integers(&mut local_ip, instruction, thread, cache); } Action::OptimizedJumpForward { offset } => { local_ip += *offset; @@ -194,8 +123,8 @@ impl Display for ActionSequence { } } -#[derive(Clone, Debug)] -pub enum Action { +#[derive(Debug)] +enum Action { Unoptimized { logic: ActionLogic, instruction: InstructionFields, @@ -203,15 +132,8 @@ pub enum Action { Loop { actions: ActionSequence, }, - OptimizedAddIntegers { - destination_pointer: *mut i64, - left_pointer: *const i64, - right_pointer: *const i64, - }, - OptimizedLessIntegers { - left_pointer: *const i64, - right_pointer: *const i64, - }, + OptimizedAddIntegers(Option<[RuntimeValue; 3]>), + OptimizedLessIntegers(Option<[RuntimeValue; 2]>), OptimizedJumpForward { offset: usize, }, @@ -272,18 +194,11 @@ impl Action { pub fn optimized(instruction: &InstructionFields) -> Self { match instruction.operation { Operation::ADD => match (instruction.b_type, instruction.c_type) { - (TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedAddIntegers { - destination_pointer: std::ptr::null_mut(), - left_pointer: std::ptr::null(), - right_pointer: std::ptr::null(), - }, + (TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedAddIntegers(None), _ => todo!(), }, Operation::LESS => match (instruction.b_type, instruction.c_type) { - (TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedLessIntegers { - left_pointer: std::ptr::null(), - right_pointer: std::ptr::null(), - }, + (TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedLessIntegers(None), _ => todo!(), }, Operation::JUMP => { @@ -315,10 +230,10 @@ impl Display for Action { write!(f, "LOOP: {actions}") } Action::OptimizedAddIntegers { .. } => { - write!(f, "ADD integers optimized") + write!(f, "ADD_INTEGERS_OPTIMIZED") } Action::OptimizedLessIntegers { .. } => { - write!(f, "LESS integers optimized") + write!(f, "LESS_INTEGERS_OPTIMIZED") } Action::OptimizedJumpForward { offset } => { write!(f, "JUMP +{offset}") @@ -333,180 +248,15 @@ impl Display for Action { pub type ActionLogic = fn(&mut usize, &InstructionFields, &mut Thread); fn point(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let to = instruction.b_field as usize; - let to_is_constant = instruction.b_is_constant; - let r#type = instruction.b_type; - - match r#type { - TypeCode::BOOLEAN => { - let boolean = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(to).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(to) - }; - let register = Register::Value(*boolean); - - thread.set_boolean_register(destination, register); - } - TypeCode::BYTE => { - let byte = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_byte().unwrap() - } else { - unsafe { thread.get_constant(to).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(to) - }; - let register = Register::Value(*byte); - - thread.set_byte_register(destination, register); - } - TypeCode::CHARACTER => { - let character = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_character().unwrap() - } else { - unsafe { thread.get_constant(to).as_character().unwrap_unchecked() } - } - } else { - thread.get_character_register(to) - }; - let register = Register::Value(*character); - - thread.set_character_register(destination, register); - } - TypeCode::FLOAT => { - let float = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_float().unwrap() - } else { - unsafe { thread.get_constant(to).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(to) - }; - let register = Register::Value(*float); - - thread.set_float_register(destination, register); - } - TypeCode::INTEGER => { - let integer = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_integer().unwrap() - } else { - unsafe { thread.get_constant(to).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(to) - }; - let register = Register::Value(*integer); - - thread.set_integer_register(destination, register); - } - TypeCode::STRING => { - let string = if to_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(to).as_string().unwrap().clone() - } else { - unsafe { - thread - .get_constant(to) - .as_string() - .unwrap_unchecked() - .clone() - } - } - } else { - thread.get_string_register(to).clone() - }; - let register = Register::Value(string); - - thread.set_string_register(destination, register); - } - TypeCode::LIST => { - let list = thread.get_list_register(to).clone(); - let register = Register::Value(list); - - thread.set_list_register(destination, register); - } - _ => unreachable!(), - } + todo!() } fn close(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let from = instruction.b_field as usize; - let to = instruction.c_field as usize; - let r#type = instruction.b_type; - - match r#type { - TypeCode::BOOLEAN => { - for register_index in from..=to { - thread.close_boolean_register(register_index); - } - } - TypeCode::BYTE => { - for register_index in from..=to { - thread.close_byte_register(register_index); - } - } - TypeCode::CHARACTER => { - for register_index in from..=to { - thread.close_character_register(register_index); - } - } - TypeCode::FLOAT => { - for register_index in from..=to { - thread.close_float_register(register_index); - } - } - TypeCode::INTEGER => { - for register_index in from..=to { - thread.close_integer_register(register_index); - } - } - TypeCode::STRING => { - for register_index in from..=to { - thread.close_string_register(register_index); - } - } - TypeCode::LIST => { - for register_index in from..=to { - thread.close_list_register(register_index); - } - } - _ => unreachable!(), - } + todo!() } fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field; - let value = instruction.b_field; - let value_type = instruction.b_type; - let jump_next = instruction.c_field != 0; - - match value_type { - TypeCode::BOOLEAN => { - let register = Register::Value(value != 0); - - thread.set_boolean_register(destination as usize, register); - } - TypeCode::BYTE => { - let register = Register::Value(value as u8); - - thread.set_byte_register(destination as usize, register); - } - _ => unreachable!(), - } - - if jump_next { - *ip += 1; - } + todo!() } fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { @@ -514,30 +264,44 @@ fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut T let constant_index = instruction.b_field as usize; let constant_type = instruction.b_type; let jump_next = instruction.c_field != 0; + let current_frame = thread.current_frame_mut(); match constant_type { TypeCode::CHARACTER => { - let constant = *thread.get_constant(constant_index).as_character().unwrap(); - let register = Register::Value(constant); + let constant = current_frame.get_character_constant(constant_index).clone(); - thread.set_character_register(destination, register); + current_frame + .registers + .characters + .get_mut(destination) + .set(constant); } TypeCode::FLOAT => { - let constant = *thread.get_constant(constant_index).as_float().unwrap(); - let register = Register::Value(constant); + let constant = current_frame.get_float_constant(constant_index).clone(); - thread.set_float_register(destination, register); + current_frame + .registers + .floats + .get_mut(destination) + .set(constant); } TypeCode::INTEGER => { - let constant = *thread.get_constant(constant_index).as_integer().unwrap(); - let register = Register::Value(constant); + let constant = current_frame.get_integer_constant(constant_index).clone(); - thread.set_integer_register(destination, register); + current_frame + .registers + .integers + .get_mut(destination) + .set(constant); } TypeCode::STRING => { - let register = Register::Pointer(Pointer::ConstantString(constant_index)); + let constant = current_frame.get_string_constant(constant_index).clone(); - thread.set_string_register(destination, register); + current_frame + .registers + .strings + .get_mut(destination) + .set(constant); } _ => unreachable!(), } @@ -548,99 +312,7 @@ fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut T } fn load_list(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field; - let start_register = instruction.b_field; - let item_type = instruction.b_type; - let end_register = instruction.c_field; - let jump_next = instruction.d_field; - - let length = (end_register - start_register + 1) as usize; - let mut item_pointers = Vec::with_capacity(length); - - for register_index in start_register..=end_register { - let register_index = register_index as usize; - - let pointer = match item_type { - TypeCode::BOOLEAN => { - let is_closed = thread.is_boolean_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterBoolean(register_index) - } - TypeCode::BYTE => { - let is_closed = thread.is_byte_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterByte(register_index) - } - TypeCode::CHARACTER => { - let is_closed = thread.is_character_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterCharacter(register_index) - } - TypeCode::FLOAT => { - let is_closed = thread.is_float_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterFloat(register_index) - } - TypeCode::INTEGER => { - let is_closed = thread.is_integer_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterInteger(register_index) - } - TypeCode::STRING => { - let is_closed = thread.is_string_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterString(register_index) - } - TypeCode::LIST => { - let is_closed = thread.is_list_register_closed(register_index); - - if is_closed { - continue; - } - - Pointer::RegisterList(register_index) - } - _ => unreachable!(), - }; - - item_pointers.push(pointer); - } - - let abstract_list = AbstractList { - item_type, - item_pointers, - }; - let register = Register::Value(abstract_list); - - thread.set_list_register(destination as usize, register); - - if jump_next { - *ip += 1; - } + todo!() } fn load_function(_: &mut usize, _: &InstructionFields, _: &mut Thread) { @@ -652,357 +324,23 @@ fn load_self(_: &mut usize, _: &InstructionFields, _: &mut Thread) { } fn subtract(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value.saturating_sub(*right_value); - let register = Register::Value(result); - - thread.set_integer_register(destination, register); - } - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value.saturating_sub(*right_value); - let register = Register::Value(result); - - thread.set_byte_register(destination, register); - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value - right_value; - let register = Register::Value(result); - - thread.set_float_register(destination, register); - } - _ => unreachable!(), - } + todo!() } fn multiply(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value.saturating_mul(*right_value); - let register = Register::Value(result); - - thread.set_byte_register(destination, register); - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value * right_value; - let register = Register::Value(result); - - thread.set_float_register(destination, register); - } - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value.saturating_mul(*right_value); - let register = Register::Value(result); - - thread.set_integer_register(destination, register); - } - _ => unreachable!(), - } + todo!() } fn divide(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value.saturating_div(*right_value); - let register = Register::Value(result); - - thread.set_byte_register(destination, register); - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value / right_value; - let register = Register::Value(result); - - thread.set_float_register(destination, register); - } - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value.saturating_div(*right_value); - let register = Register::Value(result); - - thread.set_integer_register(destination, register); - } - _ => unreachable!(), - } + todo!() } fn modulo(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field as usize; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value % right_value; - let register = Register::Value(result); - - thread.set_byte_register(destination, register); - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value % right_value; - let register = Register::Value(result); - - thread.set_float_register(destination, register); - } - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value % right_value; - let register = Register::Value(result); - - thread.set_integer_register(destination, register); - } - _ => unreachable!(), - } + todo!() } fn test(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let operand_register = instruction.b_field as usize; - let test_value = instruction.c_field != 0; - let operand_boolean = thread.get_boolean_register(operand_register); - - if *operand_boolean == test_value { - *ip += 1; - } + todo!() } fn test_set(_: &mut usize, _: &InstructionFields, _: &mut Thread) { @@ -1010,355 +348,11 @@ fn test_set(_: &mut usize, _: &InstructionFields, _: &mut Thread) { } fn equal(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let comparator = instruction.d_field; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::BOOLEAN, TypeCode::BOOLEAN) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(left).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(right).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(right) - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::CHARACTER, TypeCode::CHARACTER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_character().unwrap() - } else { - unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } - } - } else { - thread.get_character_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_character().unwrap() - } else { - unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } - } - } else { - thread.get_character_register(right) - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::STRING, TypeCode::STRING) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_string().unwrap().clone() - } else { - unsafe { - thread - .get_constant(left) - .as_string() - .unwrap_unchecked() - .clone() - } - } - } else { - thread.get_string_register(left).clone() - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_string().unwrap().clone() - } else { - unsafe { - thread - .get_constant(right) - .as_string() - .unwrap_unchecked() - .clone() - } - } - } else { - thread.get_string_register(right).clone() - }; - let result = left_value == right_value; - - if result == comparator { - *ip += 1; - } - } - _ => unreachable!(), - } + todo!() } fn less_equal(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let comparator = instruction.d_field; - let left = instruction.b_field as usize; - let left_type = instruction.b_type; - let left_is_constant = instruction.b_is_constant; - let right = instruction.c_field as usize; - let right_type = instruction.c_type; - let right_is_constant = instruction.c_is_constant; - - match (left_type, right_type) { - (TypeCode::BOOLEAN, TypeCode::BOOLEAN) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(left).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_boolean().unwrap() - } else { - unsafe { thread.get_constant(right).as_boolean().unwrap_unchecked() } - } - } else { - thread.get_boolean_register(right) - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::BYTE, TypeCode::BYTE) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_byte().unwrap() - } else { - unsafe { thread.get_constant(left).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_byte().unwrap() - } else { - unsafe { thread.get_constant(right).as_byte().unwrap_unchecked() } - } - } else { - thread.get_byte_register(right) - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::CHARACTER, TypeCode::CHARACTER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_character().unwrap() - } else { - unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } - } - } else { - thread.get_character_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_character().unwrap() - } else { - unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } - } - } else { - thread.get_character_register(right) - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::FLOAT, TypeCode::FLOAT) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_float().unwrap() - } else { - unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_float().unwrap() - } else { - unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } - } - } else { - thread.get_float_register(right) - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::INTEGER, TypeCode::INTEGER) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_integer().unwrap() - } else { - unsafe { thread.get_constant(left).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(left) - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_integer().unwrap() - } else { - unsafe { thread.get_constant(right).as_integer().unwrap_unchecked() } - } - } else { - thread.get_integer_register(right) - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - (TypeCode::STRING, TypeCode::STRING) => { - let left_value = if left_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(left).as_string().unwrap().clone() - } else { - unsafe { - thread - .get_constant(left) - .as_string() - .unwrap_unchecked() - .clone() - } - } - } else { - thread.get_string_register(left).clone() - }; - let right_value = if right_is_constant { - if cfg!(debug_assertions) { - thread.get_constant(right).as_string().unwrap().clone() - } else { - unsafe { - thread - .get_constant(right) - .as_string() - .unwrap_unchecked() - .clone() - } - } - } else { - thread.get_string_register(right).clone() - }; - let result = left_value <= right_value; - - if result == comparator { - *ip += 1; - } - } - _ => unreachable!(), - } + todo!() } fn negate(_: &mut usize, _: &InstructionFields, _: &mut Thread) { @@ -1381,47 +375,48 @@ fn r#return(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) let should_return_value = instruction.b_field != 0; let return_register = instruction.c_field as usize; let return_type = instruction.b_type; + let current_frame = thread.current_frame(); if should_return_value { match return_type { TypeCode::BOOLEAN => { - let return_value = *thread.get_boolean_register(return_register); + let return_value = current_frame + .get_boolean_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::boolean(return_value)); } TypeCode::BYTE => { - let return_value = *thread.get_byte_register(return_register); + let return_value = current_frame + .get_byte_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::byte(return_value)); } TypeCode::CHARACTER => { - let return_value = *thread.get_character_register(return_register); + let return_value = current_frame + .get_character_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::character(return_value)); } TypeCode::FLOAT => { - let return_value = *thread.get_float_register(return_register); + let return_value = current_frame + .get_float_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::float(return_value)); } TypeCode::INTEGER => { - let return_value = *thread.get_integer_register(return_register); + let return_value = current_frame + .get_integer_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::integer(return_value)); } TypeCode::STRING => { - let return_value = thread.get_string_register(return_register).clone(); + let return_value = current_frame + .get_string_from_register(return_register) + .clone_inner(); thread.return_value = Some(Value::string(return_value)); } TypeCode::LIST => { - let abstract_list = thread.get_list_register(return_register).clone(); - let mut items = Vec::with_capacity(abstract_list.item_pointers.len()); - - for pointer in &abstract_list.item_pointers { - let value = thread.get_value_from_pointer(pointer); - - items.push(value); - } - - thread.return_value = Some(Value::Concrete(ConcreteValue::List { - items, - item_type: abstract_list.item_type, - })); + todo!() } _ => unreachable!(), } diff --git a/dust-lang/src/vm/call_frame.rs b/dust-lang/src/vm/call_frame.rs index 2bbf4c1..60a6210 100644 --- a/dust-lang/src/vm/call_frame.rs +++ b/dust-lang/src/vm/call_frame.rs @@ -1,9 +1,11 @@ use std::{ + cell::{RefCell, RefMut}, fmt::{self, Debug, Display, Formatter}, + ops::{Add, Index, IndexMut}, rc::Rc, }; -use smallvec::{smallvec, SmallVec}; +use smallvec::SmallVec; use crate::{AbstractList, Chunk, DustString, Function}; @@ -13,17 +15,220 @@ pub struct CallFrame { pub ip: usize, pub return_register: u16, pub registers: RegisterTable, + pub constants: ConstantTable, } impl CallFrame { pub fn new(chunk: Rc, return_register: u16) -> Self { - let registers = RegisterTable::new(); + let registers = RegisterTable { + booleans: RegisterList::new(chunk.boolean_register_count as usize), + bytes: RegisterList::new(chunk.byte_register_count as usize), + characters: RegisterList::new(chunk.character_register_count as usize), + floats: RegisterList::new(chunk.float_register_count as usize), + integers: RegisterList::new(chunk.integer_register_count as usize), + strings: RegisterList::new(chunk.string_register_count as usize), + lists: RegisterList::new(chunk.list_register_count as usize), + functions: RegisterList::new(chunk.function_register_count as usize), + }; + let constants = ConstantTable { + characters: chunk + .character_constants + .iter() + .map(|&character| RuntimeValue::Raw(character)) + .collect(), + floats: chunk + .float_constants + .iter() + .map(|&float| RuntimeValue::Raw(float)) + .collect(), + integers: chunk + .integer_constants + .iter() + .map(|&integer| RuntimeValue::Raw(integer)) + .collect(), + strings: chunk + .string_constants + .iter() + .map(|string| RuntimeValue::Raw(string.clone())) + .collect(), + }; Self { chunk, ip: 0, return_register, registers, + constants, + } + } + + pub fn get_boolean_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.booleans.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_boolean_from_pointer(pointer), + } + } + + pub fn get_boolean_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_boolean_from_register(*register_index), + Pointer::Constant(_) => panic!("Attempted to get boolean from constant pointer"), + } + } + + pub fn get_byte_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.bytes.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_byte_from_pointer(pointer), + } + } + + pub fn get_byte_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_byte_from_register(*register_index), + Pointer::Constant(_) => panic!("Attempted to get byte from constant pointer"), + } + } + + pub fn get_character_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.characters.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_character_from_pointer(pointer), + } + } + + pub fn get_character_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_character_from_register(*register_index), + Pointer::Constant(constant_index) => self.get_character_constant(*constant_index), + } + } + + pub fn get_character_constant(&self, constant_index: usize) -> &RuntimeValue { + if cfg!(debug_assertions) { + self.constants.characters.get(constant_index).unwrap() + } else { + unsafe { self.constants.characters.get_unchecked(constant_index) } + } + } + + pub fn get_float_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.floats.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_float_from_pointer(pointer), + } + } + + pub fn get_float_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_float_from_register(*register_index), + Pointer::Constant(constant_index) => self.get_float_constant(*constant_index), + } + } + + pub fn get_float_constant(&self, constant_index: usize) -> &RuntimeValue { + if cfg!(debug_assertions) { + self.constants.floats.get(constant_index).unwrap() + } else { + unsafe { self.constants.floats.get_unchecked(constant_index) } + } + } + + pub fn get_integer_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.integers.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_integer_from_pointer(pointer), + } + } + + pub fn get_integer_from_register_mut( + &mut self, + register_index: usize, + ) -> &mut RuntimeValue { + let register = self.registers.integers.get_mut(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { .. } => { + panic!("Attempted to get mutable integer from pointer") + } + } + } + + pub fn get_integer_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_integer_from_register(*register_index), + Pointer::Constant(constant_index) => self.get_integer_constant(*constant_index), + } + } + + pub fn get_integer_from_pointer_mut(&mut self, pointer: &Pointer) -> &mut RuntimeValue { + match pointer { + Pointer::Register(register_index) => { + self.get_integer_from_register_mut(*register_index) + } + Pointer::Constant(constant_index) => self.get_integer_constant_mut(*constant_index), + } + } + + pub fn get_integer_constant(&self, constant_index: usize) -> &RuntimeValue { + if cfg!(debug_assertions) { + self.constants.integers.get(constant_index).unwrap() + } else { + unsafe { self.constants.integers.get_unchecked(constant_index) } + } + } + + pub fn get_integer_constant_mut(&mut self, constant_index: usize) -> &mut RuntimeValue { + if cfg!(debug_assertions) { + self.constants.integers.get_mut(constant_index).unwrap() + } else { + unsafe { self.constants.integers.get_unchecked_mut(constant_index) } + } + } + + pub fn get_string_from_register(&self, register_index: usize) -> &RuntimeValue { + let register = self.registers.strings.get(register_index); + + match register { + Register::Value { value, .. } => value, + Register::Pointer { pointer, .. } => self.get_string_from_pointer(pointer), + } + } + + pub fn get_string_from_pointer(&self, pointer: &Pointer) -> &RuntimeValue { + match pointer { + Pointer::Register(register_index) => self.get_string_from_register(*register_index), + Pointer::Constant(constant_index) => self.get_string_constant(*constant_index), + } + } + + pub fn get_string_constant(&self, constant_index: usize) -> &RuntimeValue { + if cfg!(debug_assertions) { + self.constants.strings.get(constant_index).unwrap() + } else { + unsafe { self.constants.strings.get_unchecked(constant_index) } + } + } + + pub fn get_string_constant_mut( + &mut self, + constant_index: usize, + ) -> &mut RuntimeValue { + if cfg!(debug_assertions) { + self.constants.strings.get_mut(constant_index).unwrap() + } else { + unsafe { self.constants.strings.get_unchecked_mut(constant_index) } } } } @@ -42,103 +247,348 @@ impl Display for CallFrame { } } -#[derive(Debug)] -pub struct RegisterTable { - pub booleans: SmallVec<[Register; 64]>, - pub bytes: SmallVec<[Register; 64]>, - pub characters: SmallVec<[Register; 64]>, - pub floats: SmallVec<[Register; 64]>, - pub integers: SmallVec<[Register; 64]>, - pub strings: SmallVec<[Register; 64]>, - pub lists: SmallVec<[Register; 64]>, - pub functions: SmallVec<[Register; 64]>, +#[derive(Debug, Default)] +pub struct ConstantTable { + pub characters: Vec>, + pub floats: Vec>, + pub integers: Vec>, + pub strings: Vec>, } -impl RegisterTable { - pub fn new() -> Self { - Self { - booleans: smallvec![Register::default(); 64], - bytes: smallvec![Register::default(); 64], - characters: smallvec![Register::default(); 64], - floats: smallvec![Register::default(); 64], - integers: smallvec![Register::default(); 64], - strings: smallvec![Register::default(); 64], - lists: smallvec![Register::default(); 64], - functions: smallvec![Register::default(); 64], +#[derive(Debug)] +pub struct RegisterTable { + pub booleans: RegisterList, + pub bytes: RegisterList, + pub characters: RegisterList, + pub floats: RegisterList, + pub integers: RegisterList, + pub strings: RegisterList, + pub lists: RegisterList, + pub functions: RegisterList, +} + +#[derive(Debug)] +pub struct RegisterList { + pub registers: SmallVec<[Register; STACK_LEN]>, +} + +impl RegisterList +where + T: Clone + Default, +{ + pub fn new(length: usize) -> Self { + let mut registers = SmallVec::with_capacity(length); + + for _ in 0..length { + registers.push(Register::default()); + } + + Self { registers } + } + + pub fn get(&self, index: usize) -> &Register { + if cfg!(debug_assertions) { + self.registers.get(index).unwrap() + } else { + unsafe { self.registers.get_unchecked(index) } + } + } + + pub fn get_mut(&mut self, index: usize) -> &mut Register { + if cfg!(debug_assertions) { + let length = self.registers.len(); + + self.registers + .get_mut(index) + .unwrap_or_else(|| panic!("Index out of bounds: {index}. Length is {length}")) + } else { + unsafe { self.registers.get_unchecked_mut(index) } + } + } + + pub fn close(&mut self, index: usize) { + if cfg!(debug_assertions) { + self.registers.get_mut(index).unwrap().close() + } else { + unsafe { self.registers.get_unchecked_mut(index).close() } + } + } + + pub fn is_closed(&self, index: usize) -> bool { + if cfg!(debug_assertions) { + self.registers.get(index).unwrap().is_closed() + } else { + unsafe { self.registers.get_unchecked(index).is_closed() } } } } -impl Default for RegisterTable { - fn default() -> Self { - Self::new() +impl Index for RegisterList { + type Output = Register; + + fn index(&self, index: usize) -> &Self::Output { + &self.registers[index] } } -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Register { - Value(T), - Closed(T), - Pointer(Pointer), +impl IndexMut for RegisterList { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.registers[index] + } } -impl Register { - pub fn contained_value_mut(&mut self) -> Option<&mut T> { +#[derive(Clone, Debug)] +pub enum Register { + Value { + value: RuntimeValue, + is_closed: bool, + }, + Pointer { + pointer: Pointer, + is_closed: bool, + }, +} + +impl Register { + pub fn is_closed(&self) -> bool { match self { - Self::Value(value) => Some(value), - Self::Closed(value) => Some(value), - Self::Pointer(_) => None, + Self::Value { is_closed, .. } => *is_closed, + Self::Pointer { is_closed, .. } => *is_closed, + } + } + + pub fn close(&mut self) { + match self { + Self::Value { is_closed, .. } => *is_closed = true, + Self::Pointer { is_closed, .. } => *is_closed = true, + } + } + + pub fn set(&mut self, new_value: RuntimeValue) { + match self { + Self::Value { + value: old_value, .. + } => *old_value = new_value, + Self::Pointer { is_closed, .. } => { + *self = Self::Value { + value: new_value, + is_closed: *is_closed, + } + } + } + } + + pub fn as_value(&self) -> &RuntimeValue { + match self { + Self::Value { value, .. } => value, + Self::Pointer { .. } => panic!("Attempted to use pointer as value"), + } + } + + pub fn as_value_mut(&mut self) -> &mut RuntimeValue { + match self { + Self::Value { value, .. } => value, + Self::Pointer { .. } => panic!("Attempted to use pointer as value"), } } } impl Default for Register { fn default() -> Self { - Self::Value(T::default()) + Self::Value { + value: RuntimeValue::Raw(Default::default()), + is_closed: false, + } } } -impl Display for Register { +#[derive(Clone, Debug)] +pub enum RuntimeValue { + Raw(T), + Rc(Rc), + RefCell(Rc>), +} + +impl RuntimeValue { + pub fn ref_cell(value: T) -> Self { + Self::RefCell(Rc::new(RefCell::new(value))) + } + + pub fn rc(value: T) -> Self { + Self::Rc(Rc::new(value)) + } + + pub fn to_ref_cell(&mut self) -> Self { + match self { + Self::Raw(value) => RuntimeValue::ref_cell(value.clone()), + Self::Rc(value) => RuntimeValue::ref_cell(value.as_ref().clone()), + Self::RefCell(_) => self.clone(), + } + } + + pub fn to_rc(&mut self) -> Self { + match self { + Self::Raw(value) => RuntimeValue::rc(value.clone()), + Self::Rc(_) => self.clone(), + Self::RefCell(value) => RuntimeValue::rc(value.borrow().clone()), + } + } + + pub fn set_inner(&mut self, new_value: T) { + match self { + Self::Raw(value) => *value = new_value, + Self::Rc(value) => { + if let Some(mutable) = Rc::get_mut(value) { + *mutable = new_value; + } + } + Self::RefCell(value) => { + let _ = value.replace(new_value); + } + } + } + + pub fn clone_inner(&self) -> T { + match self { + Self::Raw(value) => value.clone(), + Self::Rc(value) => value.as_ref().clone(), + Self::RefCell(value) => value.borrow().clone(), + } + } + + pub fn borrow_mut(&self) -> RefMut { + match self { + Self::RefCell(value) => value.borrow_mut(), + _ => panic!("Attempted to borrow mutable reference from immutable register value"), + } + } +} + +impl + Copy> Add for &RuntimeValue { + type Output = T; + + fn add(self, other: Self) -> Self::Output { + match (self, other) { + (RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => *left + *right, + (RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => *left + **right, + (RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + *left + *right + } + (RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left + *right, + (RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left + **right, + (RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + **left + *right + } + (RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => { + let left = left.borrow(); + let right = right.borrow(); + + *left + *right + } + (RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => { + let left = left.borrow(); + + *left + *right + } + (RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => { + let left = left.borrow(); + + *left + **right + } + } + } +} + +impl PartialEq for RuntimeValue { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left == right, + (RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left == &**right, + (RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + left == &*right + } + (RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => **left == *right, + (RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => **left == **right, + (RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + **left == *right + } + (RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => { + let left = left.borrow(); + let right = right.borrow(); + + *left == *right + } + (RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => { + let left = left.borrow(); + + *left == *right + } + (RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => { + let left = left.borrow(); + + *left == **right + } + } + } +} + +impl PartialOrd for RuntimeValue { + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (RuntimeValue::Raw(left), RuntimeValue::Raw(right)) => left.partial_cmp(right), + (RuntimeValue::Raw(left), RuntimeValue::Rc(right)) => left.partial_cmp(&**right), + (RuntimeValue::Raw(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + left.partial_cmp(&*right) + } + (RuntimeValue::Rc(left), RuntimeValue::Raw(right)) => (**left).partial_cmp(right), + (RuntimeValue::Rc(left), RuntimeValue::Rc(right)) => left.partial_cmp(right), + (RuntimeValue::Rc(left), RuntimeValue::RefCell(right)) => { + let right = right.borrow(); + + (**left).partial_cmp(&right) + } + (RuntimeValue::RefCell(left), RuntimeValue::RefCell(right)) => { + let left = left.borrow(); + let right = right.borrow(); + + left.partial_cmp(&*right) + } + (RuntimeValue::RefCell(left), RuntimeValue::Raw(right)) => { + let left = left.borrow(); + + left.partial_cmp(right) + } + (RuntimeValue::RefCell(left), RuntimeValue::Rc(right)) => { + let left = left.borrow(); + + left.partial_cmp(&**right) + } + } + } +} + +impl Display for RuntimeValue { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Self::Closed(value) => write!(f, "Closed({value})"), - Self::Value(value) => write!(f, "Value({value})"), - Self::Pointer(pointer) => write!(f, "Pointer({pointer:?})"), + Self::Raw(value) => write!(f, "{}", value), + Self::Rc(value) => write!(f, "{}", value), + Self::RefCell(value) => write!(f, "{}", value.borrow()), } } } #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Pointer { - RegisterBoolean(usize), - RegisterByte(usize), - RegisterCharacter(usize), - RegisterFloat(usize), - RegisterInteger(usize), - RegisterString(usize), - RegisterList(usize), - RegisterFunction(usize), - ConstantCharacter(usize), - ConstantFloat(usize), - ConstantInteger(usize), - ConstantString(usize), -} - -impl Display for Pointer { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Self::RegisterBoolean(index) => write!(f, "P_R_BOOL_{index}"), - Self::RegisterByte(index) => write!(f, "P_R_BYTE_{index}"), - Self::RegisterCharacter(index) => write!(f, "P_R_CHAR_{index}"), - Self::RegisterFloat(index) => write!(f, "P_R_FLOAT_{index}"), - Self::RegisterInteger(index) => write!(f, "P_R_INT_{index}"), - Self::RegisterString(index) => write!(f, "P_R_STR_{index}"), - Self::RegisterList(index) => write!(f, "P_R_LIST_{index}"), - Self::RegisterFunction(index) => write!(f, "P_R_FN_{index}"), - Self::ConstantCharacter(index) => write!(f, "P_C_CHAR_{index}"), - Self::ConstantFloat(index) => write!(f, "P_C_FLOAT_{index}"), - Self::ConstantInteger(index) => write!(f, "P_C_INT_{index}"), - Self::ConstantString(index) => write!(f, "P_C_STR_{index}"), - } - } + Register(usize), + Constant(usize), } diff --git a/dust-lang/src/vm/mod.rs b/dust-lang/src/vm/mod.rs index a17da0a..581932b 100644 --- a/dust-lang/src/vm/mod.rs +++ b/dust-lang/src/vm/mod.rs @@ -5,14 +5,13 @@ mod thread; use std::{rc::Rc, thread::Builder}; -pub use action::Action; -pub use call_frame::{CallFrame, Pointer, Register, RegisterTable}; +pub use call_frame::{CallFrame, Pointer, Register, RegisterTable, RuntimeValue}; pub use thread::Thread; use crossbeam_channel::bounded; -use tracing::{Level, span}; +use tracing::{span, Level}; -use crate::{Chunk, DustError, Value, compile}; +use crate::{compile, Chunk, DustError, Value}; pub fn run(source: &str) -> Result, DustError> { let chunk = compile(source)?; diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index b77f620..7eda000 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -5,11 +5,9 @@ use tracing::{info, trace}; use crate::{ instruction::InstructionFields, vm::{action::ActionSequence, CallFrame}, - AbstractList, Chunk, ConcreteValue, DustString, Span, Value, + Chunk, DustString, Span, Value, }; -use super::call_frame::{Pointer, Register}; - pub struct Thread { chunk: Rc, call_stack: Vec, @@ -77,811 +75,4 @@ impl Thread { unsafe { self.call_stack.last_mut().unwrap_unchecked() } } } - - pub fn get_value_from_pointer(&self, pointer: &Pointer) -> ConcreteValue { - match pointer { - Pointer::RegisterBoolean(register_index) => { - let boolean = *self.get_boolean_register(*register_index); - - ConcreteValue::Boolean(boolean) - } - Pointer::RegisterByte(register_index) => { - let byte = *self.get_byte_register(*register_index); - - ConcreteValue::Byte(byte) - } - Pointer::RegisterCharacter(register_index) => { - let character = *self.get_character_register(*register_index); - - ConcreteValue::Character(character) - } - Pointer::RegisterFloat(register_index) => { - let float = *self.get_float_register(*register_index); - - ConcreteValue::Float(float) - } - Pointer::RegisterInteger(register_index) => { - let integer = *self.get_integer_register(*register_index); - - ConcreteValue::Integer(integer) - } - Pointer::RegisterString(register_index) => { - let string = self.get_string_register(*register_index).clone(); - - ConcreteValue::String(string) - } - Pointer::RegisterList(register_index) => { - let abstract_list = self.get_list_register(*register_index).clone(); - let mut items = Vec::with_capacity(abstract_list.item_pointers.len()); - - for pointer in &abstract_list.item_pointers { - let value = self.get_value_from_pointer(pointer); - - items.push(value); - } - - ConcreteValue::List { - items, - item_type: abstract_list.item_type, - } - } - Pointer::RegisterFunction(_) => unimplemented!(), - Pointer::ConstantCharacter(constant_index) => { - let character = *self.get_constant(*constant_index).as_character().unwrap(); - - ConcreteValue::Character(character) - } - Pointer::ConstantFloat(constant_index) => { - let float = *self.get_constant(*constant_index).as_float().unwrap(); - - ConcreteValue::Float(float) - } - Pointer::ConstantInteger(constant_index) => { - let integer = *self.get_constant(*constant_index).as_integer().unwrap(); - - ConcreteValue::Integer(integer) - } - Pointer::ConstantString(constant_index) => { - let string = self - .get_constant(*constant_index) - .as_string() - .unwrap() - .clone(); - - ConcreteValue::String(string) - } - } - } - - pub fn get_boolean_register(&self, register_index: usize) -> &bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .booleans - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .booleans - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_boolean(pointer), - } - } - - pub fn get_pointer_to_boolean(&self, pointer: &Pointer) -> &bool { - match pointer { - Pointer::RegisterBoolean(register_index) => self.get_boolean_register(*register_index), - _ => panic!("Attempted to get boolean from non-boolean pointer"), - } - } - - pub fn set_boolean_register(&mut self, register_index: usize, new_register: Register) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .booleans - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .booleans - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_boolean_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .booleans - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .booleans - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_boolean_register(&mut self, register_index: usize) { - let register = self - .current_frame_mut() - .registers - .booleans - .get_mut(register_index) - .unwrap(); - - *register = match register { - Register::Value(value) => Register::Closed(*value), - _ => panic!("Attempted to close non-value register"), - }; - } - - pub fn get_byte_register(&self, register_index: usize) -> &u8 { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .bytes - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .bytes - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_byte(pointer), - } - } - - pub fn get_pointer_to_byte(&self, pointer: &Pointer) -> &u8 { - match pointer { - Pointer::RegisterByte(register_index) => self.get_byte_register(*register_index), - _ => panic!("Attempted to get byte from non-byte pointer"), - } - } - - pub fn set_byte_register(&mut self, register_index: usize, new_register: Register) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .bytes - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .bytes - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_byte_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .bytes - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .bytes - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_byte_register(&mut self, register_index: usize) { - let register = self - .current_frame_mut() - .registers - .bytes - .get_mut(register_index) - .unwrap(); - - *register = match register { - Register::Value(value) => Register::Closed(*value), - _ => panic!("Attempted to close non-value register"), - }; - } - - pub fn get_character_register(&self, register_index: usize) -> &char { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .characters - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .characters - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_character(pointer), - } - } - - pub fn get_pointer_to_character(&self, pointer: &Pointer) -> &char { - match pointer { - Pointer::RegisterCharacter(register_index) => { - self.get_character_register(*register_index) - } - Pointer::ConstantCharacter(constant_index) => { - self.get_constant(*constant_index).as_character().unwrap() - } - _ => panic!("Attempted to get character from non-character pointer"), - } - } - - pub fn set_character_register(&mut self, register_index: usize, new_register: Register) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .characters - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .characters - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_character_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .characters - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .characters - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_character_register(&mut self, register_index: usize) { - let register = self - .current_frame_mut() - .registers - .characters - .get_mut(register_index) - .unwrap(); - - *register = match register { - Register::Value(value) => Register::Closed(*value), - _ => panic!("Attempted to close non-value register"), - }; - } - - pub fn get_float_register(&self, register_index: usize) -> &f64 { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .floats - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .floats - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_float(pointer), - } - } - - pub fn get_pointer_to_float(&self, pointer: &Pointer) -> &f64 { - match pointer { - Pointer::RegisterFloat(register_index) => self.get_float_register(*register_index), - Pointer::ConstantFloat(constant_index) => { - self.get_constant(*constant_index).as_float().unwrap() - } - _ => panic!("Attempted to get float from non-float pointer"), - } - } - - pub fn set_float_register(&mut self, register_index: usize, new_register: Register) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .floats - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .floats - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_float_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .floats - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .floats - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_float_register(&mut self, register_index: usize) { - let register = self - .current_frame_mut() - .registers - .floats - .get_mut(register_index) - .unwrap(); - - *register = match register { - Register::Value(value) => Register::Closed(*value), - _ => panic!("Attempted to close non-value register"), - }; - } - - pub fn get_integer(&self, index: usize, is_constant: bool) -> &i64 { - if is_constant { - if cfg!(debug_assertions) { - self.get_constant(index).as_integer().unwrap() - } else { - unsafe { self.get_constant(index).as_integer().unwrap_unchecked() } - } - } else { - self.get_integer_register(index) - } - } - - pub fn get_integer_register(&self, register_index: usize) -> &i64 { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .integers - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .integers - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_integer(pointer), - } - } - - pub fn get_integer_register_mut_allow_empty(&mut self, register_index: usize) -> &mut i64 { - if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .integers - .get_mut(register_index) - .unwrap() - .contained_value_mut() - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .integers - .get_unchecked_mut(register_index) - .contained_value_mut() - .unwrap_unchecked() - } - } - } - - pub fn get_pointer_to_integer(&self, pointer: &Pointer) -> &i64 { - match pointer { - Pointer::RegisterInteger(register_index) => self.get_integer_register(*register_index), - Pointer::ConstantInteger(constant_index) => { - self.get_constant(*constant_index).as_integer().unwrap() - } - _ => panic!("Attempted to get integer from non-integer pointer"), - } - } - - pub fn set_integer_register(&mut self, register_index: usize, new_register: Register) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .integers - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .integers - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_integer_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .integers - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .integers - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_integer_register(&mut self, register_index: usize) { - let register = self - .current_frame_mut() - .registers - .integers - .get_mut(register_index) - .unwrap(); - - *register = match register { - Register::Value(value) => Register::Closed(*value), - _ => panic!("Attempted to close non-value register"), - }; - } - - pub fn get_string_register(&self, register_index: usize) -> &DustString { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .strings - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .strings - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_string(pointer), - } - } - - pub fn get_pointer_to_string(&self, pointer: &Pointer) -> &DustString { - match pointer { - Pointer::RegisterString(register_index) => self.get_string_register(*register_index), - Pointer::ConstantString(constant_index) => { - self.get_constant(*constant_index).as_string().unwrap() - } - _ => panic!("Attempted to get string from non-string pointer"), - } - } - - pub fn set_string_register( - &mut self, - register_index: usize, - new_register: Register, - ) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .strings - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .strings - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_string_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .strings - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .strings - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_string_register(&mut self, register_index: usize) { - let current_frame = self.current_frame_mut(); - - current_frame.registers.strings.push(Register::default()); - - let old_register = current_frame.registers.strings.swap_remove(register_index); - - if let Register::Value(value) = old_register { - current_frame - .registers - .strings - .push(Register::Closed(value)); - - let _ = current_frame.registers.strings.swap_remove(register_index); - } else { - panic!("Attempted to close non-value register"); - } - } - - pub fn get_list_register(&self, register_index: usize) -> &AbstractList { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .lists - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .lists - .get_unchecked(register_index) - } - }; - - match register { - Register::Value(value) => value, - Register::Closed(value) => value, - Register::Pointer(pointer) => self.get_pointer_to_list(pointer), - } - } - - pub fn get_pointer_to_list(&self, pointer: &Pointer) -> &AbstractList { - match pointer { - Pointer::RegisterList(register_index) => self.get_list_register(*register_index), - _ => panic!("Attempted to get list from non-list pointer"), - } - } - - pub fn set_list_register( - &mut self, - register_index: usize, - new_register: Register, - ) { - let old_register = if cfg!(debug_assertions) { - self.call_stack - .last_mut() - .unwrap() - .registers - .lists - .get_mut(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last_mut() - .unwrap_unchecked() - .registers - .lists - .get_unchecked_mut(register_index) - } - }; - - *old_register = new_register; - } - - pub fn is_list_register_closed(&self, register_index: usize) -> bool { - let register = if cfg!(debug_assertions) { - self.call_stack - .last() - .unwrap() - .registers - .lists - .get(register_index) - .unwrap() - } else { - unsafe { - self.call_stack - .last() - .unwrap_unchecked() - .registers - .lists - .get_unchecked(register_index) - } - }; - - matches!(register, Register::Closed(_)) - } - - pub fn close_list_register(&mut self, register_index: usize) { - let current_frame = self.current_frame_mut(); - - current_frame.registers.lists.push(Register::default()); - - let old_register = current_frame.registers.lists.swap_remove(register_index); - - if let Register::Value(value) = old_register { - current_frame.registers.lists.push(Register::Closed(value)); - - let _ = current_frame.registers.lists.swap_remove(register_index); - } else { - panic!("Attempted to close non-value register"); - } - } - - pub fn get_constant(&self, constant_index: usize) -> &ConcreteValue { - if cfg!(debug_assertions) { - self.chunk.constants.get(constant_index).unwrap() - } else { - unsafe { self.chunk.constants.get_unchecked(constant_index) } - } - } }