775e8e31af61c7b356bee0e0d93fda6b0916847b
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 # For all operators, apply pending operators
87 var result
= self.result
or else 0
90 last_op_was_unary
= true
94 self.result
= result
.to_f
.sqrt
95 else if op
== "x²" then
96 self.result
= result
.to_f
.pow
(2.0)
97 else if op
== "x!" then
98 self.result
= result
.to_i
.factorial
99 else if op
== "sin" then
100 self.result
= result
.to_f
.sin
101 else if op
== "cos" then
102 self.result
= result
.to_f
.cos
103 else if op
== "tan" then
104 self.result
= result
.to_f
.tan
107 else if op
== "=" then
112 self.result
= result
# Set as same or 0
113 last_op_was_unary
= false
127 fun push_digit
(digit
: Int)
129 if last_op_was_unary
then clear
131 var current
= current
132 if current
== null then current
= ""
133 current
+= digit
.to_s
134 self.current
= current
137 # Switch entry mode from integer to decimal
138 fun switch_to_decimals
140 var current
= current
141 if current
== null then current
= "0"
142 if not current
.chars
.has
('.') then current
+= "."
143 self.current
= current
146 # Execute the last operation it not null
147 protected fun apply_last_op_if_any
151 var current
= current
154 if current
== null then return
157 result
= current
.to_n
158 else if result
!= null then
160 result
= result
.add
(current
.to_n
)
161 else if op
== "-" then
162 result
= result
.sub
(current
.to_n
)
163 else if op
== "/" or op
== "÷" then
164 result
= result
.div
(current
.to_n
)
165 else if op
== "*" or op
== "×" then
166 result
= result
.mul
(current
.to_n
)
167 else if op
== "%" then
168 result
= result
.to_i
% current
.to_i
169 else if op
== "xⁿ" then
170 result
= result
.to_f
.pow
(current
.to_f
)
171 else if op
== "log" then
172 result
= result
.to_f
.log_base
(current
.to_f
)
180 redef universal Float
181 redef fun to_s
do return to_precision
(6)