[rlox] Add boolean literals
This commit is contained in:
@@ -7,6 +7,8 @@ pub enum Op {
|
|||||||
Return,
|
Return,
|
||||||
Constant { offset: usize },
|
Constant { offset: usize },
|
||||||
Nil,
|
Nil,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
Negate,
|
Negate,
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
@@ -17,6 +19,7 @@ pub enum Op {
|
|||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Nil,
|
Nil,
|
||||||
|
Bool(bool),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +137,9 @@ impl fmt::Debug for TraceInfo<'_> {
|
|||||||
}?;
|
}?;
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
Op::Return | Op::Nil | Op::Negate | Op::Add | Op::Subtract | Op::Multiply | Op::Divide => {
|
Op::Return | Op::Nil | Op::True
|
||||||
|
| Op::False | Op::Negate | Op::Add
|
||||||
|
| Op::Subtract | Op::Multiply | Op::Divide => {
|
||||||
write!(f, "{:?}", op)
|
write!(f, "{:?}", op)
|
||||||
}
|
}
|
||||||
Op::Constant { offset } => {
|
Op::Constant { offset } => {
|
||||||
|
|||||||
@@ -349,10 +349,16 @@ impl<'src> Parser<'src> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
Token {
|
Token {
|
||||||
ttype: TokenType::Nil,
|
ttype: ttype@(TokenType::Nil | TokenType::True | TokenType::False),
|
||||||
span: _,
|
span: _,
|
||||||
} => {
|
} => {
|
||||||
chunk.add_op(Op::Nil, 0);
|
let op = match ttype {
|
||||||
|
TokenType::Nil => Op::Nil,
|
||||||
|
TokenType::True => Op::True,
|
||||||
|
TokenType::False => Op::False,
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
chunk.add_op(op, 0);
|
||||||
}
|
}
|
||||||
Token {
|
Token {
|
||||||
ttype: TokenType::LeftParen,
|
ttype: TokenType::LeftParen,
|
||||||
@@ -504,4 +510,23 @@ mod tests {
|
|||||||
|
|
||||||
assert!(chunk.instr_eq(&expected));
|
assert!(chunk.instr_eq(&expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_bool_literals() {
|
||||||
|
let source = "true * false";
|
||||||
|
let scanner = Scanner::new(source);
|
||||||
|
let mut parser = Parser::new(scanner);
|
||||||
|
let mut chunk = Chunk::new();
|
||||||
|
parser.expression(&mut chunk);
|
||||||
|
|
||||||
|
use crate::bc::Op::*;
|
||||||
|
let expected = Chunk::new_with(
|
||||||
|
vec![True, False, Multiply],
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(chunk.instr_eq(&expected));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ impl VM {
|
|||||||
Op::Return => print!("{:?}", self.pop()?),
|
Op::Return => print!("{:?}", self.pop()?),
|
||||||
Op::Constant { offset } => self.push(chunk.constants[offset]),
|
Op::Constant { offset } => self.push(chunk.constants[offset]),
|
||||||
Op::Nil => self.push(Value::Nil),
|
Op::Nil => self.push(Value::Nil),
|
||||||
|
Op::True => self.push(Value::Bool(true)),
|
||||||
|
Op::False => self.push(Value::Bool(false)),
|
||||||
Op::Negate => {
|
Op::Negate => {
|
||||||
let new_val = -self.pop_num()?;
|
let new_val = -self.pop_num()?;
|
||||||
self.push(new_val.into());
|
self.push(new_val.into());
|
||||||
@@ -143,7 +145,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn runtime_type_error() {
|
fn nil_error() {
|
||||||
let chunk = Chunk::new_with(
|
let chunk = Chunk::new_with(
|
||||||
vec![Op::Nil, Op::Negate],
|
vec![Op::Nil, Op::Negate],
|
||||||
vec![],
|
vec![],
|
||||||
|
|||||||
Reference in New Issue
Block a user