diff --git a/rust/src/chunk.rs b/rust/src/chunk.rs
index d6ac680..934c51e 100644
--- a/rust/src/chunk.rs
+++ b/rust/src/chunk.rs
@@ -1,3 +1,5 @@
+use std::mem;
+
use vec::Vec;
use crate::vec;
@@ -5,6 +7,7 @@ use crate::vec;
#[repr(u8)]
pub enum OpCode {
Constant,
+ LongConstant,
Return,
}
@@ -23,12 +26,19 @@ impl Chunk {
self.lines.add(line);
}
- pub fn add_constant(&mut self, value: Value) -> u8 {
+ pub fn write_constant(&mut self, value: Value, line: usize) {
self.constants.push(value);
+ let index = self.constants.len() - 1;
- assert!(self.constants.len() <= u8::MAX.into(), "Too many constants");
-
- (self.constants.len() - 1) as u8
+ if let Ok(index) = index.try_into() {
+ self.write(OpCode::Constant as u8, line);
+ self.write(index, line);
+ } else {
+ self.write(OpCode::LongConstant as u8, line);
+ for byte in index.to_ne_bytes() {
+ self.write(byte, line);
+ }
+ }
}
pub fn disassemble(&self, name: &str) {
@@ -52,7 +62,8 @@ impl Chunk {
match self.code[offset] {
0 => self.constant_instruction("OP_CONSTANT", offset),
- 1 => self.simple_instruction("OP_RETURN", offset),
+ 1 => self.constant_long_instruction("OP_CONSTANT_LONG", offset),
+ 2 => self.simple_instruction("OP_RETURN", offset),
_ => unreachable!(),
}
}
@@ -68,6 +79,31 @@ impl Chunk {
println!("{:<16} {:>4} '{}'", name, constant_index, value);
offset + 2
}
+
+ fn constant_long_instruction(&self, name: &str, offset: usize) -> usize {
+ let index_len = mem::size_of::<usize>();
+ let index_bytes = &self.code[offset+1..offset+1+index_len];
+
+ let (int_bytes, _) = index_bytes.split_at(std::mem::size_of::<usize>());
+ let constant_index = usize::from_ne_bytes(int_bytes.try_into().unwrap());
+
+ let value = self.constants[constant_index as usize];
+ println!("{:<16} {:>4} '{}'", name, constant_index, value);
+ offset + 1 + index_len
+ }
+}
+
+#[test]
+fn test_constant_long() {
+ let mut chunk = Chunk::default();
+
+ for i in 0..=u8::MAX {
+ chunk.write_constant(i.into(), 123);
+ }
+
+ chunk.write_constant(0.0, 123);
+
+ // TODO Make the disassembler testable
}
// Lines are stored using run-length encoding, where the first element is the line and the second
diff --git a/rust/src/main.rs b/rust/src/main.rs
index ec0e1ce..6ed152f 100644
--- a/rust/src/main.rs
+++ b/rust/src/main.rs
@@ -6,11 +6,15 @@ pub mod vec;
fn main() {
let mut chunk = Chunk::default();
- let constant = chunk.add_constant(1.2);
- chunk.write(OpCode::Constant as u8, 123);
- chunk.write(constant, 123);
+ chunk.write_constant(1.2, 123);
chunk.write(OpCode::Return as u8, 123);
+ // for i in 0..=u8::MAX {
+ // chunk.write_constant(i.into(), 123);
+ // }
+
+ // chunk.write_constant(0.0, 123);
+
chunk.disassemble("test chunk");
}