value operator for numeric values now explicit
This commit is contained in:
@@ -14,6 +14,16 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
inline bool isDoubleInteger(ValueType::DoubleClass d)
|
||||||
|
{
|
||||||
|
return std::floor(d) == d;
|
||||||
|
}
|
||||||
|
inline bool isNumberExceededIntLimit(ValueType::DoubleClass d)
|
||||||
|
{
|
||||||
|
static constexpr ValueType::DoubleClass intMaxAsDouble = static_cast<ValueType::DoubleClass>(std::numeric_limits<ValueType::IntClass>::max());
|
||||||
|
static constexpr ValueType::DoubleClass intMinAsDouble = static_cast<ValueType::DoubleClass>(std::numeric_limits<ValueType::IntClass>::min());
|
||||||
|
return d > intMaxAsDouble || d < intMinAsDouble;
|
||||||
|
}
|
||||||
class Value
|
class Value
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -194,7 +204,14 @@ namespace Fig
|
|||||||
if (lhs.isNull() || rhs.isNull())
|
if (lhs.isNull() || rhs.isNull())
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
|
||||||
if (lhs.isNumeric() and rhs.isNumeric())
|
if (lhs.isNumeric() and rhs.isNumeric())
|
||||||
return lhs.getNumericValue() + rhs.getNumericValue();
|
{
|
||||||
|
ValueType::DoubleClass result = lhs.getNumericValue() + rhs.getNumericValue();
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
|
}
|
||||||
if (lhs.is<String>() && rhs.is<String>())
|
if (lhs.is<String>() && rhs.is<String>())
|
||||||
return Value(ValueType::StringClass(lhs.as<String>().getValue() + rhs.as<String>().getValue()));
|
return Value(ValueType::StringClass(lhs.as<String>().getValue() + rhs.as<String>().getValue()));
|
||||||
|
|
||||||
@@ -206,7 +223,14 @@ namespace Fig
|
|||||||
if (lhs.isNull() || rhs.isNull())
|
if (lhs.isNull() || rhs.isNull())
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
|
||||||
if (lhs.isNumeric() and rhs.isNumeric())
|
if (lhs.isNumeric() and rhs.isNumeric())
|
||||||
return lhs.getNumericValue() - rhs.getNumericValue();
|
{
|
||||||
|
ValueType::DoubleClass result = lhs.getNumericValue() - rhs.getNumericValue();
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
|
}
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +239,14 @@ namespace Fig
|
|||||||
if (lhs.isNull() || rhs.isNull())
|
if (lhs.isNull() || rhs.isNull())
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
|
||||||
if (lhs.isNumeric() and rhs.isNumeric())
|
if (lhs.isNumeric() and rhs.isNumeric())
|
||||||
return lhs.getNumericValue() * rhs.getNumericValue();
|
{
|
||||||
|
ValueType::DoubleClass result = lhs.getNumericValue() * rhs.getNumericValue();
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
|
}
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,9 +256,14 @@ namespace Fig
|
|||||||
throw ValueError(FStringView(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
|
||||||
if (lhs.isNumeric() and rhs.isNumeric())
|
if (lhs.isNumeric() and rhs.isNumeric())
|
||||||
{
|
{
|
||||||
auto rnv = rhs.getNumericValue();
|
ValueType::DoubleClass rnv = rhs.getNumericValue();
|
||||||
if (rnv == 0) throw ValueError(FStringView(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
|
if (rnv == 0) throw ValueError(FStringView(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
|
||||||
return lhs.getNumericValue() / rnv;
|
ValueType::DoubleClass result = lhs.getNumericValue() / rnv;
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
}
|
}
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
|
||||||
}
|
}
|
||||||
@@ -238,9 +274,14 @@ namespace Fig
|
|||||||
throw ValueError(FStringView(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
|
||||||
if (lhs.isNumeric() and rhs.isNumeric())
|
if (lhs.isNumeric() and rhs.isNumeric())
|
||||||
{
|
{
|
||||||
auto rnv = rhs.getNumericValue();
|
ValueType::DoubleClass rnv = rhs.getNumericValue();
|
||||||
if (rnv == 0) throw ValueError(FStringView(makeTypeErrorMessage("Modulo by zero", "%", lhs, rhs)));
|
if (rnv == 0) throw ValueError(FStringView(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||||
return fmod(lhs.getNumericValue(), rhs.getNumericValue());
|
ValueType::DoubleClass result = fmod(lhs.getNumericValue(), rnv);
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
}
|
}
|
||||||
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
||||||
}
|
}
|
||||||
@@ -367,6 +408,22 @@ namespace Fig
|
|||||||
throw ValueError(FStringView(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
|
throw ValueError(FStringView(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
|
||||||
return Value(lhs.as<Int>().getValue() >> rhs.as<Int>().getValue());
|
return Value(lhs.as<Int>().getValue() >> rhs.as<Int>().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend Value power(const Value &base, const Value &exp)
|
||||||
|
{
|
||||||
|
if (base.isNull() || exp.isNull())
|
||||||
|
throw ValueError(FStringView(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp)));
|
||||||
|
if (base.isNumeric() and exp.isNumeric())
|
||||||
|
{
|
||||||
|
ValueType::DoubleClass result = std::pow(base.getNumericValue(), exp.getNumericValue());
|
||||||
|
if (isDoubleInteger(result) and !isNumberExceededIntLimit(result))
|
||||||
|
{
|
||||||
|
return Value(static_cast<ValueType::IntClass>(result));
|
||||||
|
}
|
||||||
|
return Value(ValueType::DoubleClass(result));
|
||||||
|
}
|
||||||
|
throw ValueError(FStringView(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using Any = Value;
|
using Any = Value;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace Fig
|
|||||||
case Operator::Multiply: return lhs * rhs;
|
case Operator::Multiply: return lhs * rhs;
|
||||||
case Operator::Divide: return lhs / rhs;
|
case Operator::Divide: return lhs / rhs;
|
||||||
case Operator::Modulo: return lhs % rhs;
|
case Operator::Modulo: return lhs % rhs;
|
||||||
|
case Operator::Power: return power(lhs, rhs);
|
||||||
|
|
||||||
case Operator::And: return lhs && rhs;
|
case Operator::And: return lhs && rhs;
|
||||||
case Operator::Or: return lhs || rhs;
|
case Operator::Or: return lhs || rhs;
|
||||||
@@ -291,7 +292,7 @@ namespace Fig
|
|||||||
if (expectedType != actualType and expectedType != ValueType::Any)
|
if (expectedType != actualType and expectedType != ValueType::Any)
|
||||||
{
|
{
|
||||||
static constexpr char VariableTypeMismatchErrorName[] = "VariableTypeMismatchError";
|
static constexpr char VariableTypeMismatchErrorName[] = "VariableTypeMismatchError";
|
||||||
throw EvaluatorError<VariableTypeMismatchErrorName>(FStringView(std::format("Variable '{}' expects type '{}', but got type '{}'", varDef->name.toBasicString(), expectedType.toString().toBasicString(), actualType.toString().toBasicString())), currentAddressInfo);
|
throw EvaluatorError<VariableTypeMismatchErrorName>(FStringView(std::format("Variable '{}' expects type '{}', but got type '{}'", varDef->name.toBasicString(), expectedType.toString().toBasicString(), actualType.toString().toBasicString())), varDef->getAAI());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user