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

View file

@ -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;
};
};
};
});
}

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

View file

@ -3,3 +3,7 @@ add_library(bignum STATIC
bignum.hh
)
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 <iostream>
#include <iterator>
#include <span>
#include <cassert>
#include <cmath>
@ -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;
}

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
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_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 "bignum/bignum.hh"
#include "bignum.hh" // FIXME: I would like `bignum/bignum.hh` path instead...
namespace abacus::parse {

View file

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

1
tests/meson.build Normal file
View file

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

View file

@ -2,7 +2,7 @@
#include <gtest/gtest.h>
#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);

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