Cat instruction with limited implementation

This commit is contained in:
Andrew Morris
2023-05-30 11:22:50 +10:00
parent 98a7e8ea1f
commit 4164f44ece
7 changed files with 45 additions and 2 deletions

View File

@@ -54,6 +54,7 @@ pub enum InstructionByte {
ThisSubCall = 0x33,
Next = 0x34,
UnpackIterRes = 0x35,
Cat = 0x36,
}
impl InstructionByte {
@@ -115,6 +116,7 @@ impl InstructionByte {
0x33 => ThisSubCall,
0x34 => Next,
0x35 => UnpackIterRes,
0x36 => Cat,
_ => panic!("Unrecognized instruction: {}", byte),
};

View File

@@ -292,6 +292,7 @@ pub enum Instruction {
ThisSubCall(Value, Value, Value, Register),
Next(Register, Register),
UnpackIterRes(Register, Register, Register),
Cat(Value, Register),
}
impl std::fmt::Display for Instruction {
@@ -457,6 +458,9 @@ impl std::fmt::Display for Instruction {
obj, value_register, done_register
)
}
Instruction::Cat(iterables, register) => {
write!(f, "cat {} {}", iterables, register)
}
}
}
}
@@ -521,6 +525,7 @@ impl Instruction {
ThisSubCall(..) => InstructionByte::ThisSubCall,
Next(..) => InstructionByte::Next,
UnpackIterRes(..) => InstructionByte::UnpackIterRes,
Cat(..) => InstructionByte::Cat,
}
}
}

View File

@@ -240,6 +240,10 @@ impl Assembler {
self.register(value_dst);
self.register(done_dst);
}
Cat(iterables, dst) => {
self.value(iterables);
self.register(dst);
}
}
}

View File

@@ -229,6 +229,7 @@ impl<'a> AssemblyParser<'a> {
("this_subcall", InstructionByte::ThisSubCall),
("next", InstructionByte::Next),
("unpack_iter_res", InstructionByte::UnpackIterRes),
("cat", InstructionByte::Cat),
]);
for (word, instruction) in instruction_word_map {
@@ -693,6 +694,7 @@ impl<'a> AssemblyParser<'a> {
self.assemble_register(),
self.assemble_register(),
),
Cat => Instruction::Cat(self.assemble_value(), self.assemble_register()),
}
}

View File

@@ -48,7 +48,8 @@ pub fn instruction_mutates_this(instruction: &Instruction) -> bool {
| ImportStar(_, reg)
| SetCatch(_, reg)
| ConstSubCall(_, _, _, reg)
| ThisSubCall(_, _, _, reg) => reg == &Register::This,
| ThisSubCall(_, _, _, reg)
| Cat(_, reg) => reg == &Register::This,
Next(iter, res) => iter == &Register::This || res == &Register::This,
UnpackIterRes(_, value_reg, done_reg) => {

View File

@@ -244,7 +244,8 @@ where
| UnaryMinus(arg, _)
| Import(arg, _)
| ImportStar(arg, _)
| Throw(arg) => {
| Throw(arg)
| Cat(arg, _) => {
self.value(Some(owner), arg);
}
OpPlus(arg1, arg2, _)

View File

@@ -519,6 +519,34 @@ impl StackFrameTrait for BytecodeStackFrame {
operations::op_sub(self.registers[iter_res_i].clone(), "done".to_val())?;
}
}
Cat => {
let mut vals = Vec::<Val>::new();
let bytecode_type = self.decoder.decode_type();
if bytecode_type != BytecodeType::Array {
panic!("Not implemented: cat instruction not using inline array");
}
while self.decoder.peek_type() != BytecodeType::End {
let iterable = self.decoder.decode_val(&self.registers);
match iterable {
Val::Array(array_data) => {
for item in &array_data.elements {
vals.push(item.clone());
}
}
_ => todo!("Cat: Non-array iterable"),
}
}
// TODO: Just skip the byte in release builds?
assert!(self.decoder.decode_type() == BytecodeType::End);
self.registers[self.decoder.decode_register_index().unwrap()] = vals.to_val();
}
};
Ok(FrameStepOk::Continue)