///|
fn Machine::integer_word(
self : Machine,
word : String,
) -> Unit raise ForthError {
let count = match word {
"within" | "*/" | "*/mod" => 3
"abs" | "2*" | "2/" | "invert" | "0<>" => 1
_ => 2
}
if self.stack.length() < count {
raise Invalid("stack underflow")
}
let c = self.pop()
if count == 1 {
self.stack.push(
match word {
"abs" => if c < 0 { -c } else { c }
"2*" => c << 1
"2/" => c >> 1
"invert" => c.lnot()
_ => if c != 0 { -1 } else { 0 }
},
)
return
}
let b = self.pop()
if word == "*/" || word == "*/mod" || word == "/mod" {
let numerator = if word == "/mod" {
b.to_int64()
} else {
self.pop().to_int64() * b.to_int64()
}
if c == 0 {
raise Invalid("division by zero")
}
let quotient = numerator / c.to_int64()
if quotient < -2147483648L || quotient > 2147483647L {
raise Invalid("quotient outside cell range")
}
if word != "*/" {
self.stack.push((numerator % c.to_int64()).to_int())
}
self.stack.push(quotient.to_int())
return
}
if word == "within" {
let a = self.pop()
self.stack.push(
if (a - b).reinterpret_as_uint() < (c - b).reinterpret_as_uint() {
-1
} else {
0
},
)
return
}
if (word == "lshift" || word == "rshift") && (c < 0 || c >= 32) {
raise Invalid("shift outside cell width")
}
self.stack.push(
match word {
"min" => if b < c { b } else { c }
"max" => if b > c { b } else { c }
"xor" => b ^ c
"lshift" => b << c
"rshift" => (b.reinterpret_as_uint() >> c).reinterpret_as_int()
"u<" =>
if b.reinterpret_as_uint() < c.reinterpret_as_uint() {
-1
} else {
0
}
"u>" =>
if b.reinterpret_as_uint() > c.reinterpret_as_uint() {
-1
} else {
0
}
_ => if b != c { -1 } else { 0 }
},
)
}