Implemented the standard arithmetic operators
[frith-skrift.git] / frith / variable.cpp
blob3a2effcb93d2cd04c3c48c404b1e0fdfc16d3454
1 #include <ail/string.hpp>
2 #include <frith/variable.hpp>
4 namespace frith
6 namespace
8 std::string const zero_division_error_message = "Zero division error";
11 unary_argument::unary_argument(variable & output, std::string & error_message):
12 output(output),
13 error_message(error_message)
17 binary_argument::binary_argument(variable const & other, variable & output, std::string & error_message)
18 other(other),
19 output(output),
20 error_message(error_message)
24 variable::variable():
25 type(variable_type::undefined)
29 variable::variable(variable const & other):
30 type(other.type)
32 switch(type)
34 case variable_type::boolean:
35 boolean = other.boolean;
36 break;
38 case variable_type::signed_integer:
39 signed_integer = other.signed_integer;
40 break;
42 case variable_type::unsigned_integer:
43 unsigned_integer = other.unsigned_integer;
44 break;
46 case variable_type::floating_point_value:
47 floating_point_value = other.floating_point_value;
48 break;
50 case variable_type::string:
51 string = new string(*other.string);
52 break;
54 case variable_type::array:
55 array = new variable_vector(*other.array);
56 break;
58 case variable_type::map:
59 map = new variable_map(*other.map);
60 break;
64 variable::~variable()
66 switch(type)
68 case variable_type::string:
69 delete string;
70 break;
72 case variable_type::array:
73 delete array;
74 break;
76 case variable_type::map:
77 delete map;
78 break;
82 variable_type variable::get_type() const
84 return type;
87 void variable::nil()
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)
147 vector = *array;
148 vector.append(*argument.other.array);
150 else if(left_is_array && !right_is_array)
152 vector = *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);
161 else
162 return false;
164 return true;
167 bool variable::perform_string_conversion(std::string & output, bool & error)
169 if(!get_string_representation(output_string))
171 error = true;
172 return false;
174 else
175 return true;
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;
183 error = false;
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);
197 else
198 return false;
200 return true;
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()); \
208 else \
209 unsigned_integer = unsigned_integer operator argument.other.unsigned_integer; \
211 else \
213 argument.error_message = get_binary_argument_type_error(name_of_operation, type, argument.other.type); \
214 return false; \
216 return true;
218 bool variable::addition(binary_argument & argument) const
220 std::string const name_of_operation = "Addition";
222 if(array_addition(argument))
223 return true;
225 bool string_error;
226 if(string_addition(argument, string_error))
227 return true;
229 if(string_error)
231 argument.error_message = get_binary_argument_type_error(name_of_operation, type, argument.other.type);
232 return false;
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;
256 return false;
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;
267 return false;
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
343 return
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
351 switch(type)
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
368 switch(type)
370 case variable_type::boolean:
371 output = ail::bool_to_string(boolean);
372 break;
374 case variable_type::signed_integer:
375 output = ail::number_to_string<types::signed_integer>(signed_integer);
376 break;
378 case variable_type::unsigned_integer:
379 output = ail::number_to_string<types::unsigned_integer>(unsigned_integer);
380 break;
382 case variable_type::floating_point_value:
383 output = ail::number_to_string<types::floating_point_value>(floating_point_value);
384 break;
386 default:
387 return false;
390 return true;
393 bool variable::is_zero() const
395 switch(type)
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)
412 switch(type)
414 case variable_type::undefined:
415 return "undefined";
417 case variable_type::nil:
418 return "nil";
420 case variable_type::boolean:
421 return "boolean";
423 case variable_type::signed_integer:
424 return "integer";
426 case variable_type::unsigned_integer:
427 return "unsigned-integer";
429 case variable_type::floating_point_value:
430 return "float";
432 case variable_type::string:
433 return "string";
435 case variable_type::array:
436 return "array";
438 case variable_type::map:
439 return "map";
442 return "unknown";
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);