diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e52d282 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,27 @@ +--- +kind: pipeline +type: exec +name: abacus checks + +steps: +- name: flake check + commands: + - nix flake check + +- name: notifiy + commands: + - nix run github:ambroisie/matrix-notifier + environment: + ADDRESS: + from_secret: matrix_homeserver + ROOM: + from_secret: matrix_roomid + USER: + from_secret: matrix_username + PASS: + from_secret: matrix_password + when: + status: + - failure + - success +... diff --git a/.woodpecker/check.yml b/.woodpecker/check.yml deleted file mode 100644 index 0901624..0000000 --- a/.woodpecker/check.yml +++ /dev/null @@ -1,31 +0,0 @@ -labels: - type: exec - -steps: -- name: flake check - image: bash - commands: - - nix flake check - -- name: package check - image: bash - commands: - - nix build - -- name: notify - image: bash - secrets: - - source: matrix_roomid - target: room - - source: matrix_username - target: user - - source: matrix_password - target: pass - - source: matrix_homeserver - target: address - commands: - - nix run github:ambroisie/matrix-notifier - when: - status: - - failure - - success diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d72bf3..4ef9a7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,15 +4,12 @@ enable_testing() add_library(common_options INTERFACE) target_compile_features(common_options INTERFACE - cxx_std_20 + cxx_std_17 ) target_compile_options(common_options INTERFACE -Wall -Wextra ) -target_include_directories(common_options INTERFACE - src -) add_subdirectory(src) add_subdirectory(tests) diff --git a/flake.nix b/flake.nix index a697e6b..cdf39b2 100644 --- a/flake.nix +++ b/flake.nix @@ -29,40 +29,9 @@ }; outputs = { self, futils, nixpkgs, pre-commit-hooks }: - { - overlays.default = final: prev: { - abacus = final.stdenv.mkDerivation { - pname = "abacus"; - version = "0.0.0"; - - src = self; - - nativeBuildInputs = with final; [ - bison - cmake - flex - ninja - pkg-config - ]; - - checkInputs = with final; [ - gtest - ]; - - doCheck = true; - - meta = with final.lib; { - description = "A simple calculator using big numbers"; - homepage = "https://gitea.belanyi.fr/ambroisie/abacus"; - license = licenses.mit; - maintainers = [ ambroisie ]; - platforms = platforms.unix; - }; - }; - }; - } // futils.lib.eachDefaultSystem (system: + futils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; }; + pkgs = import nixpkgs { inherit system; }; in { checks = { @@ -87,17 +56,46 @@ }; }; - devShells.default = pkgs.mkShell { - inputsFrom = with self.packages.${system}; [ - abacus - ]; + defaultPackage = self.packages.${system}.abacus; + + devShell = pkgs.mkShell { + inherit (self.defaultPackage.${system}) + checkInputs + nativeBuildInputs + ; inherit (self.checks.${system}.pre-commit) shellHook; }; packages = futils.lib.flattenTree { - inherit (pkgs) abacus; - default = pkgs.abacus; + abacus = pkgs.stdenv.mkDerivation { + pname = "abacus"; + version = "0.0.0"; + + src = self; + + nativeBuildInputs = with pkgs; [ + bison + cmake + flex + ninja + pkg-config + ]; + + checkInputs = with pkgs; [ + gtest + ]; + + doCheck = true; + + meta = with pkgs.lib; { + description = "A simple calculator using big numbers"; + homepage = "https://gitea.belanyi.fr/ambroisie/abacus"; + license = licenses.mit; + maintainers = [ ambroisie ]; + platforms = platforms.unix; + }; + }; }; }); } diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..4910f6a --- /dev/null +++ b/meson.build @@ -0,0 +1,13 @@ +project( + 'abacus', + 'cpp', + version: '0.0.0', + license: 'MIT', + default_options: [ + 'warning_level=3', + 'cpp_std=c++17', + ], +) + +subdir('src') +subdir('tests') diff --git a/src/abacus.cc b/src/abacus.cc index 45d2394..3e735a0 100644 --- a/src/abacus.cc +++ b/src/abacus.cc @@ -1,4 +1,4 @@ -#include "parse/parser-driver.hh" +#include "parser-driver.hh" // FIXME: I would like `parse/parser-driver.hh` path instead... int main() { abacus::parse::ParserDriver driver{}; diff --git a/src/bignum/CMakeLists.txt b/src/bignum/CMakeLists.txt index 6b64eb6..b2434b7 100644 --- a/src/bignum/CMakeLists.txt +++ b/src/bignum/CMakeLists.txt @@ -3,3 +3,7 @@ add_library(bignum STATIC bignum.hh ) target_link_libraries(bignum PRIVATE common_options) + +target_include_directories(bignum PUBLIC + $ +) diff --git a/src/bignum/bignum.cc b/src/bignum/bignum.cc index f38159f..2121cdc 100644 --- a/src/bignum/bignum.cc +++ b/src/bignum/bignum.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -83,17 +82,18 @@ digits_type do_addition(digits_type const& lhs, digits_type const& rhs) { ++it2; } - auto leftover = [=]() { - if (it1 != end1) { - return std::span(it1, end1); - } - return std::span(it2, end2); - }(); + auto it = it1; + auto end = end1; + if (it1 == end1) { + it = it2; + end = end2; + } - for (auto value : leftover) { - int addition = value + carry; + while (it != end) { + int addition = *it + carry; carry = addition / BASE; res.push_back(addition % BASE); + ++it; } if (carry != 0) { @@ -107,7 +107,7 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) { assert(!do_less_than(lhs, rhs)); digits_type complement; - auto const take_complement = [](auto num) { return BASE - 1 - num; }; + auto const take_complement = [](auto num) { return 9 - num; }; std::transform(lhs.begin(), lhs.end(), std::back_inserter(complement), take_complement); @@ -363,11 +363,7 @@ bool BigNum::less_than(BigNum const& rhs) const { return sign_ < rhs.sign_; } - if (is_positive()) { - return do_less_than(digits_, rhs.digits_); - } else { - return do_less_than(rhs.digits_, digits_); - } + return do_less_than(digits_, rhs.digits_); } void BigNum::canonicalize() { @@ -385,15 +381,15 @@ bool BigNum::is_canonicalized() const { return sign_ == 0; } - // `back` is valid since there is at least one element - auto const has_leading_zero = digits_.back() == 0; - if (has_leading_zero) { + auto const leading_zeros = std::find_if(digits_.rbegin(), digits_.rend(), + [](auto v) { return v != 0; }); + if (leading_zeros != digits_.rbegin()) { return false; } - auto const has_overflow = std::any_of(digits_.begin(), digits_.end(), - [](auto v) { return v >= BASE; }); - if (has_overflow) { + auto const overflow = std::find_if(digits_.begin(), digits_.end(), + [](auto v) { return v >= BASE; }); + if (overflow != digits_.end()) { return false; } diff --git a/src/bignum/meson.build b/src/bignum/meson.build new file mode 100644 index 0000000..af1e4e5 --- /dev/null +++ b/src/bignum/meson.build @@ -0,0 +1,16 @@ +bignum_sources = files( + 'bignum.cc', + 'bignum.hh', +) + +bignum_inc = include_directories('.') + +bignum_lib = static_library( + 'bignum', + sources: bignum_sources, +) + +bignum = declare_dependency( + link_with: bignum_lib, + include_directories: bignum_inc, +) diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..a6c5cb2 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,16 @@ +abacus_sources = files( + 'abacus.cc', +) + +subdir('bignum') +subdir('parse') + +abacus = executable( + 'abacus', + sources: abacus_sources, + dependencies: [ + bignum, + parse, + ], + install: true, +) diff --git a/src/parse/CMakeLists.txt b/src/parse/CMakeLists.txt index 22a706c..3c87a92 100644 --- a/src/parse/CMakeLists.txt +++ b/src/parse/CMakeLists.txt @@ -18,6 +18,6 @@ target_link_libraries(parse PRIVATE ) target_include_directories(parse PUBLIC - $ $ + $ ) diff --git a/src/parse/meson.build b/src/parse/meson.build new file mode 100644 index 0000000..1a3bdcb --- /dev/null +++ b/src/parse/meson.build @@ -0,0 +1,48 @@ +flex_binary = find_program('flex', required: true) +lexer_sources = custom_target( + 'lexer_sources', + input: 'scanner.ll', + output: 'scanner.cc', + command: [ + flex_binary, + '-o', + '@OUTPUT@', + '@INPUT@', + ], +) + +bison_binary = find_program('bison', required: true) +parser_sources = custom_target( + 'parser_sources', + input: 'parser.yy', + output: [ + 'parser.cc', + 'parser.hh', + ], + command: [ + bison_binary, + '@INPUT@', + '--output=@OUTPUT0@', + '--defines=@OUTPUT1@', + '--graph', + # FIXME: html output in bison 3.7.90 + ], +) + +parse_inc = include_directories('.') + +parse_lib = static_library( + 'parser', + 'parser-driver.cc', + 'parser-driver.hh', + lexer_sources, + parser_sources, + dependencies: [ + bignum, + ], +) + +parse = declare_dependency( + link_with: parse_lib, + include_directories: parse_inc, +) diff --git a/src/parse/parser-driver.hh b/src/parse/parser-driver.hh index ad88efd..d5ba7ea 100644 --- a/src/parse/parser-driver.hh +++ b/src/parse/parser-driver.hh @@ -4,7 +4,7 @@ #include "parser.hh" -#include "bignum/bignum.hh" +#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead... namespace abacus::parse { diff --git a/src/parse/parser.yy b/src/parse/parser.yy index 07e3e3a..d8fbc87 100644 --- a/src/parse/parser.yy +++ b/src/parse/parser.yy @@ -36,7 +36,7 @@ namespace abacus::parse { class ParserDriver; } // namespace abacus::parse -#include "bignum/bignum.hh" +#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead... } %code provides { diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 0000000..082b746 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1 @@ +subdir('unit') diff --git a/tests/unit/bignum.cc b/tests/unit/bignum.cc index 1126a17..f584778 100644 --- a/tests/unit/bignum.cc +++ b/tests/unit/bignum.cc @@ -2,7 +2,7 @@ #include -#include "bignum/bignum.hh" +#include "bignum.hh" using namespace abacus::bignum; @@ -68,34 +68,6 @@ TEST(BigNum, comparisons_digits) { EXPECT_GT(ten, nine); } -TEST(BigNum, comparisons_negative) { - auto const zero = BigNum(0); - auto const minus_one = BigNum(-1); - auto const minus_two = BigNum(-2); - - EXPECT_LT(minus_one, zero); - EXPECT_LE(minus_one, zero); - EXPECT_LT(minus_two, minus_one); - EXPECT_LE(minus_two, minus_one); - EXPECT_LE(minus_one, minus_one); - EXPECT_GE(minus_two, minus_two); - - EXPECT_GT(zero, minus_one); - EXPECT_GE(zero, minus_one); - EXPECT_GT(minus_one, minus_two); - EXPECT_GE(minus_one, minus_two); - EXPECT_GE(minus_one, minus_one); - EXPECT_GE(minus_two, minus_two); -} - -TEST(BigNum, comparisons_digits_negative) { - auto const minus_nine = BigNum(-9); - auto const minus_ten = BigNum(-10); - - EXPECT_LT(minus_ten, minus_nine); - EXPECT_GT(minus_nine, minus_ten); -} - TEST(BigNum, unary) { auto const zero = BigNum(0); auto const one = BigNum(1); diff --git a/tests/unit/meson.build b/tests/unit/meson.build new file mode 100644 index 0000000..db8eddd --- /dev/null +++ b/tests/unit/meson.build @@ -0,0 +1,26 @@ +gtest = dependency( + 'gtest', + main: true, + required: false, +) + +if gtest.found() + unit_test_sources = files( + 'bignum.cc', + ) + + unit_tests = executable( + 'unit_tests', + sources: unit_test_sources, + dependencies: [ + bignum, + gtest, + ], + ) + + test( + 'unit tests', + unit_tests, + protocol: 'gtest', + ) +endif