1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Business logic of a calculator
16 module calculator_logic
20 # Hold the state of the calculator and its services
21 class CalculatorContext
24 # Result of the last operation
25 var result
: nullable Numeric = null
27 # Last operation pushed with `push_op`
28 var last_op
: nullable Text = null
30 # Is `last_op` an unary operation or a '='?
31 var last_op_was_unary
= false
33 # Value currently being entered
34 var current
: nullable String = null
36 # Text to display on screen
37 fun display_text
: String
39 var buf
= new FlatBuffer
43 if result
!= null then
44 if last_op_was_unary
then buf
.append
"{last_op or else "?"} "
46 buf
.append result
.to_s
50 if last_op
!= null and not last_op_was_unary
then
56 if current
!= null then
57 buf
.append current
.to_s
64 # Push operation `op`, will usually execute the last operation
68 # TODO Protect constants to preserve full precision and to forbid appending extra digits
70 if last_op_was_unary
then clear
73 else if op
== "e" then
74 if last_op_was_unary
then clear
75 current
= 2.718282.to_s
79 else if op
== "C" then
84 else if op
== "-" then
85 if current
== null then
86 if last_op_was_unary
then clear
89 else if current
== "-" then
95 # For all operators, apply pending operators
98 var result
= self.result
or else 0
101 last_op_was_unary
= true
105 self.result
= result
.to_f
.sqrt
106 else if op
== "x²" then
107 self.result
= result
.to_f
.pow
(2.0)
108 else if op
== "x!" then
109 self.result
= result
.to_i
.factorial
110 else if op
== "sin" then
111 self.result
= result
.to_f
.sin
112 else if op
== "cos" then
113 self.result
= result
.to_f
.cos
114 else if op
== "tan" then
115 self.result
= result
.to_f
.tan
118 else if op
== "=" then
123 self.result
= result
# Set as same or 0
124 last_op_was_unary
= false
134 last_op_was_unary
= false
139 fun push_digit
(digit
: Int)
141 if last_op_was_unary
then clear
143 var current
= current
144 if current
== null then current
= ""
145 current
+= digit
.to_s
146 self.current
= current
149 # Switch entry mode from integer to decimal
150 fun switch_to_decimals
152 var current
= current
153 if current
== null then current
= "0"
154 if not current
.chars
.has
('.') then current
+= "."
155 self.current
= current
158 # Execute the last operation it not null
159 protected fun apply_last_op_if_any
163 var current
= current
166 if current
== null then return
169 result
= current
.to_n
170 else if result
!= null then
172 result
= result
.add
(current
.to_n
)
173 else if op
== "-" then
174 result
= result
.sub
(current
.to_n
)
175 else if op
== "/" or op
== "÷" then
176 result
= result
.div
(current
.to_n
)
177 else if op
== "*" or op
== "×" then
178 result
= result
.mul
(current
.to_n
)
179 else if op
== "%" then
180 result
= result
.to_i
% current
.to_i
181 else if op
== "xⁿ" then
182 result
= result
.to_f
.pow
(current
.to_f
)
183 else if op
== "log" then
184 result
= result
.to_f
.log_base
(current
.to_f
)
192 redef universal Float
193 redef fun to_s
do return to_precision
(6)