Implement closing for lists
This commit is contained in:
parent
37dc2e05c5
commit
2f8c46f0a5
@ -15,10 +15,11 @@ impl Instruction {
|
|||||||
instruction
|
instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(to_register: u8) -> Instruction {
|
pub fn close(from_register: u8, to_register: u8) -> Instruction {
|
||||||
let mut instruction = Instruction(Operation::Close as u32);
|
let mut instruction = Instruction(Operation::Close as u32);
|
||||||
|
|
||||||
instruction.set_destination(to_register);
|
instruction.set_first_argument(from_register);
|
||||||
|
instruction.set_second_argument(to_register);
|
||||||
|
|
||||||
instruction
|
instruction
|
||||||
}
|
}
|
||||||
@ -243,7 +244,12 @@ impl Instruction {
|
|||||||
Operation::Move => {
|
Operation::Move => {
|
||||||
format!("R({}) = R({})", self.destination(), self.first_argument())
|
format!("R({}) = R({})", self.destination(), self.first_argument())
|
||||||
}
|
}
|
||||||
Operation::Close => format!("R({})", self.destination()),
|
Operation::Close => {
|
||||||
|
let from_register = self.first_argument();
|
||||||
|
let to_register = self.second_argument().saturating_sub(1);
|
||||||
|
|
||||||
|
format!("R({from_register})..=R({to_register})")
|
||||||
|
}
|
||||||
Operation::LoadConstant => {
|
Operation::LoadConstant => {
|
||||||
let constant_index = self.first_argument();
|
let constant_index = self.first_argument();
|
||||||
|
|
||||||
@ -274,7 +280,7 @@ impl Instruction {
|
|||||||
let last_index = destination - 1;
|
let last_index = destination - 1;
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"R({}) = [R({})..R({})]",
|
"R({}) = [R({})..=R({})]",
|
||||||
destination, first_index, last_index
|
destination, first_index, last_index
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -556,15 +562,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn close() {
|
fn close() {
|
||||||
let mut instruction = Instruction::close(1);
|
let instruction = Instruction::close(1, 2);
|
||||||
|
|
||||||
instruction.set_first_argument_to_constant();
|
|
||||||
instruction.set_second_argument_to_constant();
|
|
||||||
|
|
||||||
assert_eq!(instruction.operation(), Operation::Close);
|
assert_eq!(instruction.operation(), Operation::Close);
|
||||||
assert_eq!(instruction.destination(), 1);
|
assert_eq!(instruction.first_argument(), 1);
|
||||||
assert!(instruction.first_argument_is_constant());
|
assert_eq!(instruction.second_argument(), 2);
|
||||||
assert!(instruction.second_argument_is_constant());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -485,8 +485,17 @@ impl<'src> Parser<'src> {
|
|||||||
let mut length = 0;
|
let mut length = 0;
|
||||||
|
|
||||||
while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() {
|
while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() {
|
||||||
|
let next_register = self.current_register;
|
||||||
|
|
||||||
self.parse(Precedence::Assignment)?; // Do not allow assignment
|
self.parse(Precedence::Assignment)?; // Do not allow assignment
|
||||||
|
|
||||||
|
if next_register != self.current_register - 1 {
|
||||||
|
self.emit_instruction(
|
||||||
|
Instruction::close(next_register, self.current_register - 1),
|
||||||
|
self.current_position,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
length += 1;
|
length += 1;
|
||||||
|
|
||||||
if !self.allow(TokenKind::Comma)? {
|
if !self.allow(TokenKind::Comma)? {
|
||||||
|
@ -66,7 +66,14 @@ impl Vm {
|
|||||||
|
|
||||||
self.insert(value, to, position)?;
|
self.insert(value, to, position)?;
|
||||||
}
|
}
|
||||||
Operation::Close => todo!(),
|
Operation::Close => {
|
||||||
|
let from = instruction.first_argument();
|
||||||
|
let to = instruction.second_argument();
|
||||||
|
|
||||||
|
for register_index in from..to {
|
||||||
|
self.register_stack[register_index as usize] = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
Operation::LoadConstant => {
|
Operation::LoadConstant => {
|
||||||
let to_register = instruction.destination();
|
let to_register = instruction.destination();
|
||||||
let from_constant = instruction.first_argument();
|
let from_constant = instruction.first_argument();
|
||||||
@ -77,13 +84,17 @@ impl Vm {
|
|||||||
Operation::LoadList => {
|
Operation::LoadList => {
|
||||||
let to_register = instruction.destination();
|
let to_register = instruction.destination();
|
||||||
let length = instruction.first_argument();
|
let length = instruction.first_argument();
|
||||||
let first_register = to_register - length;
|
let first_register = to_register - length - 1;
|
||||||
let last_register = to_register - 1;
|
let last_register = to_register - 1;
|
||||||
|
|
||||||
let mut list = Vec::with_capacity(length as usize);
|
let mut list = Vec::with_capacity(length as usize);
|
||||||
|
|
||||||
for register_index in first_register..=last_register {
|
for register_index in first_register..=last_register {
|
||||||
let value = self.clone(register_index, position)?;
|
let value = match self.clone(register_index, position) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(VmError::EmptyRegister { .. }) => continue,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
|
||||||
list.push(value);
|
list.push(value);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user