|
|
|
@ -5,6 +5,7 @@
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <cstdint> // int64_t |
|
|
|
|
#include <memory> // std::static_pointer_cast |
|
|
|
|
|
|
|
|
|
#include "ast.h" |
|
|
|
|
#include "env/macro.h" |
|
|
|
@ -14,19 +15,46 @@ namespace blaze {
|
|
|
|
|
|
|
|
|
|
void Environment::loadOperators() |
|
|
|
|
{ |
|
|
|
|
#define APPLY_NUMBER_OR_DECIMAL(it, apply) \ |
|
|
|
|
IS_VALUE(Numeric, (*it)); \
|
|
|
|
|
if (is<Number>(it->get())) { \
|
|
|
|
|
auto it_numeric = std::static_pointer_cast<Number>(*it)->number(); \
|
|
|
|
|
do { \
|
|
|
|
|
apply \
|
|
|
|
|
} while (0); \
|
|
|
|
|
} \
|
|
|
|
|
else { \
|
|
|
|
|
return_decimal = true; \
|
|
|
|
|
auto it_numeric = std::static_pointer_cast<Decimal>(*it)->decimal(); \
|
|
|
|
|
do { \
|
|
|
|
|
apply \
|
|
|
|
|
} while (0); \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define RETURN_NUMBER_OR_DECIMAL() \ |
|
|
|
|
if (!return_decimal) { \
|
|
|
|
|
return makePtr<Number>(number); \
|
|
|
|
|
} \
|
|
|
|
|
return makePtr<Decimal>(decimal); |
|
|
|
|
|
|
|
|
|
ADD_FUNCTION( |
|
|
|
|
"+", |
|
|
|
|
"number...", |
|
|
|
|
"Return the sum of any amount of arguments, where NUMBER is of type number.", |
|
|
|
|
{ |
|
|
|
|
int64_t result = 0; |
|
|
|
|
bool return_decimal = false; |
|
|
|
|
|
|
|
|
|
int64_t number = 0; |
|
|
|
|
double decimal = 0; |
|
|
|
|
|
|
|
|
|
for (auto it = begin; it != end; ++it) { |
|
|
|
|
VALUE_CAST(number, Number, (*it)); |
|
|
|
|
result += number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(it, { |
|
|
|
|
number += it_numeric; |
|
|
|
|
decimal += it_numeric; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return makePtr<Number>(result); |
|
|
|
|
RETURN_NUMBER_OR_DECIMAL(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ADD_FUNCTION( |
|
|
|
@ -42,21 +70,33 @@ subtracts all but the first from the first.)",
|
|
|
|
|
return makePtr<Number>(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool return_decimal = false; |
|
|
|
|
|
|
|
|
|
int64_t number = 0; |
|
|
|
|
double decimal = 0; |
|
|
|
|
|
|
|
|
|
// Start with the first number
|
|
|
|
|
VALUE_CAST(number, Number, (*begin)); |
|
|
|
|
int64_t result = number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(begin, { |
|
|
|
|
number = it_numeric; |
|
|
|
|
decimal = it_numeric; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Return negative on single argument
|
|
|
|
|
if (length == 1) { |
|
|
|
|
return makePtr<Number>(-result); |
|
|
|
|
number = -number; |
|
|
|
|
decimal = -decimal; |
|
|
|
|
RETURN_NUMBER_OR_DECIMAL(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Skip the first node
|
|
|
|
|
for (auto it = begin + 1; it != end; ++it) { |
|
|
|
|
VALUE_CAST(number, Number, (*it)); |
|
|
|
|
result -= number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(it, { |
|
|
|
|
number -= it_numeric; |
|
|
|
|
decimal -= it_numeric; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return makePtr<Number>(result); |
|
|
|
|
RETURN_NUMBER_OR_DECIMAL(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ADD_FUNCTION( |
|
|
|
@ -64,14 +104,19 @@ subtracts all but the first from the first.)",
|
|
|
|
|
"", |
|
|
|
|
"", |
|
|
|
|
{ |
|
|
|
|
int64_t result = 1; |
|
|
|
|
bool return_decimal = false; |
|
|
|
|
|
|
|
|
|
int64_t number = 1; |
|
|
|
|
double decimal = 1; |
|
|
|
|
|
|
|
|
|
for (auto it = begin; it != end; ++it) { |
|
|
|
|
VALUE_CAST(number, Number, (*it)); |
|
|
|
|
result *= number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(it, { |
|
|
|
|
number *= it_numeric; |
|
|
|
|
decimal *= it_numeric; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return makePtr<Number>(result); |
|
|
|
|
RETURN_NUMBER_OR_DECIMAL(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ADD_FUNCTION( |
|
|
|
@ -81,17 +126,26 @@ subtracts all but the first from the first.)",
|
|
|
|
|
{ |
|
|
|
|
CHECK_ARG_COUNT_AT_LEAST("/", SIZE(), 1); |
|
|
|
|
|
|
|
|
|
bool return_decimal = false; |
|
|
|
|
|
|
|
|
|
int64_t number = 0; |
|
|
|
|
double decimal = 0; |
|
|
|
|
|
|
|
|
|
// Start with the first number
|
|
|
|
|
VALUE_CAST(number, Number, (*begin)); |
|
|
|
|
double result = number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(begin, { |
|
|
|
|
number = it_numeric; |
|
|
|
|
decimal = it_numeric; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// Skip the first node
|
|
|
|
|
for (auto it = begin + 1; it != end; ++it) { |
|
|
|
|
VALUE_CAST(number, Number, (*it)); |
|
|
|
|
result /= number->number(); |
|
|
|
|
APPLY_NUMBER_OR_DECIMAL(it, { |
|
|
|
|
number /= it_numeric; |
|
|
|
|
decimal /= it_numeric; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return makePtr<Number>((int64_t)result); |
|
|
|
|
RETURN_NUMBER_OR_DECIMAL(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// (% 5 2) -> 1
|
|
|
|
|