Add jmpif_not instruction

This commit is contained in:
Andrew Morris
2023-07-03 09:33:47 +10:00
parent adce30305f
commit d217f60967
9 changed files with 66 additions and 38 deletions

View File

@@ -235,7 +235,7 @@ impl Assembler {
Jmp(label_ref) => {
self.label_ref(label_ref);
}
JmpIf(value, label_ref) => {
JmpIf(value, label_ref) | JmpIfNot(value, label_ref) => {
self.value(value);
self.label_ref(label_ref);
}

View File

@@ -238,6 +238,7 @@ impl<'a> AssemblyParser<'a> {
("subcall", InstructionByte::SubCall),
("jmp", InstructionByte::Jmp),
("jmpif", InstructionByte::JmpIf),
("jmpif_not", InstructionByte::JmpIfNot),
("unary+", InstructionByte::UnaryPlus),
("unary-", InstructionByte::UnaryMinus),
("new", InstructionByte::New),
@@ -731,6 +732,7 @@ impl<'a> AssemblyParser<'a> {
),
Jmp => Instruction::Jmp(self.assemble_label_read()),
JmpIf => Instruction::JmpIf(self.assemble_value(), self.assemble_label_read()),
JmpIfNot => Instruction::JmpIfNot(self.assemble_value(), self.assemble_label_read()),
UnaryPlus => Instruction::UnaryPlus(self.assemble_value(), self.assemble_register()),
UnaryMinus => Instruction::UnaryMinus(self.assemble_value(), self.assemble_register()),
New => Instruction::New(

View File

@@ -45,6 +45,7 @@ pub enum Instruction {
SubCall(Register, Value, Value, Register),
Jmp(LabelRef),
JmpIf(Value, LabelRef),
JmpIfNot(Value, LabelRef),
UnaryPlus(Value, Register),
UnaryMinus(Value, Register),
New(Value, Value, Register),
@@ -190,7 +191,7 @@ impl Instruction {
visit(InstructionFieldMut::LabelRef(label_ref));
}
JmpIf(cond, label_ref) => {
JmpIf(cond, label_ref) | JmpIfNot(cond, label_ref) => {
visit(InstructionFieldMut::Value(cond));
visit(InstructionFieldMut::LabelRef(label_ref));
}
@@ -313,7 +314,7 @@ impl Instruction {
Jmp(_label_ref) => {}
JmpIf(cond, _label_ref) => {
JmpIf(cond, _label_ref) | JmpIfNot(cond, _label_ref) => {
cond.visit_registers_mut_rev(visit);
}
@@ -393,6 +394,7 @@ impl Instruction {
SubCall(..) => InstructionByte::SubCall,
Jmp(..) => InstructionByte::Jmp,
JmpIf(..) => InstructionByte::JmpIf,
JmpIfNot(..) => InstructionByte::JmpIfNot,
UnaryPlus(..) => InstructionByte::UnaryPlus,
UnaryMinus(..) => InstructionByte::UnaryMinus,
New(..) => InstructionByte::New,
@@ -531,6 +533,9 @@ impl std::fmt::Display for Instruction {
Instruction::JmpIf(value, label_ref) => {
write!(f, "jmpif {} {}", value, label_ref)
}
Instruction::JmpIfNot(value, label_ref) => {
write!(f, "jmpif_not {} {}", value, label_ref)
}
Instruction::UnaryPlus(value, register) => {
write!(f, "unary+ {} {}", value, register)
}

View File

@@ -442,7 +442,7 @@ impl FnState {
self.set(dst.name.clone(), Kal::Unknown);
}
JmpIf(a1, _) => {
JmpIf(a1, _) | JmpIfNot(a1, _) => {
self.eval_arg(a1);
}
@@ -511,6 +511,7 @@ impl FnState {
| SubCall(_, _, _, _)
| Jmp(_)
| JmpIf(_, _)
| JmpIfNot(_, _)
| New(_, _, _)
| Throw(_)
| Import(_, _)

View File

@@ -80,6 +80,12 @@ fn reduce(instr: Instruction) -> Option<Instruction> {
Value::Bool(true) => Some(Instruction::Jmp(label_ref.clone())),
_ => Some(instr),
},
JmpIfNot(cond, label_ref) => match cond {
// TODO: Kal::from_value(cond).is_truthy()
Value::Bool(false) => Some(Instruction::Jmp(label_ref.clone())),
Value::Bool(true) => None,
_ => Some(instr),
},
UnpackIterRes(_, value_dst, done_dst) => {
if value_dst.is_ignore() && done_dst.is_ignore() {
None

View File

@@ -150,7 +150,10 @@ fn is_jmp_or_label(line: &FnLine) -> bool {
fn is_jmp_instr(instr: &Instruction) -> bool {
match instr {
Instruction::End | Instruction::Jmp(..) | Instruction::JmpIf(..) => true,
Instruction::End
| Instruction::Jmp(..)
| Instruction::JmpIf(..)
| Instruction::JmpIfNot(..) => true,
Instruction::Mov(..)
| Instruction::OpInc(..)
| Instruction::OpDec(..)

View File

@@ -163,7 +163,7 @@ where
self.value(Some(owner), key);
self.value(Some(owner), args);
}
JmpIf(arg, _) => {
JmpIf(arg, _) | JmpIfNot(arg, _) => {
self.value(Some(owner), arg);
}
};