# Result of the last operation
var result: nullable Numeric = null
- # Last operation pushed with `push_op`, to be executed on the next push
+ # Last operation pushed with `push_op`
var last_op: nullable Text = null
+ # Is `last_op` an unary operation or a '='?
+ var last_op_was_unary = false
+
# Value currently being entered
var current: nullable String = null
# Text to display on screen
fun display_text: String
do
- var result = result
- var last_op = last_op
- var current = current
-
var buf = new FlatBuffer
- if result != null and (current == null or last_op != "=") then
- if last_op == "=" then buf.append "= "
+ var last_op = last_op
+ var result = result
+ if result != null then
+ if last_op_was_unary then buf.append "{last_op or else "?"} "
buf.append result.to_s
buf.add ' '
end
- if last_op != null and last_op != "=" then
+ if last_op != null and not last_op_was_unary then
buf.append last_op
buf.add ' '
end
+ var current = current
if current != null then
buf.append current.to_s
buf.add ' '
# Push operation `op`, will usually execute the last operation
fun push_op(op: Text)
do
+ # Constants
+ # TODO Protect constants to preserve full precision and to forbid appending extra digits
+ if op == "π" then
+ if last_op_was_unary then clear
+ current = pi.to_s
+ return
+ else if op == "e" then
+ if last_op_was_unary then clear
+ current = 2.718282.to_s
+ return
+
+ # Clear screen
+ else if op == "C" then
+ clear
+ return
+ end
+
+ # For all operators, apply pending operators
apply_last_op_if_any
- if op == "C" then
- self.result = null
- last_op = null
+
+ var result = self.result or else 0
+
+ last_op = op
+ last_op_was_unary = true
+
+ # Unary operators
+ if op == "√" then
+ self.result = result.to_f.sqrt
+ else if op == "x²" then
+ self.result = result.to_f.pow(2.0)
+ else if op == "x!" then
+ self.result = result.to_i.factorial
+ else if op == "sin" then
+ self.result = result.to_f.sin
+ else if op == "cos" then
+ self.result = result.to_f.cos
+ else if op == "tan" then
+ self.result = result.to_f.tan
+
+ # =
+ else if op == "=" then
+ current = null
+
+ # Binary operators
else
- last_op = op # store for next push_op
+ self.result = result # Set as same or 0
+ last_op_was_unary = false
+ current = null
end
+ end
- # prepare next current
- self.current = null
+ # Clear all state
+ private fun clear
+ do
+ result = null
+ last_op = null
+ current = null
end
# Push a digit
fun push_digit(digit: Int)
do
+ if last_op_was_unary then clear
+
var current = current
if current == null then current = ""
current += digit.to_s
self.current = current
-
- if last_op == "=" then
- self.result = null
- last_op = null
- end
end
# Switch entry mode from integer to decimal
result = result.div(current.to_n)
else if op == "*" or op == "×" then
result = result.mul(current.to_n)
+ else if op == "%" then
+ result = result.to_i % current.to_i
+ else if op == "xⁿ" then
+ result = result.to_f.pow(current.to_f)
+ else if op == "log" then
+ result = result.to_f.log_base(current.to_f)
end
end