1 #include <ail/string.hpp>
2 #include <frith/variable.hpp>
8 std::string
const zero_division_error_message
= "Zero division error";
11 unary_argument::unary_argument(variable
& output
, std::string
& error_message
):
13 error_message(error_message
)
17 binary_argument::binary_argument(variable
const & other
, variable
& output
, std::string
& error_message
)
20 error_message(error_message
)
25 type(variable_type::undefined
)
29 variable::variable(variable
const & other
):
34 case variable_type::boolean
:
35 boolean
= other
.boolean
;
38 case variable_type::signed_integer
:
39 signed_integer
= other
.signed_integer
;
42 case variable_type::unsigned_integer
:
43 unsigned_integer
= other
.unsigned_integer
;
46 case variable_type::floating_point_value
:
47 floating_point_value
= other
.floating_point_value
;
50 case variable_type::string
:
51 string
= new string(*other
.string
);
54 case variable_type::array
:
55 array
= new variable_vector(*other
.array
);
58 case variable_type::map
:
59 map
= new variable_map(*other
.map
);
68 case variable_type::string
:
72 case variable_type::array
:
76 case variable_type::map
:
82 variable_type
variable::get_type() const
89 type
= variable_type::nil
;
92 void variable::new_boolean(types::boolean new_boolean
)
94 type
= variable_type::boolean
;
95 boolean
= new_boolean
;
98 void variable::new_signed_integer(types::signed_integer new_signed_integer
)
100 type
= variable_type::signed_integer
;
101 signed_integer
= new_signed_integer
;
104 void variable::new_unsigned_integer(types::unsigned_integer new_unsigned_integer
)
106 type
= variable_type::unsigned_integer
;
107 unsigned_integer
= new_unsigned_integer
;
110 void variable::new_floating_point_value(types::floating_point_value new_floating_point_value
)
112 type
= variable_type::floating_point_value
;
113 floating_point_value
= new_floating_point_value
;
116 void variable::new_string(types::string
const & new_string
)
118 type
= variable_type::string
;
119 string
= new std::string(new_string
);
122 void variable::new_array()
124 type
= variable_type::array
;
125 array
= new variable_vector();
128 void variable::new_map()
130 type
= variable_type::map
;
131 map
= new variable_map();
134 bool variable::array_addition(binary_argument
& argument
) const
136 bool left_is_array
= type
== variable_type::array
;
137 bool right_is_array
= argument
.other
.type
== variable_type::array
;
139 if(left_is_array
|| right_is_array
)
141 argument
.output
.type
= variable_type::array
;
142 argument
.output
.array
= new types::variable_vector
;
143 types::variable_vector
& vector
= *argument
.output
.array
;
145 if(left_is_array
&& right_is_array
)
148 vector
.append(*argument
.other
.array
);
150 else if(left_is_array
&& !right_is_array
)
153 vector
.push_back(argument
.other
);
155 else if(!left_is_array
&& right_is_array
)
157 vector
= *argument
.other
.array
;
158 vector
.push_back(*this);
167 bool variable::perform_string_conversion(std::string
& output
, bool & error
)
169 if(!get_string_representation(output_string
))
178 bool variable::string_addition(binary_argument
& argument
, bool & error
) const
180 bool left_is_string
= type
== variable_type::string
;
181 bool right_is_string
= argument
.other
.type
== variable_type::string
;
185 if(left_is_string
|| right_is_string
)
187 argument
.output
.type
= variable_type::string
;
188 argument
.output
.string
= new std::string
;
189 std::string
& output_string
= *argument
.output
.string
;
190 if(left_is_string
&& right_is_string
)
191 output_string
= *string
+ *argument
.other
.string
;
192 else if(left_is_string
&& !right_is_string
)
193 return other
.argument
.perform_string_conversion(output_string
, error
);
194 else if(!left_is_string
&& right_is_string
)
195 return perform_string_conversion(output_string
, error
);
203 #define ARITHMETIC_OPERATION(operator) \
204 if(is_numeric_type() && argument.other.is_numeric_type()) \
206 if(is_floating_point_operation(argument)) \
207 argument.output.new_floating_point_value(get_floating_point_value() operator argument.other.get_floating_point_value()); \
209 unsigned_integer = unsigned_integer operator argument.other.unsigned_integer; \
213 argument.error_message = get_binary_argument_type_error(name_of_operation, type, argument.other.type); \
218 bool variable::addition(binary_argument
& argument
) const
220 std::string
const name_of_operation
= "Addition";
222 if(array_addition(argument
))
226 if(string_addition(argument
, string_error
))
231 argument
.error_message
= get_binary_argument_type_error(name_of_operation
, type
, argument
.other
.type
);
235 ARITHMETIC_OPERATION(+)
238 bool variable::subtraction(binary_argument
& argument
) const
240 std::string
const name_of_operation
= "Subtraction";
241 ARITHMETIC_OPERATION(-)
244 bool variable::multiplication(binary_argument
& argument
) const
246 std::string
const name_of_operation
= "Multiplication";
247 ARITHMETIC_OPERATION(*)
250 bool variable::division(binary_argument
& argument
) const
252 std::string
const name_of_operation
= "Division";
253 if(argument
.other
.is_zero())
255 argument
.error_message
= zero_division_error_message
;
258 ARITHMETIC_OPERATION(/)
261 bool variable::modulo(binary_argument
& argument
) const
263 std::string
const name_of_operation
= "Modulo";
264 if(argument
.other
.is_zero())
266 argument
.error_message
= zero_division_error_message
;
269 ARITHMETIC_OPERATION(%)
272 bool variable::negative(unary_argument
& argument
) const
276 bool variable::less_than(binary_argument
& argument
) const
280 bool variable::less_than_or_equal(binary_argument
& argument
) const
284 bool variable::greater_than(binary_argument
& argument
) const
288 bool variable::greater_than_or_equal(binary_argument
& argument
) const
292 bool variable::unequal(binary_argument
& argument
) const
296 bool variable::equal(binary_argument
& argument
) const
300 bool variable::logical_not(unary_argument
& argument
) const
304 bool variable::logical_and(binary_argument
& argument
) const
308 bool variable::logical_or(binary_argument
& argument
) const
312 bool variable::shift_left(binary_argument
& argument
) const
316 bool variable::shift_right(binary_argument
& argument
) const
320 bool variable::binary_and(binary_argument
& argument
) const
324 bool variable::binary_or(binary_argument
& argument
) const
328 bool variable::binary_xor(binary_argument
& argument
) const
332 bool variable::binary_not(unary_argument
& argument
) const
336 bool variabe::is_floating_point_operation(binary_argument
& argument
) const
338 return type
== variable_type::floating_point_value
|| argument
.other
.type
== variable_type::floating_point_value
;
341 bool variabe::is_numeric_type(binary_argument
& argument
) const
344 type
== variable_type::signed_integer
||
345 type
== variable_type::unsigned_integer
||
346 type
== variable_type::floating_point_value
;
349 types::floating_point_value
variable::get_floating_point_value() const
353 case variable_type::signed_integer
:
354 return signed_integer
;
356 case variable_type::unsigned_integer
:
357 return unsigned_integer
;
359 case variable_type::floating_point_value
:
360 return floating_point_value
;
363 throw ail::exception("Failed to retrieve floating point value");
366 bool variable::get_string_representation(std::string
& output
) const
370 case variable_type::boolean
:
371 output
= ail::bool_to_string(boolean
);
374 case variable_type::signed_integer
:
375 output
= ail::number_to_string
<types::signed_integer
>(signed_integer
);
378 case variable_type::unsigned_integer
:
379 output
= ail::number_to_string
<types::unsigned_integer
>(unsigned_integer
);
382 case variable_type::floating_point_value
:
383 output
= ail::number_to_string
<types::floating_point_value
>(floating_point_value
);
393 bool variable::is_zero() const
397 case variable_type::signed_integer
:
398 return signed_integer
== 0;
400 case variable_type::unsigned_integer
:
401 return unsigned_integer
== 0;
403 case variable_type::floating_point_value
:
404 return floating_point_value
== 0.0;
407 throw exception("Unable to check if variable is zero");
410 std::string
get_type_string(variable_type type
)
414 case variable_type::undefined
:
417 case variable_type::nil
:
420 case variable_type::boolean
:
423 case variable_type::signed_integer
:
426 case variable_type::unsigned_integer
:
427 return "unsigned-integer";
429 case variable_type::floating_point_value
:
432 case variable_type::string
:
435 case variable_type::array
:
438 case variable_type::map
:
445 std::string
get_binary_argument_type_error(std::string
const & operation
, variable_type left
, variable_type right
)
447 return operation
+ ": Invalid argument types \"" + get_type_string(left
) + "\", \"" + get_type_string(right
);