Skip to content

Commit

Permalink
WIP: We are making progress. Things feel good.
Browse files Browse the repository at this point in the history
Comparisons with double and BigInt are a bit picky. I have implemented
some of it now, and some more remains. We *will* be producing weird
results for small/big doubles, because of the way IEEE754 floating
points are represented. But that's life, and we just need to make our
dear users aware of it.
  • Loading branch information
perlun committed Dec 28, 2023
1 parent 46e8c0e commit 034ecaf
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 12 deletions.
12 changes: 12 additions & 0 deletions src/Perlang.Interpreter/Compiler/PerlangCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,18 @@ private void RegisterGlobalClasses()
"-Wall",
"-Werror",

// Enable warnings on e.g. narrowing conversion from `long long` to `unsigned long long`.
"-Wconversion",

// ...but do not warn on implicit conversion from `int` to `float` or `double`. For now, we are
// aiming at mimicking the C# semantics in this.
"-Wno-implicit-int-float-conversion",

// Certain narrowing conversions are problematic; we have seen this causing issues when implementing
// the BigInt support. For example, `uint64_t` must not be implicitly converted to call a `long
// long` constructor/method.
"-Wimplicit-int-conversion",

// C# allows cast from e.g. 2147483647 to float without warnings, but here's an interesting thing:
// clang emits a very nice warning for this ("implicit conversion from 'int' to 'float' changes
// value from 2147483647 to 2147483648"). We might want to consider doing something similar for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ public static class BinaryOperatorData
new object[] { "9223372036854775807", "18446744073709551616", "false" },
new object[] { "9223372036854775807", "340282349999999991754788743781432688640.0f", "false" },
new object[] { "9223372036854775807", "12.0", "false" },
new object[] { "9223372036854775807", "9223372036854775807.0", "false" },
new object[] { "18446744073709551615", "2147483647", "false" },
new object[] { "18446744073709551615", "4294967295", "false" },
new object[] { "18446744073709551615", "9223372036854775807", "false" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Perlang.Tests.Integration.Operator.Binary
// https://github.com/munificent/craftinginterpreters/blob/c6da0e61e6072271de404464c34b51c2fdc39e59/test/operator/divide_num_nonnum.lox
public class DivisionTests
{
[SkippableTheory]
[Theory]
[MemberData(nameof(BinaryOperatorData.Division_result), MemberType = typeof(BinaryOperatorData))]
void performs_division(string i, string j, string expectedResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MultiplicationTests
//
// Tests for the * (multiplication) operator
//
[SkippableTheory]
[Theory]
[MemberData(nameof(BinaryOperatorData.Multiplication_result), MemberType = typeof(BinaryOperatorData))]
public void performs_multiplication(string i, string j, string expectedResult)
{
Expand Down
2 changes: 1 addition & 1 deletion src/stdlib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ install(
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

# The testing code is not yet ready for macOS, since it uses a different linker which doesnät support --wrap. We'll
# The testing code is not yet ready for macOS, since it uses a different linker which doesn't support --wrap. We'll
# live with only building/running the tests on other platforms for now.
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
enable_testing()
Expand Down
179 changes: 175 additions & 4 deletions src/stdlib/src/bigint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,26 @@ BigInt::BigInt(const BigInt& num) {


/*
Integer to BigInt
Integer (various sizes) to BigInt
-----------------
*/

BigInt::BigInt(const int& num) :
BigInt((long long)num) {
}

BigInt::BigInt(const unsigned int& num) :
BigInt((unsigned long long)num) {
}

BigInt::BigInt(const long& num) :
BigInt((long long)num) {
}

BigInt::BigInt(const unsigned long& num) :
BigInt((unsigned long long)num) {
}

BigInt::BigInt(const long long& num) {
value = std::to_string(std::abs(num));
if (num < 0)
Expand All @@ -226,6 +242,11 @@ BigInt::BigInt(const long long& num) {
sign = '+';
}

BigInt::BigInt(const unsigned long long& num) {
value = std::to_string(num);
sign = '+';
}


/*
String to BigInt
Expand Down Expand Up @@ -510,20 +531,72 @@ bool BigInt::operator>=(const BigInt& num) const {
-----------------
*/

bool BigInt::operator==(const int& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const unsigned int& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const long& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const unsigned long& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const long long& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const unsigned long long& num) const {
return *this == BigInt(num);
}

bool BigInt::operator==(const double& num) const {
if (ceil(num) != num) {
// num has a fractional part and can inherently never be equal to a BigInt.
return false;
}
else {
// num does not have a fractional part. Disregarding IEEE754 semantics, we can compare it to a BigInt (reliably
// for numbers between -2^53 and +2^53, because of the aforementioned IEEE754 semantics).
return *this == BigInt((int64_t)num);
}
}


/*
Integer == BigInt
-----------------
*/

bool operator==(const int& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}

bool operator==(const unsigned int& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}

bool operator==(const long& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}

bool operator==(const unsigned long& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}

bool operator==(const long long& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}

bool operator==(const unsigned long long& lhs, const BigInt& rhs) {
return BigInt(lhs) == rhs;
}


/*
BigInt != Integer
Expand Down Expand Up @@ -1402,20 +1475,60 @@ BigInt operator*(const long long& lhs, const BigInt& rhs) {
----------------
*/

BigInt BigInt::operator/(const int& num) const {
return *this / BigInt(num);
}

BigInt BigInt::operator/(const unsigned int& num) const {
return *this / BigInt(num);
}

BigInt BigInt::operator/(const long& num) const {
return *this / BigInt(num);
}

BigInt BigInt::operator/(const unsigned long& num) const {
return *this / BigInt(num);
}

BigInt BigInt::operator/(const long long& num) const {
return *this / BigInt(num);
}

BigInt BigInt::operator/(const unsigned long long& num) const {
return *this / BigInt(num);
}


/*
Integer / BigInt
----------------
*/

BigInt operator/(const int& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}

BigInt operator/(const unsigned int& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}

BigInt operator/(const long& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}

BigInt operator/(const unsigned long& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}

BigInt operator/(const long long& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}

BigInt operator/(const unsigned long long& lhs, const BigInt& rhs) {
return BigInt(lhs) / rhs;
}


/*
BigInt % Integer
Expand Down Expand Up @@ -1615,24 +1728,84 @@ BigInt& BigInt::operator%=(const BigInt& num) {
-----------------
*/

BigInt& BigInt::operator+=(const int& num) {
*this = *this + BigInt(num);

return *this;
}

BigInt& BigInt::operator+=(const unsigned int& num) {
*this = *this + BigInt(num);

return *this;
}

BigInt& BigInt::operator+=(const long& num) {
*this = *this + BigInt(num);

return *this;
}

BigInt& BigInt::operator+=(const unsigned long& num) {
*this = *this + BigInt(num);

return *this;
}

BigInt& BigInt::operator+=(const long long& num) {
*this = *this + BigInt(num);

return *this;
}

BigInt& BigInt::operator+=(const unsigned long long& num) {
*this = *this + BigInt(num);

return *this;
}


/*
BigInt -= Integer
-----------------
*/

BigInt& BigInt::operator-=(const int& num) {
*this = *this - BigInt(num);

return *this;
}

BigInt& BigInt::operator-=(const unsigned int& num) {
*this = *this - BigInt(num);

return *this;
}

BigInt& BigInt::operator-=(const long& num) {
*this = *this - BigInt(num);

return *this;
}

BigInt& BigInt::operator-=(const unsigned long& num) {
*this = *this - BigInt(num);

return *this;
}

BigInt& BigInt::operator-=(const long long& num) {
*this = *this - BigInt(num);

return *this;
}

BigInt& BigInt::operator-=(const unsigned long long& num) {
*this = *this - BigInt(num);

return *this;
}


/*
BigInt *= Integer
Expand Down Expand Up @@ -1837,6 +2010,4 @@ std::ostream& operator<<(std::ostream& out, const BigInt& num) {
return out;
}

#endif // BIG_INT_IO_STREAM_OPERATORS_HPP


#endif // BIG_INT_IO_STREAM_OPERATORS_HPP
Loading

0 comments on commit 034ecaf

Please sign in to comment.