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"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -66,7 +66,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -121,6 +121,16 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
@ -164,8 +174,10 @@ name = "dust-shell"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"colored",
|
||||
"dust-lang",
|
||||
"env_logger",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -226,6 +238,12 @@ version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
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"
|
||||
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]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
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]]
|
||||
@ -440,51 +482,93 @@ version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.52.4",
|
||||
"windows_aarch64_msvc 0.52.4",
|
||||
"windows_i686_gnu 0.52.4",
|
||||
"windows_i686_msvc 0.52.4",
|
||||
"windows_x86_64_gnu 0.52.4",
|
||||
"windows_x86_64_gnullvm 0.52.4",
|
||||
"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]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
|
@ -3,7 +3,8 @@ use std::fmt::{self, Debug, Display, Formatter};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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)]
|
||||
@ -42,27 +43,34 @@ impl Chunk {
|
||||
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
|
||||
.get(offset)
|
||||
.ok_or(ChunkError::CodeIndexOfBounds(offset))
|
||||
.ok_or(ChunkError::CodeIndexOfBounds { offset, position })
|
||||
}
|
||||
|
||||
pub fn push_code(&mut self, instruction: u8, position: Span) {
|
||||
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
|
||||
.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;
|
||||
|
||||
if index >= self.constants.len() {
|
||||
Err(ChunkError::ConstantIndexOutOfBounds(index as u8))
|
||||
Err(ChunkError::ConstantIndexOutOfBounds {
|
||||
index: index as u8,
|
||||
position,
|
||||
})
|
||||
} else {
|
||||
Ok(self.constants.remove(index))
|
||||
}
|
||||
@ -90,6 +98,14 @@ impl Chunk {
|
||||
.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> {
|
||||
self.identifiers
|
||||
.get(index as usize)
|
||||
@ -97,10 +113,18 @@ impl Chunk {
|
||||
.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
|
||||
.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> {
|
||||
@ -110,7 +134,7 @@ impl Chunk {
|
||||
Err(ChunkError::IdentifierOverflow)
|
||||
} else {
|
||||
self.identifiers
|
||||
.declare(identifier, ValueLocation::ConstantStack);
|
||||
.define(identifier, ValueLocation::ConstantStack);
|
||||
|
||||
Ok(starting_length as u8)
|
||||
}
|
||||
@ -123,12 +147,25 @@ impl Chunk {
|
||||
Err(ChunkError::IdentifierOverflow)
|
||||
} else {
|
||||
self.identifiers
|
||||
.declare(identifier, ValueLocation::RuntimeStack);
|
||||
.define(identifier, ValueLocation::RuntimeStack);
|
||||
|
||||
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) {
|
||||
self.identifiers.begin_scope();
|
||||
}
|
||||
@ -162,7 +199,7 @@ impl Chunk {
|
||||
for (offset, (byte, position)) in self.code.iter().enumerate() {
|
||||
if let Some(
|
||||
Instruction::Constant
|
||||
| Instruction::DefineVariableConstant
|
||||
| Instruction::DefineVariable
|
||||
| Instruction::GetVariable
|
||||
| Instruction::SetVariable,
|
||||
) = previous
|
||||
@ -179,9 +216,9 @@ impl Chunk {
|
||||
instruction.disassemble(self, offset)
|
||||
);
|
||||
|
||||
previous = Some(instruction);
|
||||
|
||||
output.push_str(&display);
|
||||
|
||||
previous = Some(instruction);
|
||||
}
|
||||
|
||||
output.push_str("\n Constants \n");
|
||||
@ -245,29 +282,80 @@ impl Debug for Chunk {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ChunkError {
|
||||
CodeIndexOfBounds(usize),
|
||||
CodeIndexOfBounds {
|
||||
offset: usize,
|
||||
position: Span,
|
||||
},
|
||||
ConstantOverflow,
|
||||
ConstantIndexOutOfBounds(u8),
|
||||
ConstantIndexOutOfBounds {
|
||||
index: u8,
|
||||
position: Span,
|
||||
},
|
||||
IdentifierIndexOutOfBounds(u8),
|
||||
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 {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ChunkError::CodeIndexOfBounds(offset) => {
|
||||
ChunkError::CodeIndexOfBounds { offset, .. } => {
|
||||
write!(f, "Code index out of bounds: {}", offset)
|
||||
}
|
||||
ChunkError::ConstantOverflow => write!(f, "Constant overflow"),
|
||||
ChunkError::ConstantIndexOutOfBounds(index) => {
|
||||
ChunkError::ConstantIndexOutOfBounds { index, .. } => {
|
||||
write!(f, "Constant index out of bounds: {}", index)
|
||||
}
|
||||
ChunkError::IdentifierIndexOutOfBounds(index) => {
|
||||
write!(f, "Identifier index out of bounds: {}", index)
|
||||
}
|
||||
ChunkError::IdentifierOverflow => write!(f, "Identifier overflow"),
|
||||
ChunkError::IdentifierNotFound(identifier) => {
|
||||
ChunkError::IdentifierNotFound { identifier, .. } => {
|
||||
write!(f, "Identifier not found: {}", identifier)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Identifier;
|
||||
use crate::{Chunk, Identifier};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IdentifierStack {
|
||||
@ -41,11 +41,33 @@ impl IdentifierStack {
|
||||
.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> {
|
||||
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(
|
||||
|(
|
||||
index,
|
||||
@ -54,7 +76,7 @@ impl IdentifierStack {
|
||||
},
|
||||
)| {
|
||||
if local == identifier {
|
||||
Some(index as u8)
|
||||
Some(index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -62,6 +84,10 @@ impl IdentifierStack {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn scope_depth(&self) -> usize {
|
||||
self.scope_depth
|
||||
}
|
||||
|
||||
pub fn begin_scope(&mut self) {
|
||||
self.scope_depth += 1;
|
||||
}
|
||||
@ -70,7 +96,7 @@ impl IdentifierStack {
|
||||
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 {
|
||||
identifier,
|
||||
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> {
|
||||
self.locals.iter()
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Chunk;
|
||||
use crate::{Chunk, Span};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Instruction {
|
||||
@ -11,28 +11,27 @@ pub enum Instruction {
|
||||
Pop = 2,
|
||||
|
||||
// Variables
|
||||
DefineVariableRuntime = 3,
|
||||
DefineVariableConstant = 4,
|
||||
GetVariable = 5,
|
||||
SetVariable = 6,
|
||||
DefineVariable = 3,
|
||||
GetVariable = 4,
|
||||
SetVariable = 5,
|
||||
|
||||
// Unary
|
||||
Negate = 7,
|
||||
Not = 8,
|
||||
Negate = 6,
|
||||
Not = 7,
|
||||
|
||||
// Binary
|
||||
Add = 9,
|
||||
Subtract = 10,
|
||||
Multiply = 11,
|
||||
Divide = 12,
|
||||
Greater = 13,
|
||||
Less = 14,
|
||||
GreaterEqual = 15,
|
||||
LessEqual = 16,
|
||||
Equal = 17,
|
||||
NotEqual = 18,
|
||||
And = 19,
|
||||
Or = 20,
|
||||
Add = 8,
|
||||
Subtract = 9,
|
||||
Multiply = 10,
|
||||
Divide = 11,
|
||||
Greater = 12,
|
||||
Less = 13,
|
||||
GreaterEqual = 14,
|
||||
LessEqual = 15,
|
||||
Equal = 16,
|
||||
NotEqual = 17,
|
||||
And = 18,
|
||||
Or = 19,
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
@ -41,65 +40,65 @@ impl Instruction {
|
||||
0 => Some(Instruction::Constant),
|
||||
1 => Some(Instruction::Return),
|
||||
2 => Some(Instruction::Pop),
|
||||
3 => Some(Instruction::DefineVariableRuntime),
|
||||
4 => Some(Instruction::DefineVariableConstant),
|
||||
5 => Some(Instruction::GetVariable),
|
||||
6 => Some(Instruction::SetVariable),
|
||||
7 => Some(Instruction::Negate),
|
||||
8 => Some(Instruction::Not),
|
||||
9 => Some(Instruction::Add),
|
||||
10 => Some(Instruction::Subtract),
|
||||
11 => Some(Instruction::Multiply),
|
||||
12 => Some(Instruction::Divide),
|
||||
13 => Some(Instruction::Greater),
|
||||
14 => Some(Instruction::Less),
|
||||
15 => Some(Instruction::GreaterEqual),
|
||||
16 => Some(Instruction::LessEqual),
|
||||
17 => Some(Instruction::Equal),
|
||||
18 => Some(Instruction::NotEqual),
|
||||
19 => Some(Instruction::And),
|
||||
20 => Some(Instruction::Or),
|
||||
3 => Some(Instruction::DefineVariable),
|
||||
4 => Some(Instruction::GetVariable),
|
||||
5 => Some(Instruction::SetVariable),
|
||||
6 => Some(Instruction::Negate),
|
||||
7 => Some(Instruction::Not),
|
||||
8 => Some(Instruction::Add),
|
||||
9 => Some(Instruction::Subtract),
|
||||
10 => Some(Instruction::Multiply),
|
||||
11 => Some(Instruction::Divide),
|
||||
12 => Some(Instruction::Greater),
|
||||
13 => Some(Instruction::Less),
|
||||
14 => Some(Instruction::GreaterEqual),
|
||||
15 => Some(Instruction::LessEqual),
|
||||
16 => Some(Instruction::Equal),
|
||||
17 => Some(Instruction::NotEqual),
|
||||
18 => Some(Instruction::And),
|
||||
19 => Some(Instruction::Or),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disassemble(&self, chunk: &Chunk, offset: usize) -> String {
|
||||
let dummy_position = Span(0, 0);
|
||||
|
||||
match self {
|
||||
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
|
||||
.get_constant(*argument)
|
||||
.get_constant(argument, position)
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|error| error.to_string());
|
||||
|
||||
format!("CONSTANT {argument} {value_display}")
|
||||
format!("CONSTANT {value_display}")
|
||||
}
|
||||
Instruction::Return => "RETURN".to_string(),
|
||||
Instruction::Pop => "POP".to_string(),
|
||||
|
||||
// Variables
|
||||
Instruction::DefineVariableRuntime => "DEFINE_VARIABLE_RUNTIME".to_string(),
|
||||
Instruction::DefineVariableConstant => {
|
||||
let (argument, _) = chunk.get_code(offset + 1).unwrap();
|
||||
Instruction::DefineVariable => {
|
||||
let (argument, _) = chunk.get_code(offset + 1, dummy_position).unwrap();
|
||||
let identifier_display = match chunk.get_identifier(*argument) {
|
||||
Ok(identifier) => identifier.to_string(),
|
||||
Err(error) => error.to_string(),
|
||||
};
|
||||
|
||||
format!("DEFINE_VARIABLE_CONSTANT {argument} {identifier_display}")
|
||||
format!("DEFINE_VARIABLE {identifier_display}")
|
||||
}
|
||||
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) {
|
||||
Ok(identifier) => identifier.to_string(),
|
||||
Err(error) => error.to_string(),
|
||||
};
|
||||
|
||||
format!("GET_VARIABLE {argument} {identifier_display}")
|
||||
format!("GET_VARIABLE {identifier_display}")
|
||||
}
|
||||
|
||||
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) {
|
||||
Ok(identifier) => identifier.to_string(),
|
||||
Err(error) => error.to_string(),
|
||||
|
@ -6,7 +6,7 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
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> {
|
||||
@ -234,10 +234,10 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
|
||||
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 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> {
|
||||
if let TokenOwned::Identifier(text) = token {
|
||||
let identifier = Identifier::new(text);
|
||||
|
||||
let identifier_index =
|
||||
self.chunk
|
||||
.get_identifier_index(&identifier)
|
||||
.push_constant_identifier(identifier)
|
||||
.map_err(|error| ParseError::Chunk {
|
||||
error,
|
||||
position: self.previous_position,
|
||||
@ -337,35 +338,16 @@ impl<'src> Parser<'src> {
|
||||
};
|
||||
|
||||
self.expect(TokenKind::Equal)?;
|
||||
self.parse_expression()?;
|
||||
|
||||
let is_constant = matches!(
|
||||
self.current_token,
|
||||
Token::Boolean(_)
|
||||
| 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)
|
||||
}
|
||||
let identifier_index = self
|
||||
.chunk
|
||||
.push_constant_identifier(identifier)
|
||||
.map_err(|error| ParseError::Chunk { error, position })?;
|
||||
|
||||
if is_constant {
|
||||
self.emit_byte(Instruction::DefineVariableConstant, position);
|
||||
self.emit_byte(Instruction::DefineVariable, position);
|
||||
self.emit_byte(identifier_index, position);
|
||||
|
||||
self.parse_expression()?;
|
||||
} else {
|
||||
self.parse_expression()?;
|
||||
|
||||
self.emit_byte(Instruction::DefineVariableRuntime, position);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -729,11 +711,11 @@ mod tests {
|
||||
test_chunk,
|
||||
Ok(Chunk::with_data(
|
||||
vec![
|
||||
(Instruction::DefineVariableConstant as u8, Span(4, 5)),
|
||||
(Instruction::DefineVariable as u8, Span(4, 5)),
|
||||
(0, Span(4, 5)),
|
||||
(Instruction::Constant as u8, 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)),
|
||||
(Instruction::Constant as u8, Span(20, 22)),
|
||||
(1, Span(20, 22)),
|
||||
@ -770,7 +752,7 @@ mod tests {
|
||||
test_chunk,
|
||||
Ok(Chunk::with_data(
|
||||
vec![
|
||||
(Instruction::DefineVariableConstant as u8, Span(4, 5)),
|
||||
(Instruction::DefineVariable as u8, Span(4, 5)),
|
||||
(0, Span(4, 5)),
|
||||
(Instruction::Constant as u8, Span(8, 10)),
|
||||
(0, Span(8, 10)),
|
||||
|
@ -796,7 +796,7 @@ impl From<&str> for Value {
|
||||
|
||||
impl Clone for Value {
|
||||
fn clone(&self) -> Self {
|
||||
log::trace!("Cloning value: {:?}", self);
|
||||
log::trace!("Cloning value {:?}", self);
|
||||
|
||||
match self {
|
||||
Value::Raw(data) => Value::Raw(data.clone()),
|
||||
|
@ -45,9 +45,12 @@ impl Vm {
|
||||
|
||||
match instruction {
|
||||
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 => {
|
||||
let stacked = self.pop(position)?;
|
||||
@ -55,73 +58,76 @@ impl Vm {
|
||||
StackedValue::Runtime(value) => value,
|
||||
StackedValue::Constant(index) => Rc::get_mut(&mut self.chunk)
|
||||
.unwrap()
|
||||
.remove_constant(index)
|
||||
.map_err(|error| VmError::Chunk { error, position })?,
|
||||
.remove_constant(index, position)?,
|
||||
};
|
||||
|
||||
log::trace!("Returning {value}");
|
||||
|
||||
return Ok(Some(value));
|
||||
}
|
||||
Instruction::Pop => {
|
||||
self.pop(position)?;
|
||||
let value = self.pop(position)?;
|
||||
|
||||
log::trace!("Popping {value:?}");
|
||||
}
|
||||
|
||||
// Variables
|
||||
Instruction::DefineVariableRuntime => {
|
||||
let value = self.pop(position)?.resolve(&self.chunk, position)?.clone();
|
||||
Instruction::DefineVariable => {
|
||||
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)?;
|
||||
} else {
|
||||
return Err(VmError::UndefinedVariable {
|
||||
identifier,
|
||||
position,
|
||||
});
|
||||
}
|
||||
Instruction::DefineVariableConstant => {
|
||||
let (argument, _) = *self.read(position)?;
|
||||
|
||||
self.push_constant_value(argument, position)?;
|
||||
}
|
||||
Instruction::GetVariable => {
|
||||
let (argument, _) = *self.read(position)?;
|
||||
let value = self.pop(position)?.to_value(&self.chunk, position)?.clone();
|
||||
|
||||
let local = self
|
||||
.chunk
|
||||
.get_local(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();
|
||||
log::trace!(
|
||||
"Getting {} as value {value}",
|
||||
self.chunk.get_identifier(argument)?,
|
||||
);
|
||||
|
||||
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 => {
|
||||
let (argument, _) = *self.read(position)?;
|
||||
let identifier = self
|
||||
.chunk
|
||||
.get_identifier(argument)
|
||||
.map_err(|error| VmError::Chunk { error, position })?;
|
||||
let identifier = self.chunk.get_identifier(argument)?.clone();
|
||||
|
||||
if !self.chunk.contains_identifier(identifier) {
|
||||
return Err(VmError::UndefinedVariable(identifier.clone(), position));
|
||||
if !self.chunk.contains_identifier(&identifier) {
|
||||
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
|
||||
Instruction::Negate => {
|
||||
let negated = self
|
||||
.pop(position)?
|
||||
.resolve(&self.chunk, position)?
|
||||
.to_value(&self.chunk, position)?
|
||||
.negate()
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
|
||||
@ -130,7 +136,7 @@ impl Vm {
|
||||
Instruction::Not => {
|
||||
let not = self
|
||||
.pop(position)?
|
||||
.resolve(&self.chunk, position)?
|
||||
.to_value(&self.chunk, position)?
|
||||
.not()
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
|
||||
@ -141,9 +147,9 @@ impl Vm {
|
||||
Instruction::Add => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let sum = left
|
||||
.add(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -153,9 +159,9 @@ impl Vm {
|
||||
Instruction::Subtract => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let difference = left
|
||||
.subtract(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -165,9 +171,9 @@ impl Vm {
|
||||
Instruction::Multiply => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let product = left
|
||||
.multiply(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -177,9 +183,9 @@ impl Vm {
|
||||
Instruction::Divide => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let quotient = left
|
||||
.divide(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -189,9 +195,9 @@ impl Vm {
|
||||
Instruction::Greater => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let greater = left
|
||||
.greater_than(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -201,9 +207,9 @@ impl Vm {
|
||||
Instruction::Less => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let less = left
|
||||
.less_than(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -213,9 +219,9 @@ impl Vm {
|
||||
Instruction::GreaterEqual => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let greater_equal = left
|
||||
.greater_than_or_equal(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -225,9 +231,9 @@ impl Vm {
|
||||
Instruction::LessEqual => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let less_equal = left
|
||||
.less_than_or_equal(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -237,9 +243,9 @@ impl Vm {
|
||||
Instruction::Equal => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let equal = left
|
||||
.equal(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -249,9 +255,9 @@ impl Vm {
|
||||
Instruction::NotEqual => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let not_equal = left
|
||||
.not_equal(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -261,9 +267,9 @@ impl Vm {
|
||||
Instruction::And => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let and = left
|
||||
.and(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -273,9 +279,9 @@ impl Vm {
|
||||
Instruction::Or => {
|
||||
let chunk = self.chunk.clone();
|
||||
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 = left_stacked.resolve(&self.chunk, position)?;
|
||||
let left = left_stacked.to_value(&self.chunk, position)?;
|
||||
let or = left
|
||||
.or(right)
|
||||
.map_err(|error| VmError::Value { error, position })?;
|
||||
@ -323,10 +329,7 @@ impl Vm {
|
||||
}
|
||||
|
||||
fn read(&mut self, position: Span) -> Result<&(u8, Span), VmError> {
|
||||
let current = self
|
||||
.chunk
|
||||
.get_code(self.ip)
|
||||
.map_err(|error| VmError::Chunk { error, position })?;
|
||||
let current = self.chunk.get_code(self.ip, position)?;
|
||||
|
||||
self.ip += 1;
|
||||
|
||||
@ -341,12 +344,10 @@ pub enum 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 {
|
||||
Self::Runtime(value) => Ok(value),
|
||||
Self::Constant(index) => chunk
|
||||
.get_constant(*index)
|
||||
.map_err(|error| VmError::Chunk { error, position }),
|
||||
Self::Constant(index) => Ok(chunk.get_constant(*index, position)?),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -356,20 +357,22 @@ pub enum VmError {
|
||||
InvalidInstruction(u8, Span),
|
||||
StackOverflow(Span),
|
||||
StackUnderflow(Span),
|
||||
UndefinedVariable(Identifier, Span),
|
||||
UndefinedVariable {
|
||||
identifier: Identifier,
|
||||
position: Span,
|
||||
},
|
||||
|
||||
// Wrappers for foreign errors
|
||||
Chunk { error: ChunkError, position: Span },
|
||||
Value { error: ValueError, position: Span },
|
||||
Chunk(ChunkError),
|
||||
Value {
|
||||
error: ValueError,
|
||||
position: Span,
|
||||
},
|
||||
}
|
||||
|
||||
impl VmError {
|
||||
pub fn chunk(error: ChunkError, position: Span) -> Self {
|
||||
Self::Chunk { error, position }
|
||||
}
|
||||
|
||||
pub fn value(error: ValueError, position: Span) -> Self {
|
||||
Self::Value { error, position }
|
||||
impl From<ChunkError> for VmError {
|
||||
fn from(v: ChunkError) -> Self {
|
||||
Self::Chunk(v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,8 +386,8 @@ impl AnnotatedError for VmError {
|
||||
Self::InvalidInstruction(_, _) => "Invalid instruction",
|
||||
Self::StackOverflow(_) => "Stack overflow",
|
||||
Self::StackUnderflow(_) => "Stack underflow",
|
||||
Self::UndefinedVariable(_, _) => "Undefined variable",
|
||||
Self::Chunk { .. } => "Chunk error",
|
||||
Self::UndefinedVariable { .. } => "Undefined variable",
|
||||
Self::Chunk(_) => "Chunk error",
|
||||
Self::Value { .. } => "Value error",
|
||||
}
|
||||
}
|
||||
@ -396,11 +399,11 @@ impl AnnotatedError for VmError {
|
||||
)),
|
||||
Self::StackOverflow(position) => Some(format!("Stack overflow at {position}")),
|
||||
Self::StackUnderflow(position) => Some(format!("Stack underflow at {position}")),
|
||||
Self::UndefinedVariable(identifier, position) => {
|
||||
Some(format!("{identifier} is not in scope at {position}"))
|
||||
Self::UndefinedVariable { identifier, .. } => {
|
||||
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()),
|
||||
}
|
||||
}
|
||||
@ -410,8 +413,8 @@ impl AnnotatedError for VmError {
|
||||
Self::InvalidInstruction(_, position) => *position,
|
||||
Self::StackUnderflow(position) => *position,
|
||||
Self::StackOverflow(position) => *position,
|
||||
Self::UndefinedVariable(_, position) => *position,
|
||||
Self::Chunk { position, .. } => *position,
|
||||
Self::UndefinedVariable { position, .. } => *position,
|
||||
Self::Chunk(error) => error.position(),
|
||||
Self::Value { position, .. } => *position,
|
||||
}
|
||||
}
|
||||
|
@ -9,5 +9,7 @@ repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.14", features = ["derive"] }
|
||||
colored = "2.1.0"
|
||||
dust-lang = { path = "../dust-lang" }
|
||||
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 colored::Colorize;
|
||||
use dust_lang::{parse, run};
|
||||
use env_logger::WriteStyle;
|
||||
use log::Level;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Cli {
|
||||
@ -18,8 +19,21 @@ struct Cli {
|
||||
fn main() {
|
||||
env_logger::builder()
|
||||
.parse_env("DUST_LOG")
|
||||
.format_timestamp_secs()
|
||||
.write_style(WriteStyle::Always)
|
||||
.format(|buf, record| {
|
||||
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();
|
||||
|
||||
let args = Cli::parse();
|
||||
|
Loading…
Reference in New Issue
Block a user