|
@@ -108,40 +108,55 @@ impl Filter {
|
|
|
let mut has_changed = false;
|
|
|
let mut counter: usize = self.opcodes.len();
|
|
|
|
|
|
- let mut register_new_mapping = HashMap::new();
|
|
|
+ let mut register_new_mapping = HashMap::<_, Register>::new();
|
|
|
+
|
|
|
+ let mut new_mapping = |register_new_mapping: &mut HashMap<Register, Register>,
|
|
|
+ current: &Register|
|
|
|
+ -> Register {
|
|
|
+ counter += 1;
|
|
|
+ if counter != **current {
|
|
|
+ has_changed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ register_new_mapping.insert(current.clone(), counter.into());
|
|
|
+ counter.into()
|
|
|
+ };
|
|
|
|
|
|
self.opcodes.iter_mut().for_each(|opcode| match opcode {
|
|
|
OpCode::LOAD(current, _) | OpCode::LOAD_EXTERNAL(current, _) => {
|
|
|
- counter += 1;
|
|
|
- if counter != **current {
|
|
|
- has_changed = true;
|
|
|
- }
|
|
|
-
|
|
|
- register_new_mapping.insert(**current, counter.into());
|
|
|
- *current = register_new_mapping[current];
|
|
|
+ *current = new_mapping(&mut register_new_mapping, current);
|
|
|
}
|
|
|
- OpCode::SHL(_, reg1, _)
|
|
|
- | OpCode::SHR(_, reg1, _)
|
|
|
- | OpCode::NOT(_, reg1)
|
|
|
- | OpCode::CPY(_, reg1)
|
|
|
- | OpCode::MOV(_, reg1)
|
|
|
- | OpCode::JEQ(reg1, _)
|
|
|
- | OpCode::JNE(reg1, _) => {
|
|
|
+ OpCode::SHL(set, reg1, _)
|
|
|
+ | OpCode::SHR(set, reg1, _)
|
|
|
+ | OpCode::NOT(set, reg1)
|
|
|
+ | OpCode::CPY(set, reg1)
|
|
|
+ | OpCode::NEG(set, reg1)
|
|
|
+ | OpCode::MOV(set, reg1) => {
|
|
|
*reg1 = register_new_mapping[reg1];
|
|
|
+ *set = new_mapping(&mut register_new_mapping, set);
|
|
|
}
|
|
|
- OpCode::ADD(_, reg1, reg2)
|
|
|
- | OpCode::MUL(_, reg1, reg2)
|
|
|
- | OpCode::DIV(_, reg1, reg2)
|
|
|
- | OpCode::MOD(_, reg1, reg2)
|
|
|
- | OpCode::XOR(_, reg1, reg2)
|
|
|
- | OpCode::SUB(_, reg1, reg2)
|
|
|
- | OpCode::AND(_, reg1, reg2)
|
|
|
- | OpCode::EQ(_, reg1, reg2)
|
|
|
- | OpCode::OR(_, reg1, reg2) => {
|
|
|
+ OpCode::HLT(reg1) | OpCode::JEQ(reg1, _) | OpCode::JNE(reg1, _) => {
|
|
|
+ *reg1 = register_new_mapping[reg1];
|
|
|
+ }
|
|
|
+ OpCode::ADD(set, reg1, reg2)
|
|
|
+ | OpCode::MUL(set, reg1, reg2)
|
|
|
+ | OpCode::NE(set, reg1, reg2)
|
|
|
+ | OpCode::GE(set, reg1, reg2)
|
|
|
+ | OpCode::LE(set, reg1, reg2)
|
|
|
+ | OpCode::GT(set, reg1, reg2)
|
|
|
+ | OpCode::LT(set, reg1, reg2)
|
|
|
+ | OpCode::DIV(set, reg1, reg2)
|
|
|
+ | OpCode::MOD(set, reg1, reg2)
|
|
|
+ | OpCode::XOR(set, reg1, reg2)
|
|
|
+ | OpCode::SUB(set, reg1, reg2)
|
|
|
+ | OpCode::AND(set, reg1, reg2)
|
|
|
+ | OpCode::EQ(set, reg1, reg2)
|
|
|
+ | OpCode::OR(set, reg1, reg2) => {
|
|
|
*reg1 = register_new_mapping[reg1];
|
|
|
*reg2 = register_new_mapping[reg2];
|
|
|
+ *set = new_mapping(&mut register_new_mapping, set);
|
|
|
}
|
|
|
- _ => {}
|
|
|
+ OpCode::LABEL(_) | OpCode::JMP(_) => {}
|
|
|
});
|
|
|
|
|
|
has_changed
|
|
@@ -155,17 +170,27 @@ impl Filter {
|
|
|
.iter()
|
|
|
.enumerate()
|
|
|
.map(|(pos, opcode)| match opcode {
|
|
|
+ OpCode::LOAD(_, _)
|
|
|
+ | OpCode::LOAD_EXTERNAL(_, _)
|
|
|
+ | OpCode::LABEL(_)
|
|
|
+ | OpCode::JMP(_) => vec![],
|
|
|
OpCode::NOT(_, reg1)
|
|
|
| OpCode::CPY(_, reg1)
|
|
|
| OpCode::MOV(_, reg1)
|
|
|
| OpCode::JEQ(reg1, _)
|
|
|
| OpCode::SHL(_, reg1, _)
|
|
|
| OpCode::SHR(_, reg1, _)
|
|
|
+ | OpCode::NEG(_, reg1)
|
|
|
+ | OpCode::HLT(reg1)
|
|
|
+ | OpCode::JNE(reg1, _)
|
|
|
| OpCode::JEQ(reg1, _) => {
|
|
|
vec![(*reg1, pos)]
|
|
|
}
|
|
|
OpCode::ADD(_, reg1, reg2)
|
|
|
+ | OpCode::GE(_, reg1, reg2)
|
|
|
+ | OpCode::LE(_, reg1, reg2)
|
|
|
| OpCode::MUL(_, reg1, reg2)
|
|
|
+ | OpCode::NE(_, reg1, reg2)
|
|
|
| OpCode::DIV(_, reg1, reg2)
|
|
|
| OpCode::MOD(_, reg1, reg2)
|
|
|
| OpCode::XOR(_, reg1, reg2)
|
|
@@ -177,7 +202,6 @@ impl Filter {
|
|
|
| OpCode::LT(_, reg1, reg2) => {
|
|
|
vec![(*reg1, pos), (*reg2, pos)]
|
|
|
}
|
|
|
- _ => vec![],
|
|
|
})
|
|
|
.flatten()
|
|
|
.fold(HashMap::new(), |mut acc, (reg, pos)| {
|
|
@@ -194,7 +218,7 @@ impl Filter {
|
|
|
.into_iter()
|
|
|
.enumerate()
|
|
|
.filter_map(|(pos, opcode)| match &opcode {
|
|
|
- OpCode::LOAD(dst, _) => {
|
|
|
+ OpCode::LOAD(dst, _) | OpCode::LOAD_EXTERNAL(dst, _) => {
|
|
|
if used_registers.get(dst).is_some() {
|
|
|
return Some(opcode);
|
|
|
} else {
|
|
@@ -276,7 +300,7 @@ mod test {
|
|
|
let mut x = Filter::new(
|
|
|
r#"
|
|
|
WHERE
|
|
|
- $foo = 3 + 2 * 4 / 2 * 298210
|
|
|
+ $foo = 3 + 2 * 4 / 2 * 298210 + $bar
|
|
|
"#,
|
|
|
)
|
|
|
.unwrap();
|
|
@@ -291,13 +315,19 @@ mod test {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- let external_variables_1 = vec![("foo".into(), ValueOrRef::Value(0.into()))]
|
|
|
- .into_iter()
|
|
|
- .collect();
|
|
|
+ let external_variables_1 = vec![
|
|
|
+ ("foo".into(), ValueOrRef::Value(0.into())),
|
|
|
+ ("bar".into(), ValueOrRef::Value(0.into())),
|
|
|
+ ]
|
|
|
+ .into_iter()
|
|
|
+ .collect();
|
|
|
|
|
|
- let external_variables_2 = vec![("foo".into(), ValueOrRef::Value(1192843.into()))]
|
|
|
- .into_iter()
|
|
|
- .collect();
|
|
|
+ let external_variables_2 = vec![
|
|
|
+ ("foo".into(), ValueOrRef::Value(1192844.into())),
|
|
|
+ ("bar".into(), ValueOrRef::Value(1.into())),
|
|
|
+ ]
|
|
|
+ .into_iter()
|
|
|
+ .collect();
|
|
|
|
|
|
let value = x.execute(&external_variables_1).expect("valid execution");
|
|
|
assert!(matches!(value, Value::Bool(false)));
|