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
22 # Result of the last operation
23 var result
: nullable Numeric = null
25 # Last operation pushed with `push_op`, to be executed on the next push
26 var last_op
: nullable Char = null
28 # Value currently being entered
29 var current
: nullable FlatBuffer = null
31 # Text to display on screen
32 fun display_text
: String
38 var buf
= new FlatBuffer
40 if result
!= null and (current
== null or last_op
!= '=') then
41 if last_op
== '=' then buf
.append
"= "
43 buf
.append result
.to_s
47 if last_op
!= null and last_op
!= '=' then
52 if current
!= null then
53 buf
.append current
.to_s
60 # Push operation `op`, will usually execute the last operation
68 last_op
= op
# store for next push_op
71 # prepare next current
76 fun push_digit
(digit
: Int)
79 if current
== null then current
= new FlatBuffer
80 current
.add digit
.to_s
.chars
.first
81 self.current
= current
83 if last_op
== '=' then
89 # Switch entry mode from integer to decimal
90 fun switch_to_decimals
93 if current
== null then current
= new FlatBuffer.from
("0")
94 if not current
.chars
.has
('.') then current
.add
'.'
95 self.current
= current
98 # Execute the last operation it not null
99 protected fun apply_last_op_if_any
105 var current
= current
106 if current
== null then current
= new FlatBuffer
109 result
= current
.to_n
110 else if op
== '+' then
111 result
= result
.add
(current
.to_n
)
112 else if op
== '-' then
113 result
= result
.sub
(current
.to_n
)
114 else if op
== '/' then
115 result
= result
.div
(current
.to_n
)
116 else if op
== '*' then
117 result
= result
.mul
(current
.to_n
)
124 # Serialize calculator state to Json
127 # Do not save NaN nor inf
128 var result
= self.result
129 if result
!= null and (result
.to_f
.is_nan
or result
.to_f
.is_inf
!= 0) then result
= null
131 var self_last_op
= self.last_op
133 if self_last_op
== null then
135 else last_op
= "\"{self_last_op}\
""
137 var self_current
= self.current
139 if self_current
== null then
141 else current
= "\"{self_current}\
""
145 "result": {{{result or else "null"}}},
146 "last_op": {{{last_op}}},
147 "current": {{{current}}}
151 # Load calculator state from Json
152 init from_json
(json_string
: String)
154 var json
= json_string
.to_json_value
155 if json
.is_error
then
156 print
"Loading state failed: {json.to_error}"
160 var result
= json
["result"]
161 if result
.is_numeric
then self.result
= result
.to_numeric
163 var last_op
= json
["last_op"]
164 if last_op
.is_string
then self.last_op
= last_op
.to_s
.chars
.first
166 var current
= json
["current"]
167 if current
.is_string
then self.current
= new FlatBuffer.from
(current
.to_s
)
171 redef universal Float
172 redef fun to_s
do return to_precision
(6)