Compare commits
No commits in common. "main" and "6c0950dbe15af558c2ba6fe2ad47f26d5dd44847" have entirely different histories.
main
...
6c0950dbe1
27
.drone.yml
Normal file
27
.drone.yml
Normal 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
|
||||||
|
...
|
|
@ -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
|
|
|
@ -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)
|
||||||
|
|
76
flake.nix
76
flake.nix
|
@ -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
13
meson.build
Normal 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')
|
|
@ -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{};
|
||||||
|
|
|
@ -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}>
|
||||||
|
)
|
||||||
|
|
|
@ -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;
|
||||||
|
end = end2;
|
||||||
}
|
}
|
||||||
return std::span(it2, 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
16
src/bignum/meson.build
Normal 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
16
src/meson.build
Normal 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,
|
||||||
|
)
|
|
@ -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
48
src/parse/meson.build
Normal 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,
|
||||||
|
)
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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
1
tests/meson.build
Normal file
|
@ -0,0 +1 @@
|
||||||
|
subdir('unit')
|
|
@ -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
26
tests/unit/meson.build
Normal 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
|
Loading…
Reference in a new issue