Compare commits
No commits in common. "main" and "6c0950dbe15af558c2ba6fe2ad47f26d5dd44847" have entirely different histories.
main
...
6c0950dbe1
17 changed files with 211 additions and 128 deletions
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;
|
||||||
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
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…
Add table
Add a link
Reference in a new issue