Fix byte lexing bug; Implement Move operation
This commit is contained in:
parent
5c54a5b9bd
commit
82a2b8f6b7
@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
rc::Weak,
|
||||
};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
use colored::Colorize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -139,7 +139,7 @@ impl Instruction {
|
||||
pub fn disassembly_info(&self, chunk: Option<&Chunk>) -> Option<String> {
|
||||
let info = match self.operation {
|
||||
Operation::Move => {
|
||||
format!("R({}) R({})", self.destination, self.arguments[0])
|
||||
format!("R({}) = R({})", self.destination, self.arguments[0])
|
||||
}
|
||||
Operation::Close => format!("R({})", self.destination),
|
||||
Operation::LoadConstant => {
|
||||
|
@ -386,11 +386,47 @@ impl<'src> Lexer<'src> {
|
||||
fn lex_numeric(&mut self) -> Result<(Token<'src>, Span), LexError> {
|
||||
let start_pos = self.position;
|
||||
let mut is_float = false;
|
||||
let peek_char = self.peek_char();
|
||||
|
||||
if let Some('-') = self.peek_char() {
|
||||
if let Some('-') = peek_char {
|
||||
self.next_char();
|
||||
}
|
||||
|
||||
if let Some('0') = peek_char {
|
||||
self.next_char();
|
||||
|
||||
if let Some('x') = self.peek_char() {
|
||||
self.next_char();
|
||||
|
||||
let mut peek_chars = self.peek_chars(2).chars();
|
||||
|
||||
match (peek_chars.next(), peek_chars.next()) {
|
||||
(Some('0'..='9' | 'A'..='f'), Some('0'..='9' | 'A'..='f')) => {
|
||||
self.next_char();
|
||||
self.next_char();
|
||||
|
||||
let text = &self.source[start_pos..self.position];
|
||||
|
||||
return Ok((Token::Byte(text), Span(start_pos, self.position)));
|
||||
}
|
||||
(Some('0'..='9' | 'A'..='f'), erroneous) => {
|
||||
self.next_char();
|
||||
|
||||
return Err(LexError::ExpectedAsciiHexDigit {
|
||||
actual: erroneous,
|
||||
position: self.position,
|
||||
});
|
||||
}
|
||||
(erroneous, _) => {
|
||||
return Err(LexError::ExpectedAsciiHexDigit {
|
||||
actual: erroneous,
|
||||
position: self.position,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(c) = self.peek_char() {
|
||||
if c == '.' {
|
||||
if let Some('0'..='9') = self.peek_second_char() {
|
||||
@ -440,25 +476,6 @@ impl<'src> Lexer<'src> {
|
||||
}
|
||||
}
|
||||
|
||||
if c == 'x' {
|
||||
self.next_char();
|
||||
|
||||
while let Some(c) = self.peek_char() {
|
||||
if c.is_ascii_hexdigit() {
|
||||
self.next_char();
|
||||
} else {
|
||||
return Err(LexError::ExpectedAsciiHexDigit {
|
||||
actual: c,
|
||||
position: self.position,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let text = &self.source[start_pos..self.position];
|
||||
|
||||
return Ok((Token::Byte(text), Span(start_pos, self.position)));
|
||||
}
|
||||
|
||||
if c.is_ascii_digit() {
|
||||
self.next_char();
|
||||
} else {
|
||||
@ -535,7 +552,7 @@ impl<'src> Lexer<'src> {
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum LexError {
|
||||
ExpectedAsciiHexDigit {
|
||||
actual: char,
|
||||
actual: Option<char>,
|
||||
position: usize,
|
||||
},
|
||||
ExpectedCharacter {
|
||||
@ -577,6 +594,8 @@ impl AnnotatedError for LexError {
|
||||
Self::ExpectedAsciiHexDigit { actual, .. } => Some(format!(
|
||||
"Expected ASCII hex digit (0-9 or A-F), found \"{}\"",
|
||||
actual
|
||||
.map(|character| character.to_string())
|
||||
.unwrap_or("end of input".to_string())
|
||||
)),
|
||||
Self::ExpectedCharacter {
|
||||
expected, actual, ..
|
||||
|
@ -450,6 +450,33 @@ impl<'src> Parser<'src> {
|
||||
self.parse_expression()?;
|
||||
|
||||
let local_index = self.chunk.declare_local(identifier, position)?;
|
||||
let previous_instruction = self.chunk.pop_instruction();
|
||||
|
||||
if let Some((
|
||||
Instruction {
|
||||
operation: Operation::GetLocal,
|
||||
destination,
|
||||
arguments,
|
||||
},
|
||||
_,
|
||||
)) = previous_instruction
|
||||
{
|
||||
self.emit_instruction(
|
||||
Instruction {
|
||||
operation: Operation::Move,
|
||||
destination,
|
||||
arguments,
|
||||
},
|
||||
position,
|
||||
);
|
||||
} else if let Some((instruction, position)) = previous_instruction {
|
||||
self.chunk.push_instruction(instruction, position);
|
||||
} else {
|
||||
return Err(ParseError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
});
|
||||
}
|
||||
|
||||
self.emit_instruction(
|
||||
Instruction::declare_local(self.current_register - 1, local_index),
|
||||
|
@ -39,20 +39,27 @@ impl Vm {
|
||||
log::trace!("Running instruction {instruction} at {position}");
|
||||
|
||||
match instruction.operation {
|
||||
Operation::Move => todo!(),
|
||||
Operation::Move => {
|
||||
let from = instruction.arguments[0] as usize;
|
||||
let to = instruction.destination as usize;
|
||||
let value = self.clone(from, position)?;
|
||||
|
||||
self.insert(value, to, position)?;
|
||||
}
|
||||
Operation::Close => todo!(),
|
||||
Operation::LoadConstant => {
|
||||
let constant_index = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.chunk.use_constant(constant_index, position)?;
|
||||
let to_register = instruction.destination as usize;
|
||||
let from_constant = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.chunk.use_constant(from_constant, position)?;
|
||||
|
||||
self.insert(value, instruction.destination as usize, position)?;
|
||||
self.insert(value, to_register, position)?;
|
||||
}
|
||||
Operation::DeclareLocal => {
|
||||
let register_index = instruction.destination as usize;
|
||||
let local_index = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.take(register_index, position)?;
|
||||
let from_register = instruction.destination as usize;
|
||||
let to_local = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.clone(from_register, position)?;
|
||||
|
||||
self.chunk.define_local(local_index, value, position)?;
|
||||
self.chunk.define_local(to_local, value, position)?;
|
||||
}
|
||||
Operation::GetLocal => {
|
||||
let register_index = instruction.destination as usize;
|
||||
@ -148,6 +155,18 @@ impl Vm {
|
||||
}
|
||||
}
|
||||
|
||||
fn clone(&mut self, index: usize, position: Span) -> Result<Value, VmError> {
|
||||
if let Some(register) = self.register_stack.get_mut(index) {
|
||||
if let Some(value) = register.take() {
|
||||
Ok(register.insert(value.into_reference()).clone())
|
||||
} else {
|
||||
Err(VmError::EmptyRegister { index, position })
|
||||
}
|
||||
} else {
|
||||
Err(VmError::RegisterIndexOutOfBounds { position })
|
||||
}
|
||||
}
|
||||
|
||||
fn take(&mut self, index: usize, position: Span) -> Result<Value, VmError> {
|
||||
if let Some(register) = self.register_stack.get_mut(index) {
|
||||
if let Some(value) = register.take() {
|
||||
|
Loading…
Reference in New Issue
Block a user