improved REPL a bit

now uses rustyline for input
This commit is contained in:
Moritz Gmeiner 2024-09-02 03:10:35 +02:00
commit fb88595b6c
13 changed files with 560 additions and 100 deletions

View file

@ -9,10 +9,10 @@ path = "../frontend"
[dependencies]
itertools = "0.10.5"
lazy_static = "1.4.0"
num-derive = "0.3.3"
num-traits = "0.2.15"
regex = "1.7.1"
thiserror = "1.0.38"
static_assertions = "1.1.0"
itertools = "0.13"
lazy_static = "1"
num-derive = "0.4"
num-traits = "0.2"
regex = "1"
thiserror = "1"
static_assertions = "1"

View file

@ -236,7 +236,10 @@ impl Compiler {
self.emit_opcode(Opcode::Negate);
}
TokenType::Bang => todo!(),
_ => unreachable!("Called unary, but next token had token_type {:?}", token.token_type),
_ => unreachable!(
"Called unary, but next token had token_type {:?}",
token.token_type
),
}
Ok(())
@ -247,8 +250,10 @@ impl Compiler {
self.expression()?;
self.consume_token(TokenType::RightParen, |token| CompilerError::MissingRightParen {
code_pos: token.code_pos,
self.consume_token(TokenType::RightParen, |token| {
CompilerError::MissingRightParen {
code_pos: token.code_pos,
}
})?;
Ok(())
@ -308,7 +313,10 @@ impl Compiler {
Ok(())
}
// call err_fn with dummy token so we don't have to eat the EOF token
TokenType::EOF => Err(err_fn(Token::new(TokenType::EOF, self.peek_token().code_pos))),
TokenType::EOF => Err(err_fn(Token::new(
TokenType::EOF,
self.peek_token().code_pos,
))),
_ => Err(err_fn(self.next_token())),
}
}
@ -346,9 +354,15 @@ impl Compiler {
if const_idx <= u8::MAX as usize {
self.emit_opcode_byte(Opcode::LoadConst, const_idx.try_into().unwrap());
} else if const_idx <= u16::MAX as usize {
self.emit_opcode_bytes(Opcode::LoadConstLong, &u16_to_bytes(const_idx.try_into().unwrap()))
self.emit_opcode_bytes(
Opcode::LoadConstLong,
&u16_to_bytes(const_idx.try_into().unwrap()),
)
} else {
panic!("Tried to add more than {} constants to current chunk", u16::MAX);
panic!(
"Tried to add more than {} constants to current chunk",
u16::MAX
);
}
}

View file

@ -16,7 +16,9 @@ pub struct ChunkDebugInfo {
impl ChunkDebugInfo {
pub fn new() -> Self {
ChunkDebugInfo { line_infos: Vec::new() }
ChunkDebugInfo {
line_infos: Vec::new(),
}
}
pub fn write_line(&mut self, line: u32, offset: usize) {

View file

@ -17,7 +17,11 @@ pub enum RuntimeError {
#[error("Opcopde {opcode} had invalid operand {operand}")]
UnaryInvalidOperand { opcode: Opcode, operand: Value },
#[error("Opcopde {opcode} had invalid operands {left} and {right}")]
BinaryInvalidOperand { opcode: Opcode, left: Value, right: Value },
BinaryInvalidOperand {
opcode: Opcode,
left: Value,
right: Value,
},
#[error("Division by zero")]
DivisionByZero,
}
@ -52,7 +56,7 @@ impl From<RuntimeError> for LoxError {
}
}
fn format_multiple_errors(errs: &Vec<impl std::error::Error>) -> String {
fn format_multiple_errors(errs: &[impl std::error::Error]) -> String {
let msg = if errs.len() == 1 {
errs[0].to_string()
} else {

View file

@ -51,9 +51,12 @@ pub fn run_repl(vm: &mut VM) {
std::process::exit(66);
});
let num_open_braces = (input_buf.matches('{').count() as i64) - (input_buf.matches('}').count() as i64);
let num_open_parens = (input_buf.matches('(').count() as i64) - (input_buf.matches(')').count() as i64);
let num_open_brackets = (input_buf.matches('[').count() as i64) - (input_buf.matches(']').count() as i64);
let num_open_braces =
(input_buf.matches('{').count() as i64) - (input_buf.matches('}').count() as i64);
let num_open_parens =
(input_buf.matches('(').count() as i64) - (input_buf.matches(')').count() as i64);
let num_open_brackets =
(input_buf.matches('[').count() as i64) - (input_buf.matches(']').count() as i64);
// all braces/parens/brackets closed => break
if num_open_braces == 0 && num_open_parens == 0 && num_open_brackets == 0 {

View file

@ -1,17 +1,12 @@
use std::fmt::Display;
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq)]
pub enum Value {
#[default]
Nil,
Number(f64),
}
impl Default for Value {
fn default() -> Self {
Value::Nil
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {

View file

@ -134,7 +134,13 @@ impl VM {
self.push_value(Value::Number(left + right));
}
// (Value::String(left), Value::String(right)) => todo!(),
(left, right) => return Err(RuntimeError::BinaryInvalidOperand { opcode, left, right }),
(left, right) => {
return Err(RuntimeError::BinaryInvalidOperand {
opcode,
left,
right,
})
}
}
}
Opcode::Subtract => {
@ -144,7 +150,13 @@ impl VM {
(Value::Number(left), Value::Number(right)) => {
self.push_value(Value::Number(left - right));
}
(left, right) => return Err(RuntimeError::BinaryInvalidOperand { opcode, left, right }),
(left, right) => {
return Err(RuntimeError::BinaryInvalidOperand {
opcode,
left,
right,
})
}
}
}
Opcode::Multiply => {
@ -154,7 +166,13 @@ impl VM {
(Value::Number(left), Value::Number(right)) => {
self.push_value(Value::Number(left * right));
}
(left, right) => return Err(RuntimeError::BinaryInvalidOperand { opcode, left, right }),
(left, right) => {
return Err(RuntimeError::BinaryInvalidOperand {
opcode,
left,
right,
})
}
}
}
Opcode::Divide => {
@ -167,7 +185,13 @@ impl VM {
}
self.push_value(Value::Number(left / right));
}
(left, right) => return Err(RuntimeError::BinaryInvalidOperand { opcode, left, right }),
(left, right) => {
return Err(RuntimeError::BinaryInvalidOperand {
opcode,
left,
right,
})
}
}
}
Opcode::Negate => {
@ -176,7 +200,10 @@ impl VM {
if let Value::Number(num) = value {
self.push_value(Value::Number(-num));
} else {
return Err(RuntimeError::UnaryInvalidOperand { opcode, operand: value });
return Err(RuntimeError::UnaryInvalidOperand {
opcode,
operand: value,
});
}
}
Opcode::Return => {