|
@@ -43,6 +43,7 @@ pub fn execute<'a>(
|
|
|
|
|
|
loop {
|
|
loop {
|
|
match code.get(*execution).ok_or(Error::OutOfBoundaries)? {
|
|
match code.get(*execution).ok_or(Error::OutOfBoundaries)? {
|
|
|
|
+ OpCode::LABEL(_addr) => {}
|
|
OpCode::LOAD_EXTERNAL(dst, name) => {
|
|
OpCode::LOAD_EXTERNAL(dst, name) => {
|
|
let value = external_variables
|
|
let value = external_variables
|
|
.get(name)
|
|
.get(name)
|
|
@@ -66,6 +67,17 @@ pub fn execute<'a>(
|
|
.into();
|
|
.into();
|
|
set!(registers, dst, new_value);
|
|
set!(registers, dst, new_value);
|
|
}
|
|
}
|
|
|
|
+ OpCode::SUB(dst, reg1, reg2) => {
|
|
|
|
+ let num1 = get!(registers, reg1).as_number()?;
|
|
|
|
+ let num2 = get!(registers, reg2).as_number()?;
|
|
|
|
+ set!(
|
|
|
|
+ registers,
|
|
|
|
+ dst,
|
|
|
|
+ num1.checked_sub(num2)
|
|
|
|
+ .map(|number| Value::Number(number).into())
|
|
|
|
+ .ok_or(Error::Overflow)?
|
|
|
|
+ );
|
|
|
|
+ }
|
|
OpCode::AND(dst, reg2, reg3) => {
|
|
OpCode::AND(dst, reg2, reg3) => {
|
|
let new_value = Value::Bool(
|
|
let new_value = Value::Bool(
|
|
get!(registers, reg2).as_boolean()? && get!(registers, reg3).as_boolean()?,
|
|
get!(registers, reg2).as_boolean()? && get!(registers, reg3).as_boolean()?,
|
|
@@ -73,10 +85,51 @@ pub fn execute<'a>(
|
|
.into();
|
|
.into();
|
|
set!(registers, dst, new_value);
|
|
set!(registers, dst, new_value);
|
|
}
|
|
}
|
|
|
|
+ OpCode::MOD(dst, reg1, reg2) => {
|
|
|
|
+ let num1 = get!(registers, reg1).as_number()?;
|
|
|
|
+ let num2 = get!(registers, reg2).as_number()?;
|
|
|
|
+ set!(
|
|
|
|
+ registers,
|
|
|
|
+ dst,
|
|
|
|
+ num1.checked_rem(num2)
|
|
|
|
+ .map(|number| Value::Number(number).into())
|
|
|
|
+ .ok_or(Error::Overflow)?
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ OpCode::NEG(dst, reg1) => {
|
|
|
|
+ let num1 = get!(registers, reg1).as_number()?;
|
|
|
|
+ set!(
|
|
|
|
+ registers,
|
|
|
|
+ dst,
|
|
|
|
+ num1.checked_neg()
|
|
|
|
+ .map(|number| Value::Number(number).into())
|
|
|
|
+ .ok_or(Error::Overflow)?
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ OpCode::GE(dst, reg1, reg2) => {
|
|
|
|
+ let new_value = Value::Bool(get!(registers, reg1) >= get!(registers, reg2)).into();
|
|
|
|
+ set!(registers, dst, new_value);
|
|
|
|
+ }
|
|
|
|
+ OpCode::GT(dst, reg1, reg2) => {
|
|
|
|
+ let new_value = Value::Bool(get!(registers, reg1) > get!(registers, reg2)).into();
|
|
|
|
+ set!(registers, dst, new_value);
|
|
|
|
+ }
|
|
|
|
+ OpCode::LE(dst, reg1, reg2) => {
|
|
|
|
+ let new_value = Value::Bool(get!(registers, reg1) <= get!(registers, reg2)).into();
|
|
|
|
+ set!(registers, dst, new_value);
|
|
|
|
+ }
|
|
|
|
+ OpCode::LT(dst, reg1, reg2) => {
|
|
|
|
+ let new_value = Value::Bool(get!(registers, reg1) < get!(registers, reg2)).into();
|
|
|
|
+ set!(registers, dst, new_value);
|
|
|
|
+ }
|
|
OpCode::EQ(dst, reg1, reg2) => {
|
|
OpCode::EQ(dst, reg1, reg2) => {
|
|
let new_value = Value::Bool(get!(registers, reg1) == get!(registers, reg2)).into();
|
|
let new_value = Value::Bool(get!(registers, reg1) == get!(registers, reg2)).into();
|
|
set!(registers, dst, new_value);
|
|
set!(registers, dst, new_value);
|
|
}
|
|
}
|
|
|
|
+ OpCode::NE(dst, reg1, reg2) => {
|
|
|
|
+ let new_value = Value::Bool(get!(registers, reg1) != get!(registers, reg2)).into();
|
|
|
|
+ set!(registers, dst, new_value);
|
|
|
|
+ }
|
|
OpCode::DIV(dst, reg1, reg2) => {
|
|
OpCode::DIV(dst, reg1, reg2) => {
|
|
let num1 = get!(registers, reg1).as_number()?;
|
|
let num1 = get!(registers, reg1).as_number()?;
|
|
let num2 = get!(registers, reg2).as_number()?;
|
|
let num2 = get!(registers, reg2).as_number()?;
|
|
@@ -131,7 +184,6 @@ pub fn execute<'a>(
|
|
.map(|x| x.into())
|
|
.map(|x| x.into())
|
|
.ok_or_else(|| Error::EmptyRegister(return_register.to_owned()));
|
|
.ok_or_else(|| Error::EmptyRegister(return_register.to_owned()));
|
|
}
|
|
}
|
|
- x => println!("{:?} is not implemented", x),
|
|
|
|
}
|
|
}
|
|
|
|
|
|
execution.next();
|
|
execution.next();
|