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
138 fun push_digit
(digit
: Int)
140 if last_op_was_unary
then clear
142 var current
= current
143 if current
== null then current
= ""
144 current
+= digit
.to_s
145 self.current
= current
148 # Switch entry mode from integer to decimal
149 fun switch_to_decimals
151 var current
= current
152 if current
== null then current
= "0"
153 if not current
.chars
.has
('.') then current
+= "."
154 self.current
= current
157 # Execute the last operation it not null
158 protected fun apply_last_op_if_any
162 var current
= current
165 if current
== null then return
168 result
= current
.to_n
169 else if result
!= null then
171 result
= result
.add
(current
.to_n
)
172 else if op
== "-" then
173 result
= result
.sub
(current
.to_n
)
174 else if op
== "/" or op
== "÷" then
175 result
= result
.div
(current
.to_n
)
176 else if op
== "*" or op
== "×" then
177 result
= result
.mul
(current
.to_n
)
178 else if op
== "%" then
179 result
= result
.to_i
% current
.to_i
180 else if op
== "xⁿ" then
181 result
= result
.to_f
.pow
(current
.to_f
)
182 else if op
== "log" then
183 result
= result
.to_f
.log_base
(current
.to_f
)
191 redef universal Float
192 redef fun to_s
do return to_precision
(6)