Compare commits

..

No commits in common. "main" and "6c0950dbe15af558c2ba6fe2ad47f26d5dd44847" have entirely different histories.

17 changed files with 211 additions and 128 deletions

27
.drone.yml Normal file
View file

@ -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
...

View file

@ -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

View file

@ -4,15 +4,12 @@ enable_testing()
add_library(common_options INTERFACE) add_library(common_options INTERFACE)
target_compile_features(common_options INTERFACE target_compile_features(common_options INTERFACE
cxx_std_20 cxx_std_17
) )
target_compile_options(common_options INTERFACE target_compile_options(common_options INTERFACE
-Wall -Wall
-Wextra -Wextra
) )
target_include_directories(common_options INTERFACE
src
)
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(tests) add_subdirectory(tests)

View file

@ -29,40 +29,9 @@
}; };
outputs = { self, futils, nixpkgs, pre-commit-hooks }: outputs = { self, futils, nixpkgs, pre-commit-hooks }:
{ futils.lib.eachDefaultSystem (system:
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:
let let
pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; }; pkgs = import nixpkgs { inherit system; };
in in
{ {
checks = { checks = {
@ -87,17 +56,46 @@
}; };
}; };
devShells.default = pkgs.mkShell { defaultPackage = self.packages.${system}.abacus;
inputsFrom = with self.packages.${system}; [
abacus devShell = pkgs.mkShell {
]; inherit (self.defaultPackage.${system})
checkInputs
nativeBuildInputs
;
inherit (self.checks.${system}.pre-commit) shellHook; inherit (self.checks.${system}.pre-commit) shellHook;
}; };
packages = futils.lib.flattenTree { packages = futils.lib.flattenTree {
inherit (pkgs) abacus; abacus = pkgs.stdenv.mkDerivation {
default = pkgs.abacus; 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;
};
};
}; };
}); });
} }

13
meson.build Normal file
View file

@ -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')

View file

@ -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() { int main() {
abacus::parse::ParserDriver driver{}; abacus::parse::ParserDriver driver{};

View file

@ -3,3 +3,7 @@ add_library(bignum STATIC
bignum.hh bignum.hh
) )
target_link_libraries(bignum PRIVATE common_options) target_link_libraries(bignum PRIVATE common_options)
target_include_directories(bignum PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

View file

@ -3,7 +3,6 @@
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
#include <span>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
@ -83,17 +82,18 @@ digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
++it2; ++it2;
} }
auto leftover = [=]() { auto it = it1;
if (it1 != end1) { auto end = end1;
return std::span(it1, end1); if (it1 == end1) {
} it = it2;
return std::span(it2, end2); end = end2;
}(); }
for (auto value : leftover) { while (it != end) {
int addition = value + carry; int addition = *it + carry;
carry = addition / BASE; carry = addition / BASE;
res.push_back(addition % BASE); res.push_back(addition % BASE);
++it;
} }
if (carry != 0) { 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)); assert(!do_less_than(lhs, rhs));
digits_type complement; 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), std::transform(lhs.begin(), lhs.end(), std::back_inserter(complement),
take_complement); take_complement);
@ -363,11 +363,7 @@ bool BigNum::less_than(BigNum const& rhs) const {
return sign_ < rhs.sign_; return sign_ < rhs.sign_;
} }
if (is_positive()) { return do_less_than(digits_, rhs.digits_);
return do_less_than(digits_, rhs.digits_);
} else {
return do_less_than(rhs.digits_, digits_);
}
} }
void BigNum::canonicalize() { void BigNum::canonicalize() {
@ -385,15 +381,15 @@ bool BigNum::is_canonicalized() const {
return sign_ == 0; return sign_ == 0;
} }
// `back` is valid since there is at least one element auto const leading_zeros = std::find_if(digits_.rbegin(), digits_.rend(),
auto const has_leading_zero = digits_.back() == 0; [](auto v) { return v != 0; });
if (has_leading_zero) { if (leading_zeros != digits_.rbegin()) {
return false; return false;
} }
auto const has_overflow = std::any_of(digits_.begin(), digits_.end(), auto const overflow = std::find_if(digits_.begin(), digits_.end(),
[](auto v) { return v >= BASE; }); [](auto v) { return v >= BASE; });
if (has_overflow) { if (overflow != digits_.end()) {
return false; return false;
} }

16
src/bignum/meson.build Normal file
View file

@ -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,
)

16
src/meson.build Normal file
View file

@ -0,0 +1,16 @@
abacus_sources = files(
'abacus.cc',
)
subdir('bignum')
subdir('parse')
abacus = executable(
'abacus',
sources: abacus_sources,
dependencies: [
bignum,
parse,
],
install: true,
)

View file

@ -18,6 +18,6 @@ target_link_libraries(parse PRIVATE
) )
target_include_directories(parse PUBLIC target_include_directories(parse PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
) )

48
src/parse/meson.build Normal file
View file

@ -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,
)

View file

@ -4,7 +4,7 @@
#include "parser.hh" #include "parser.hh"
#include "bignum/bignum.hh" #include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
namespace abacus::parse { namespace abacus::parse {

View file

@ -36,7 +36,7 @@ namespace abacus::parse {
class ParserDriver; class ParserDriver;
} // namespace abacus::parse } // namespace abacus::parse
#include "bignum/bignum.hh" #include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
} }
%code provides { %code provides {

1
tests/meson.build Normal file
View file

@ -0,0 +1 @@
subdir('unit')

View file

@ -2,7 +2,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "bignum/bignum.hh" #include "bignum.hh"
using namespace abacus::bignum; using namespace abacus::bignum;
@ -68,34 +68,6 @@ TEST(BigNum, comparisons_digits) {
EXPECT_GT(ten, nine); 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) { TEST(BigNum, unary) {
auto const zero = BigNum(0); auto const zero = BigNum(0);
auto const one = BigNum(1); auto const one = BigNum(1);

26
tests/unit/meson.build Normal file
View file

@ -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