Make everything messy
This commit is contained in:
parent
c3790e90bf
commit
8f58bf30a4
104
Cargo.lock
generated
104
Cargo.lock
generated
@ -56,7 +56,7 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -66,7 +66,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -121,6 +121,16 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -164,8 +174,10 @@ name = "dust-shell"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"colored",
|
||||||
"dust-lang",
|
"dust-lang",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -226,6 +238,12 @@ version = "1.0.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.153"
|
version = "0.2.153"
|
||||||
@ -425,13 +443,37 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets",
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -440,51 +482,93 @@ version = "0.52.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm 0.52.4",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc 0.52.4",
|
||||||
"windows_i686_gnu",
|
"windows_i686_gnu 0.52.4",
|
||||||
"windows_i686_msvc",
|
"windows_i686_msvc 0.52.4",
|
||||||
"windows_x86_64_gnu",
|
"windows_x86_64_gnu 0.52.4",
|
||||||
"windows_x86_64_gnullvm",
|
"windows_x86_64_gnullvm 0.52.4",
|
||||||
"windows_x86_64_msvc",
|
"windows_x86_64_msvc 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.4"
|
version = "0.52.4"
|
||||||
|
@ -3,7 +3,8 @@ use std::fmt::{self, Debug, Display, Formatter};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
identifier_stack::Local, Identifier, IdentifierStack, Instruction, Span, Value, ValueLocation,
|
identifier_stack::Local, AnnotatedError, Identifier, IdentifierStack, Instruction, Span, Value,
|
||||||
|
ValueLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
@ -42,27 +43,34 @@ impl Chunk {
|
|||||||
self.code.is_empty()
|
self.code.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_code(&self, offset: usize) -> Result<&(u8, Span), ChunkError> {
|
pub fn scope_depth(&self) -> usize {
|
||||||
|
self.identifiers.scope_depth()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_code(&self, offset: usize, position: Span) -> Result<&(u8, Span), ChunkError> {
|
||||||
self.code
|
self.code
|
||||||
.get(offset)
|
.get(offset)
|
||||||
.ok_or(ChunkError::CodeIndexOfBounds(offset))
|
.ok_or(ChunkError::CodeIndexOfBounds { offset, position })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_code(&mut self, instruction: u8, position: Span) {
|
pub fn push_code(&mut self, instruction: u8, position: Span) {
|
||||||
self.code.push((instruction, position));
|
self.code.push((instruction, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_constant(&self, index: u8) -> Result<&Value, ChunkError> {
|
pub fn get_constant(&self, index: u8, position: Span) -> Result<&Value, ChunkError> {
|
||||||
self.constants
|
self.constants
|
||||||
.get(index as usize)
|
.get(index as usize)
|
||||||
.ok_or(ChunkError::ConstantIndexOutOfBounds(index))
|
.ok_or(ChunkError::ConstantIndexOutOfBounds { index, position })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_constant(&mut self, index: u8) -> Result<Value, ChunkError> {
|
pub fn remove_constant(&mut self, index: u8, position: Span) -> Result<Value, ChunkError> {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
|
|
||||||
if index >= self.constants.len() {
|
if index >= self.constants.len() {
|
||||||
Err(ChunkError::ConstantIndexOutOfBounds(index as u8))
|
Err(ChunkError::ConstantIndexOutOfBounds {
|
||||||
|
index: index as u8,
|
||||||
|
position,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(self.constants.remove(index))
|
Ok(self.constants.remove(index))
|
||||||
}
|
}
|
||||||
@ -90,6 +98,14 @@ impl Chunk {
|
|||||||
.ok_or(ChunkError::IdentifierIndexOutOfBounds(index))
|
.ok_or(ChunkError::IdentifierIndexOutOfBounds(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_local(&self, identifier: &Identifier) -> Option<u8> {
|
||||||
|
self.identifiers.resolve(self, identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_local_index(&self, identifier: &Identifier) -> Option<u8> {
|
||||||
|
self.identifiers.resolve_index(identifier)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_identifier(&self, index: u8) -> Result<&Identifier, ChunkError> {
|
pub fn get_identifier(&self, index: u8) -> Result<&Identifier, ChunkError> {
|
||||||
self.identifiers
|
self.identifiers
|
||||||
.get(index as usize)
|
.get(index as usize)
|
||||||
@ -97,10 +113,18 @@ impl Chunk {
|
|||||||
.ok_or(ChunkError::IdentifierIndexOutOfBounds(index))
|
.ok_or(ChunkError::IdentifierIndexOutOfBounds(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_identifier_index(&self, identifier: &Identifier) -> Result<u8, ChunkError> {
|
pub fn get_identifier_index(
|
||||||
|
&self,
|
||||||
|
identifier: &Identifier,
|
||||||
|
position: Span,
|
||||||
|
) -> Result<u8, ChunkError> {
|
||||||
self.identifiers
|
self.identifiers
|
||||||
.get_index(identifier)
|
.get_index(identifier)
|
||||||
.ok_or(ChunkError::IdentifierNotFound(identifier.clone()))
|
.map(|index| index as u8)
|
||||||
|
.ok_or(ChunkError::IdentifierNotFound {
|
||||||
|
identifier: identifier.clone(),
|
||||||
|
position,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_constant_identifier(&mut self, identifier: Identifier) -> Result<u8, ChunkError> {
|
pub fn push_constant_identifier(&mut self, identifier: Identifier) -> Result<u8, ChunkError> {
|
||||||
@ -110,7 +134,7 @@ impl Chunk {
|
|||||||
Err(ChunkError::IdentifierOverflow)
|
Err(ChunkError::IdentifierOverflow)
|
||||||
} else {
|
} else {
|
||||||
self.identifiers
|
self.identifiers
|
||||||
.declare(identifier, ValueLocation::ConstantStack);
|
.define(identifier, ValueLocation::ConstantStack);
|
||||||
|
|
||||||
Ok(starting_length as u8)
|
Ok(starting_length as u8)
|
||||||
}
|
}
|
||||||
@ -123,12 +147,25 @@ impl Chunk {
|
|||||||
Err(ChunkError::IdentifierOverflow)
|
Err(ChunkError::IdentifierOverflow)
|
||||||
} else {
|
} else {
|
||||||
self.identifiers
|
self.identifiers
|
||||||
.declare(identifier, ValueLocation::RuntimeStack);
|
.define(identifier, ValueLocation::RuntimeStack);
|
||||||
|
|
||||||
Ok(starting_length as u8)
|
Ok(starting_length as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn redefine_as_runtime_identifier(
|
||||||
|
&mut self,
|
||||||
|
identifier: &Identifier,
|
||||||
|
position: Span,
|
||||||
|
) -> Result<usize, ChunkError> {
|
||||||
|
self.identifiers
|
||||||
|
.redefine(identifier, ValueLocation::RuntimeStack)
|
||||||
|
.ok_or_else(|| ChunkError::IdentifierNotFound {
|
||||||
|
identifier: identifier.clone(),
|
||||||
|
position,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn begin_scope(&mut self) {
|
pub fn begin_scope(&mut self) {
|
||||||
self.identifiers.begin_scope();
|
self.identifiers.begin_scope();
|
||||||
}
|
}
|
||||||
@ -162,7 +199,7 @@ impl Chunk {
|
|||||||
for (offset, (byte, position)) in self.code.iter().enumerate() {
|
for (offset, (byte, position)) in self.code.iter().enumerate() {
|
||||||
if let Some(
|
if let Some(
|
||||||
Instruction::Constant
|
Instruction::Constant
|
||||||
| Instruction::DefineVariableConstant
|
| Instruction::DefineVariable
|
||||||
| Instruction::GetVariable
|
| Instruction::GetVariable
|
||||||
| Instruction::SetVariable,
|
| Instruction::SetVariable,
|
||||||
) = previous
|
) = previous
|
||||||
@ -179,9 +216,9 @@ impl Chunk {
|
|||||||
instruction.disassemble(self, offset)
|
instruction.disassemble(self, offset)
|
||||||
);
|
);
|
||||||
|
|
||||||
previous = Some(instruction);
|
|
||||||
|
|
||||||
output.push_str(&display);
|
output.push_str(&display);
|
||||||
|
|
||||||
|
previous = Some(instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.push_str("\n Constants \n");
|
output.push_str("\n Constants \n");
|
||||||
@ -245,29 +282,80 @@ impl Debug for Chunk {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ChunkError {
|
pub enum ChunkError {
|
||||||
CodeIndexOfBounds(usize),
|
CodeIndexOfBounds {
|
||||||
|
offset: usize,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
ConstantOverflow,
|
ConstantOverflow,
|
||||||
ConstantIndexOutOfBounds(u8),
|
ConstantIndexOutOfBounds {
|
||||||
|
index: u8,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
IdentifierIndexOutOfBounds(u8),
|
IdentifierIndexOutOfBounds(u8),
|
||||||
IdentifierOverflow,
|
IdentifierOverflow,
|
||||||
IdentifierNotFound(Identifier),
|
IdentifierNotFound {
|
||||||
|
identifier: Identifier,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnnotatedError for ChunkError {
|
||||||
|
fn title() -> &'static str {
|
||||||
|
"Chunk Error"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ChunkError::CodeIndexOfBounds { .. } => "Code index out of bounds",
|
||||||
|
ChunkError::ConstantOverflow => "Constant overflow",
|
||||||
|
ChunkError::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
|
||||||
|
ChunkError::IdentifierIndexOutOfBounds(_) => "Identifier index out of bounds",
|
||||||
|
ChunkError::IdentifierOverflow => "Identifier overflow",
|
||||||
|
ChunkError::IdentifierNotFound { .. } => "Identifier not found",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn details(&self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
ChunkError::CodeIndexOfBounds { offset, .. } => Some(format!("Code index: {}", offset)),
|
||||||
|
ChunkError::ConstantIndexOutOfBounds { index, .. } => {
|
||||||
|
Some(format!("Constant index: {}", index))
|
||||||
|
}
|
||||||
|
ChunkError::IdentifierIndexOutOfBounds(index) => {
|
||||||
|
Some(format!("Identifier index: {}", index))
|
||||||
|
}
|
||||||
|
ChunkError::IdentifierNotFound { identifier, .. } => {
|
||||||
|
Some(format!("Identifier: {}", identifier))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn position(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
ChunkError::CodeIndexOfBounds { position, .. } => *position,
|
||||||
|
ChunkError::ConstantIndexOutOfBounds { position, .. } => *position,
|
||||||
|
ChunkError::IdentifierNotFound { position, .. } => *position,
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ChunkError {
|
impl Display for ChunkError {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ChunkError::CodeIndexOfBounds(offset) => {
|
ChunkError::CodeIndexOfBounds { offset, .. } => {
|
||||||
write!(f, "Code index out of bounds: {}", offset)
|
write!(f, "Code index out of bounds: {}", offset)
|
||||||
}
|
}
|
||||||
ChunkError::ConstantOverflow => write!(f, "Constant overflow"),
|
ChunkError::ConstantOverflow => write!(f, "Constant overflow"),
|
||||||
ChunkError::ConstantIndexOutOfBounds(index) => {
|
ChunkError::ConstantIndexOutOfBounds { index, .. } => {
|
||||||
write!(f, "Constant index out of bounds: {}", index)
|
write!(f, "Constant index out of bounds: {}", index)
|
||||||
}
|
}
|
||||||
ChunkError::IdentifierIndexOutOfBounds(index) => {
|
ChunkError::IdentifierIndexOutOfBounds(index) => {
|
||||||
write!(f, "Identifier index out of bounds: {}", index)
|
write!(f, "Identifier index out of bounds: {}", index)
|
||||||
}
|
}
|
||||||
ChunkError::IdentifierOverflow => write!(f, "Identifier overflow"),
|
ChunkError::IdentifierOverflow => write!(f, "Identifier overflow"),
|
||||||
ChunkError::IdentifierNotFound(identifier) => {
|
ChunkError::IdentifierNotFound { identifier, .. } => {
|
||||||
write!(f, "Identifier not found: {}", identifier)
|
write!(f, "Identifier not found: {}", identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Identifier;
|
use crate::{Chunk, Identifier};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct IdentifierStack {
|
pub struct IdentifierStack {
|
||||||
@ -41,11 +41,33 @@ impl IdentifierStack {
|
|||||||
.any(|local| &local.identifier == identifier)
|
.any(|local| &local.identifier == identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve(&self, chunk: &Chunk, identifier: &Identifier) -> Option<u8> {
|
||||||
|
for (index, local) in self.locals.iter().rev().enumerate() {
|
||||||
|
if &local.identifier == identifier {
|
||||||
|
let offset = index;
|
||||||
|
|
||||||
|
return Some(offset as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_index(&self, identifier: &Identifier) -> Option<u8> {
|
||||||
|
self.locals.iter().enumerate().find_map(|(index, local)| {
|
||||||
|
if &local.identifier == identifier && local.depth <= self.scope_depth {
|
||||||
|
Some(index as u8)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(&self, index: usize) -> Option<&Local> {
|
pub fn get(&self, index: usize) -> Option<&Local> {
|
||||||
self.locals.get(index)
|
self.locals.get(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_index(&self, identifier: &Identifier) -> Option<u8> {
|
pub fn get_index(&self, identifier: &Identifier) -> Option<usize> {
|
||||||
self.locals.iter().enumerate().rev().find_map(
|
self.locals.iter().enumerate().rev().find_map(
|
||||||
|(
|
|(
|
||||||
index,
|
index,
|
||||||
@ -54,7 +76,7 @@ impl IdentifierStack {
|
|||||||
},
|
},
|
||||||
)| {
|
)| {
|
||||||
if local == identifier {
|
if local == identifier {
|
||||||
Some(index as u8)
|
Some(index)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -62,6 +84,10 @@ impl IdentifierStack {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scope_depth(&self) -> usize {
|
||||||
|
self.scope_depth
|
||||||
|
}
|
||||||
|
|
||||||
pub fn begin_scope(&mut self) {
|
pub fn begin_scope(&mut self) {
|
||||||
self.scope_depth += 1;
|
self.scope_depth += 1;
|
||||||
}
|
}
|
||||||
@ -70,7 +96,7 @@ impl IdentifierStack {
|
|||||||
self.scope_depth -= 1;
|
self.scope_depth -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn declare(&mut self, identifier: Identifier, value_location: ValueLocation) {
|
pub fn define(&mut self, identifier: Identifier, value_location: ValueLocation) {
|
||||||
self.locals.push(Local {
|
self.locals.push(Local {
|
||||||
identifier,
|
identifier,
|
||||||
depth: self.scope_depth,
|
depth: self.scope_depth,
|
||||||
@ -78,6 +104,20 @@ impl IdentifierStack {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn redefine(
|
||||||
|
&mut self,
|
||||||
|
identifier: &Identifier,
|
||||||
|
value_location: ValueLocation,
|
||||||
|
) -> Option<usize> {
|
||||||
|
if let Some(index) = self.get_index(identifier) {
|
||||||
|
self.locals[index].value_location = value_location;
|
||||||
|
|
||||||
|
Some(index)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &Local> {
|
pub fn iter(&self) -> impl Iterator<Item = &Local> {
|
||||||
self.locals.iter()
|
self.locals.iter()
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Chunk;
|
use crate::{Chunk, Span};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
@ -11,28 +11,27 @@ pub enum Instruction {
|
|||||||
Pop = 2,
|
Pop = 2,
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
DefineVariableRuntime = 3,
|
DefineVariable = 3,
|
||||||
DefineVariableConstant = 4,
|
GetVariable = 4,
|
||||||
GetVariable = 5,
|
SetVariable = 5,
|
||||||
SetVariable = 6,
|
|
||||||
|
|
||||||
// Unary
|
// Unary
|
||||||
Negate = 7,
|
Negate = 6,
|
||||||
Not = 8,
|
Not = 7,
|
||||||
|
|
||||||
// Binary
|
// Binary
|
||||||
Add = 9,
|
Add = 8,
|
||||||
Subtract = 10,
|
Subtract = 9,
|
||||||
Multiply = 11,
|
Multiply = 10,
|
||||||
Divide = 12,
|
Divide = 11,
|
||||||
Greater = 13,
|
Greater = 12,
|
||||||
Less = 14,
|
Less = 13,
|
||||||
GreaterEqual = 15,
|
GreaterEqual = 14,
|
||||||
LessEqual = 16,
|
LessEqual = 15,
|
||||||
Equal = 17,
|
Equal = 16,
|
||||||
NotEqual = 18,
|
NotEqual = 17,
|
||||||
And = 19,
|
And = 18,
|
||||||
Or = 20,
|
Or = 19,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instruction {
|
impl Instruction {
|
||||||
@ -41,65 +40,65 @@ impl Instruction {
|
|||||||
0 => Some(Instruction::Constant),
|
0 => Some(Instruction::Constant),
|
||||||
1 => Some(Instruction::Return),
|
1 => Some(Instruction::Return),
|
||||||
2 => Some(Instruction::Pop),
|
2 => Some(Instruction::Pop),
|
||||||
3 => Some(Instruction::DefineVariableRuntime),
|
3 => Some(Instruction::DefineVariable),
|
||||||
4 => Some(Instruction::DefineVariableConstant),
|
4 => Some(Instruction::GetVariable),
|
||||||
5 => Some(Instruction::GetVariable),
|
5 => Some(Instruction::SetVariable),
|
||||||
6 => Some(Instruction::SetVariable),
|
6 => Some(Instruction::Negate),
|
||||||
7 => Some(Instruction::Negate),
|
7 => Some(Instruction::Not),
|
||||||
8 => Some(Instruction::Not),
|
8 => Some(Instruction::Add),
|
||||||
9 => Some(Instruction::Add),
|
9 => Some(Instruction::Subtract),
|
||||||
10 => Some(Instruction::Subtract),
|
10 => Some(Instruction::Multiply),
|
||||||
11 => Some(Instruction::Multiply),
|
11 => Some(Instruction::Divide),
|
||||||
12 => Some(Instruction::Divide),
|
12 => Some(Instruction::Greater),
|
||||||
13 => Some(Instruction::Greater),
|
13 => Some(Instruction::Less),
|
||||||
14 => Some(Instruction::Less),
|
14 => Some(Instruction::GreaterEqual),
|
||||||
15 => Some(Instruction::GreaterEqual),
|
15 => Some(Instruction::LessEqual),
|
||||||
16 => Some(Instruction::LessEqual),
|
16 => Some(Instruction::Equal),
|
||||||
17 => Some(Instruction::Equal),
|
17 => Some(Instruction::NotEqual),
|
||||||
18 => Some(Instruction::NotEqual),
|
18 => Some(Instruction::And),
|
||||||
19 => Some(Instruction::And),
|
19 => Some(Instruction::Or),
|
||||||
20 => Some(Instruction::Or),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble(&self, chunk: &Chunk, offset: usize) -> String {
|
pub fn disassemble(&self, chunk: &Chunk, offset: usize) -> String {
|
||||||
|
let dummy_position = Span(0, 0);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Instruction::Constant => {
|
Instruction::Constant => {
|
||||||
let (argument, _) = chunk.get_code(offset + 1).unwrap();
|
let (argument, position) = *chunk.get_code(offset + 1, dummy_position).unwrap();
|
||||||
let value_display = chunk
|
let value_display = chunk
|
||||||
.get_constant(*argument)
|
.get_constant(argument, position)
|
||||||
.map(|value| value.to_string())
|
.map(|value| value.to_string())
|
||||||
.unwrap_or_else(|error| error.to_string());
|
.unwrap_or_else(|error| error.to_string());
|
||||||
|
|
||||||
format!("CONSTANT {argument} {value_display}")
|
format!("CONSTANT {value_display}")
|
||||||
}
|
}
|
||||||
Instruction::Return => "RETURN".to_string(),
|
Instruction::Return => "RETURN".to_string(),
|
||||||
Instruction::Pop => "POP".to_string(),
|
Instruction::Pop => "POP".to_string(),
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
Instruction::DefineVariableRuntime => "DEFINE_VARIABLE_RUNTIME".to_string(),
|
Instruction::DefineVariable => {
|
||||||
Instruction::DefineVariableConstant => {
|
let (argument, _) = chunk.get_code(offset + 1, dummy_position).unwrap();
|
||||||
let (argument, _) = chunk.get_code(offset + 1).unwrap();
|
|
||||||
let identifier_display = match chunk.get_identifier(*argument) {
|
let identifier_display = match chunk.get_identifier(*argument) {
|
||||||
Ok(identifier) => identifier.to_string(),
|
Ok(identifier) => identifier.to_string(),
|
||||||
Err(error) => error.to_string(),
|
Err(error) => error.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
format!("DEFINE_VARIABLE_CONSTANT {argument} {identifier_display}")
|
format!("DEFINE_VARIABLE {identifier_display}")
|
||||||
}
|
}
|
||||||
Instruction::GetVariable => {
|
Instruction::GetVariable => {
|
||||||
let (argument, _) = chunk.get_code(offset + 1).unwrap();
|
let (argument, _) = chunk.get_code(offset + 1, dummy_position).unwrap();
|
||||||
let identifier_display = match chunk.get_identifier(*argument) {
|
let identifier_display = match chunk.get_identifier(*argument) {
|
||||||
Ok(identifier) => identifier.to_string(),
|
Ok(identifier) => identifier.to_string(),
|
||||||
Err(error) => error.to_string(),
|
Err(error) => error.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
format!("GET_VARIABLE {argument} {identifier_display}")
|
format!("GET_VARIABLE {identifier_display}")
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction::SetVariable => {
|
Instruction::SetVariable => {
|
||||||
let (argument, _) = chunk.get_code(offset + 1).unwrap();
|
let (argument, _) = chunk.get_code(offset + 1, dummy_position).unwrap();
|
||||||
let identifier_display = match chunk.get_identifier(*argument) {
|
let identifier_display = match chunk.get_identifier(*argument) {
|
||||||
Ok(identifier) => identifier.to_string(),
|
Ok(identifier) => identifier.to_string(),
|
||||||
Err(error) => error.to_string(),
|
Err(error) => error.to_string(),
|
||||||
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dust_error::AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, LexError,
|
dust_error::AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, LexError,
|
||||||
Lexer, Span, Token, TokenKind, TokenOwned, Value,
|
Lexer, Local, Span, Token, TokenKind, TokenOwned, Value, ValueLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
pub fn parse(source: &str) -> Result<Chunk, DustError> {
|
||||||
@ -234,10 +234,10 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_variable(&mut self, allow_assignment: bool) -> Result<(), ParseError> {
|
fn parse_variable(&mut self, allow_assignment: bool) -> Result<(), ParseError> {
|
||||||
self.parse_named_variable_from(allow_assignment)
|
self.parse_named_variable(allow_assignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_named_variable_from(&mut self, allow_assignment: bool) -> Result<(), ParseError> {
|
fn parse_named_variable(&mut self, allow_assignment: bool) -> Result<(), ParseError> {
|
||||||
let token = self.previous_token.to_owned();
|
let token = self.previous_token.to_owned();
|
||||||
let identifier_index = self.parse_identifier_from(token)?;
|
let identifier_index = self.parse_identifier_from(token)?;
|
||||||
|
|
||||||
@ -256,9 +256,10 @@ impl<'src> Parser<'src> {
|
|||||||
fn parse_identifier_from(&mut self, token: TokenOwned) -> Result<u8, ParseError> {
|
fn parse_identifier_from(&mut self, token: TokenOwned) -> Result<u8, ParseError> {
|
||||||
if let TokenOwned::Identifier(text) = token {
|
if let TokenOwned::Identifier(text) = token {
|
||||||
let identifier = Identifier::new(text);
|
let identifier = Identifier::new(text);
|
||||||
|
|
||||||
let identifier_index =
|
let identifier_index =
|
||||||
self.chunk
|
self.chunk
|
||||||
.get_identifier_index(&identifier)
|
.push_constant_identifier(identifier)
|
||||||
.map_err(|error| ParseError::Chunk {
|
.map_err(|error| ParseError::Chunk {
|
||||||
error,
|
error,
|
||||||
position: self.previous_position,
|
position: self.previous_position,
|
||||||
@ -337,35 +338,16 @@ impl<'src> Parser<'src> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.expect(TokenKind::Equal)?;
|
self.expect(TokenKind::Equal)?;
|
||||||
|
self.parse_expression()?;
|
||||||
|
|
||||||
let is_constant = matches!(
|
let identifier_index = self
|
||||||
self.current_token,
|
.chunk
|
||||||
Token::Boolean(_)
|
.push_constant_identifier(identifier)
|
||||||
| Token::Byte(_)
|
|
||||||
| Token::Character(_)
|
|
||||||
| Token::Float(_)
|
|
||||||
| Token::Integer(_)
|
|
||||||
| Token::String(_)
|
|
||||||
);
|
|
||||||
|
|
||||||
let identifier_index = if is_constant {
|
|
||||||
self.chunk.push_constant_identifier(identifier)
|
|
||||||
} else {
|
|
||||||
self.chunk.push_runtime_identifier(identifier)
|
|
||||||
}
|
|
||||||
.map_err(|error| ParseError::Chunk { error, position })?;
|
.map_err(|error| ParseError::Chunk { error, position })?;
|
||||||
|
|
||||||
if is_constant {
|
self.emit_byte(Instruction::DefineVariable, position);
|
||||||
self.emit_byte(Instruction::DefineVariableConstant, position);
|
|
||||||
self.emit_byte(identifier_index, position);
|
self.emit_byte(identifier_index, position);
|
||||||
|
|
||||||
self.parse_expression()?;
|
|
||||||
} else {
|
|
||||||
self.parse_expression()?;
|
|
||||||
|
|
||||||
self.emit_byte(Instruction::DefineVariableRuntime, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,11 +711,11 @@ mod tests {
|
|||||||
test_chunk,
|
test_chunk,
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![
|
vec![
|
||||||
(Instruction::DefineVariableConstant as u8, Span(4, 5)),
|
(Instruction::DefineVariable as u8, Span(4, 5)),
|
||||||
(0, Span(4, 5)),
|
(0, Span(4, 5)),
|
||||||
(Instruction::Constant as u8, Span(8, 10)),
|
(Instruction::Constant as u8, Span(8, 10)),
|
||||||
(0, Span(8, 10)),
|
(0, Span(8, 10)),
|
||||||
(Instruction::DefineVariableConstant as u8, Span(16, 17)),
|
(Instruction::DefineVariable as u8, Span(16, 17)),
|
||||||
(1, Span(16, 17)),
|
(1, Span(16, 17)),
|
||||||
(Instruction::Constant as u8, Span(20, 22)),
|
(Instruction::Constant as u8, Span(20, 22)),
|
||||||
(1, Span(20, 22)),
|
(1, Span(20, 22)),
|
||||||
@ -770,7 +752,7 @@ mod tests {
|
|||||||
test_chunk,
|
test_chunk,
|
||||||
Ok(Chunk::with_data(
|
Ok(Chunk::with_data(
|
||||||
vec![
|
vec![
|
||||||
(Instruction::DefineVariableConstant as u8, Span(4, 5)),
|
(Instruction::DefineVariable as u8, Span(4, 5)),
|
||||||
(0, Span(4, 5)),
|
(0, Span(4, 5)),
|
||||||
(Instruction::Constant as u8, Span(8, 10)),
|
(Instruction::Constant as u8, Span(8, 10)),
|
||||||
(0, Span(8, 10)),
|
(0, Span(8, 10)),
|
||||||
|
@ -796,7 +796,7 @@ impl From<&str> for Value {
|
|||||||
|
|
||||||
impl Clone for Value {
|
impl Clone for Value {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
log::trace!("Cloning value: {:?}", self);
|
log::trace!("Cloning value {:?}", self);
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Value::Raw(data) => Value::Raw(data.clone()),
|
Value::Raw(data) => Value::Raw(data.clone()),
|
||||||
|
@ -45,9 +45,12 @@ impl Vm {
|
|||||||
|
|
||||||
match instruction {
|
match instruction {
|
||||||
Instruction::Constant => {
|
Instruction::Constant => {
|
||||||
let (argument, _) = self.read(position).copied()?;
|
let (argument, _) = *self.read(position)?;
|
||||||
|
let value = self.chunk.get_constant(argument, position)?.clone();
|
||||||
|
|
||||||
self.push_constant_value(argument, position)?;
|
log::trace!("Pushing constant {value}");
|
||||||
|
|
||||||
|
self.push_runtime_value(value, position)?;
|
||||||
}
|
}
|
||||||
Instruction::Return => {
|
Instruction::Return => {
|
||||||
let stacked = self.pop(position)?;
|
let stacked = self.pop(position)?;
|
||||||
@ -55,73 +58,76 @@ impl Vm {
|
|||||||
StackedValue::Runtime(value) => value,
|
StackedValue::Runtime(value) => value,
|
||||||
StackedValue::Constant(index) => Rc::get_mut(&mut self.chunk)
|
StackedValue::Constant(index) => Rc::get_mut(&mut self.chunk)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.remove_constant(index)
|
.remove_constant(index, position)?,
|
||||||
.map_err(|error| VmError::Chunk { error, position })?,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::trace!("Returning {value}");
|
||||||
|
|
||||||
return Ok(Some(value));
|
return Ok(Some(value));
|
||||||
}
|
}
|
||||||
Instruction::Pop => {
|
Instruction::Pop => {
|
||||||
self.pop(position)?;
|
let value = self.pop(position)?;
|
||||||
|
|
||||||
|
log::trace!("Popping {value:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
Instruction::DefineVariableRuntime => {
|
Instruction::DefineVariable => {
|
||||||
let value = self.pop(position)?.resolve(&self.chunk, position)?.clone();
|
let (argument, _) = *self.read(position)?;
|
||||||
|
let identifier = self.chunk.get_identifier(argument)?.clone();
|
||||||
|
let stack_index_option = self.chunk.resolve_local(&identifier);
|
||||||
|
|
||||||
|
if let Some(index) = stack_index_option {
|
||||||
|
let value = self.stack[index as usize]
|
||||||
|
.to_value(&self.chunk, position)?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
log::trace!("Defining {identifier} as value {value}");
|
||||||
|
|
||||||
self.push_runtime_value(value, position)?;
|
self.push_runtime_value(value, position)?;
|
||||||
|
} else {
|
||||||
|
return Err(VmError::UndefinedVariable {
|
||||||
|
identifier,
|
||||||
|
position,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Instruction::DefineVariableConstant => {
|
|
||||||
let (argument, _) = *self.read(position)?;
|
|
||||||
|
|
||||||
self.push_constant_value(argument, position)?;
|
|
||||||
}
|
}
|
||||||
Instruction::GetVariable => {
|
Instruction::GetVariable => {
|
||||||
let (argument, _) = *self.read(position)?;
|
let (argument, _) = *self.read(position)?;
|
||||||
|
let value = self.pop(position)?.to_value(&self.chunk, position)?.clone();
|
||||||
|
|
||||||
let local = self
|
log::trace!(
|
||||||
.chunk
|
"Getting {} as value {value}",
|
||||||
.get_local(argument)
|
self.chunk.get_identifier(argument)?,
|
||||||
.map_err(|error| VmError::Chunk { error, position })?;
|
);
|
||||||
|
|
||||||
match local.value_location {
|
|
||||||
ValueLocation::ConstantStack => {
|
|
||||||
let value = self
|
|
||||||
.chunk
|
|
||||||
.get_constant(argument)
|
|
||||||
.map_err(|error| VmError::Chunk { error, position })?
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
self.push_runtime_value(value, position)?;
|
self.push_runtime_value(value, position)?;
|
||||||
}
|
}
|
||||||
ValueLocation::RuntimeStack => {
|
|
||||||
let value = self.pop(position)?.resolve(&self.chunk, position)?.clone();
|
|
||||||
|
|
||||||
self.push_runtime_value(value, position)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Instruction::SetVariable => {
|
Instruction::SetVariable => {
|
||||||
let (argument, _) = *self.read(position)?;
|
let (argument, _) = *self.read(position)?;
|
||||||
let identifier = self
|
let identifier = self.chunk.get_identifier(argument)?.clone();
|
||||||
.chunk
|
|
||||||
.get_identifier(argument)
|
|
||||||
.map_err(|error| VmError::Chunk { error, position })?;
|
|
||||||
|
|
||||||
if !self.chunk.contains_identifier(identifier) {
|
if !self.chunk.contains_identifier(&identifier) {
|
||||||
return Err(VmError::UndefinedVariable(identifier.clone(), position));
|
return Err(VmError::UndefinedVariable {
|
||||||
|
identifier,
|
||||||
|
position,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let stacked = self.pop(position)?;
|
let value = self.stack[argument as usize]
|
||||||
|
.to_value(&self.chunk, position)?
|
||||||
|
.clone();
|
||||||
|
|
||||||
self.stack[argument as usize] = stacked;
|
log::trace!("Setting {identifier} to {value}");
|
||||||
|
|
||||||
|
self.push_runtime_value(value, position)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unary
|
// Unary
|
||||||
Instruction::Negate => {
|
Instruction::Negate => {
|
||||||
let negated = self
|
let negated = self
|
||||||
.pop(position)?
|
.pop(position)?
|
||||||
.resolve(&self.chunk, position)?
|
.to_value(&self.chunk, position)?
|
||||||
.negate()
|
.negate()
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
@ -130,7 +136,7 @@ impl Vm {
|
|||||||
Instruction::Not => {
|
Instruction::Not => {
|
||||||
let not = self
|
let not = self
|
||||||
.pop(position)?
|
.pop(position)?
|
||||||
.resolve(&self.chunk, position)?
|
.to_value(&self.chunk, position)?
|
||||||
.not()
|
.not()
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
|
|
||||||
@ -141,9 +147,9 @@ impl Vm {
|
|||||||
Instruction::Add => {
|
Instruction::Add => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let sum = left
|
let sum = left
|
||||||
.add(right)
|
.add(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -153,9 +159,9 @@ impl Vm {
|
|||||||
Instruction::Subtract => {
|
Instruction::Subtract => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let difference = left
|
let difference = left
|
||||||
.subtract(right)
|
.subtract(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -165,9 +171,9 @@ impl Vm {
|
|||||||
Instruction::Multiply => {
|
Instruction::Multiply => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let product = left
|
let product = left
|
||||||
.multiply(right)
|
.multiply(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -177,9 +183,9 @@ impl Vm {
|
|||||||
Instruction::Divide => {
|
Instruction::Divide => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let quotient = left
|
let quotient = left
|
||||||
.divide(right)
|
.divide(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -189,9 +195,9 @@ impl Vm {
|
|||||||
Instruction::Greater => {
|
Instruction::Greater => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let greater = left
|
let greater = left
|
||||||
.greater_than(right)
|
.greater_than(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -201,9 +207,9 @@ impl Vm {
|
|||||||
Instruction::Less => {
|
Instruction::Less => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let less = left
|
let less = left
|
||||||
.less_than(right)
|
.less_than(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -213,9 +219,9 @@ impl Vm {
|
|||||||
Instruction::GreaterEqual => {
|
Instruction::GreaterEqual => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let greater_equal = left
|
let greater_equal = left
|
||||||
.greater_than_or_equal(right)
|
.greater_than_or_equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -225,9 +231,9 @@ impl Vm {
|
|||||||
Instruction::LessEqual => {
|
Instruction::LessEqual => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let less_equal = left
|
let less_equal = left
|
||||||
.less_than_or_equal(right)
|
.less_than_or_equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -237,9 +243,9 @@ impl Vm {
|
|||||||
Instruction::Equal => {
|
Instruction::Equal => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let equal = left
|
let equal = left
|
||||||
.equal(right)
|
.equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -249,9 +255,9 @@ impl Vm {
|
|||||||
Instruction::NotEqual => {
|
Instruction::NotEqual => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let not_equal = left
|
let not_equal = left
|
||||||
.not_equal(right)
|
.not_equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -261,9 +267,9 @@ impl Vm {
|
|||||||
Instruction::And => {
|
Instruction::And => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let and = left
|
let and = left
|
||||||
.and(right)
|
.and(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -273,9 +279,9 @@ impl Vm {
|
|||||||
Instruction::Or => {
|
Instruction::Or => {
|
||||||
let chunk = self.chunk.clone();
|
let chunk = self.chunk.clone();
|
||||||
let right_stacked = self.pop(position)?;
|
let right_stacked = self.pop(position)?;
|
||||||
let right = right_stacked.resolve(chunk.as_ref(), position)?;
|
let right = right_stacked.to_value(chunk.as_ref(), position)?;
|
||||||
let left_stacked = self.pop(position)?;
|
let left_stacked = self.pop(position)?;
|
||||||
let left = left_stacked.resolve(&self.chunk, position)?;
|
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||||
let or = left
|
let or = left
|
||||||
.or(right)
|
.or(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
.map_err(|error| VmError::Value { error, position })?;
|
||||||
@ -323,10 +329,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self, position: Span) -> Result<&(u8, Span), VmError> {
|
fn read(&mut self, position: Span) -> Result<&(u8, Span), VmError> {
|
||||||
let current = self
|
let current = self.chunk.get_code(self.ip, position)?;
|
||||||
.chunk
|
|
||||||
.get_code(self.ip)
|
|
||||||
.map_err(|error| VmError::Chunk { error, position })?;
|
|
||||||
|
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
|
||||||
@ -341,12 +344,10 @@ pub enum StackedValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StackedValue {
|
impl StackedValue {
|
||||||
fn resolve<'a>(&'a self, chunk: &'a Chunk, position: Span) -> Result<&'a Value, VmError> {
|
fn to_value<'a>(&'a self, chunk: &'a Chunk, position: Span) -> Result<&'a Value, VmError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Runtime(value) => Ok(value),
|
Self::Runtime(value) => Ok(value),
|
||||||
Self::Constant(index) => chunk
|
Self::Constant(index) => Ok(chunk.get_constant(*index, position)?),
|
||||||
.get_constant(*index)
|
|
||||||
.map_err(|error| VmError::Chunk { error, position }),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,20 +357,22 @@ pub enum VmError {
|
|||||||
InvalidInstruction(u8, Span),
|
InvalidInstruction(u8, Span),
|
||||||
StackOverflow(Span),
|
StackOverflow(Span),
|
||||||
StackUnderflow(Span),
|
StackUnderflow(Span),
|
||||||
UndefinedVariable(Identifier, Span),
|
UndefinedVariable {
|
||||||
|
identifier: Identifier,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
|
|
||||||
// Wrappers for foreign errors
|
// Wrappers for foreign errors
|
||||||
Chunk { error: ChunkError, position: Span },
|
Chunk(ChunkError),
|
||||||
Value { error: ValueError, position: Span },
|
Value {
|
||||||
|
error: ValueError,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmError {
|
impl From<ChunkError> for VmError {
|
||||||
pub fn chunk(error: ChunkError, position: Span) -> Self {
|
fn from(v: ChunkError) -> Self {
|
||||||
Self::Chunk { error, position }
|
Self::Chunk(v)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value(error: ValueError, position: Span) -> Self {
|
|
||||||
Self::Value { error, position }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,8 +386,8 @@ impl AnnotatedError for VmError {
|
|||||||
Self::InvalidInstruction(_, _) => "Invalid instruction",
|
Self::InvalidInstruction(_, _) => "Invalid instruction",
|
||||||
Self::StackOverflow(_) => "Stack overflow",
|
Self::StackOverflow(_) => "Stack overflow",
|
||||||
Self::StackUnderflow(_) => "Stack underflow",
|
Self::StackUnderflow(_) => "Stack underflow",
|
||||||
Self::UndefinedVariable(_, _) => "Undefined variable",
|
Self::UndefinedVariable { .. } => "Undefined variable",
|
||||||
Self::Chunk { .. } => "Chunk error",
|
Self::Chunk(_) => "Chunk error",
|
||||||
Self::Value { .. } => "Value error",
|
Self::Value { .. } => "Value error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,11 +399,11 @@ impl AnnotatedError for VmError {
|
|||||||
)),
|
)),
|
||||||
Self::StackOverflow(position) => Some(format!("Stack overflow at {position}")),
|
Self::StackOverflow(position) => Some(format!("Stack overflow at {position}")),
|
||||||
Self::StackUnderflow(position) => Some(format!("Stack underflow at {position}")),
|
Self::StackUnderflow(position) => Some(format!("Stack underflow at {position}")),
|
||||||
Self::UndefinedVariable(identifier, position) => {
|
Self::UndefinedVariable { identifier, .. } => {
|
||||||
Some(format!("{identifier} is not in scope at {position}"))
|
Some(format!("{identifier} is not in scope"))
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Chunk { error, .. } => Some(error.to_string()),
|
Self::Chunk(error) => Some(error.to_string()),
|
||||||
Self::Value { error, .. } => Some(error.to_string()),
|
Self::Value { error, .. } => Some(error.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,8 +413,8 @@ impl AnnotatedError for VmError {
|
|||||||
Self::InvalidInstruction(_, position) => *position,
|
Self::InvalidInstruction(_, position) => *position,
|
||||||
Self::StackUnderflow(position) => *position,
|
Self::StackUnderflow(position) => *position,
|
||||||
Self::StackOverflow(position) => *position,
|
Self::StackOverflow(position) => *position,
|
||||||
Self::UndefinedVariable(_, position) => *position,
|
Self::UndefinedVariable { position, .. } => *position,
|
||||||
Self::Chunk { position, .. } => *position,
|
Self::Chunk(error) => error.position(),
|
||||||
Self::Value { position, .. } => *position,
|
Self::Value { position, .. } => *position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,7 @@ repository.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.14", features = ["derive"] }
|
clap = { version = "4.5.14", features = ["derive"] }
|
||||||
|
colored = "2.1.0"
|
||||||
dust-lang = { path = "../dust-lang" }
|
dust-lang = { path = "../dust-lang" }
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
|
log = "0.4.22"
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use std::fs::read_to_string;
|
use std::{fs::read_to_string, io::Write};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use colored::Colorize;
|
||||||
use dust_lang::{parse, run};
|
use dust_lang::{parse, run};
|
||||||
use env_logger::WriteStyle;
|
use log::Level;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
@ -18,8 +19,21 @@ struct Cli {
|
|||||||
fn main() {
|
fn main() {
|
||||||
env_logger::builder()
|
env_logger::builder()
|
||||||
.parse_env("DUST_LOG")
|
.parse_env("DUST_LOG")
|
||||||
.format_timestamp_secs()
|
.format(|buf, record| {
|
||||||
.write_style(WriteStyle::Always)
|
let level = match record.level() {
|
||||||
|
Level::Error => "ERROR".red(),
|
||||||
|
Level::Warn => "WARN".yellow(),
|
||||||
|
Level::Info => "INFO".white(),
|
||||||
|
Level::Debug => "DEBUG".blue(),
|
||||||
|
Level::Trace => "TRACE".purple(),
|
||||||
|
};
|
||||||
|
let module = record
|
||||||
|
.module_path()
|
||||||
|
.map(|path| path.split("::").last().unwrap_or("UNKNOWN").to_uppercase())
|
||||||
|
.unwrap_or("UNKNOWN".to_string());
|
||||||
|
|
||||||
|
writeln!(buf, "[{level:^5}] {module:^6} {}", record.args())
|
||||||
|
})
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
Loading…
Reference in New Issue
Block a user