Mike Gerwitz
a9d0f43684
This introduces, but does not yet integrate, `CanonicalName`, which not only represents canonicalized package names, but handles namespec resolution. The term "namespec" is motivated by Git's use of *spec (e.g. refspec) referring to various ways of specifying a particular object. Names look like paths, and are derived from them, but they _are not paths_. Their resolution is a purely lexical operation, and they include a number of restrictions to simplify their clarity and handling. I expect them to evolve more in the future, and I've had ideas to do so for quite some time. In particular, resolving packages in this way and then loading the from the filesystem relative to the project root will ensure that traversing (conceptually) to a parent directory will not operate unintuitively with symlinks. The path will always resolve unambigiously. (With that said, if the symlink is to a shared directory with different directory structures, that doesn't solve the compilation problem---we'll have to move object files into a project-specific build directory to handle that.) Span Slicing ------------ Okay, it's worth commenting on the horridity of the path name slicing that goes on here. Care has been taken to ensure that spans will be able to be properly sliced in all relevant contexts, and there are plenty of words devoted to that in the documentation committed here. But there is a more fundamental problem here that I regret not having solved earlier, because I don't have the time for it right now: while we do have SPair, it makes no guarantees that the span associated with the corresponding SymbolId is actually the span that matches the original source lexeme. In fact, it's often not. This is a problem when we want to slice up a symbol in an SPair and produce a sensible span. If it _is_ a source lexeme with its original span, that's no problem. But if it's _not_, then the two are not in sync, and slicing up the span won't produce something that actually makes sense to the user. Or, worse (or maybe it's not worse?), it may cause a panic if the slicing is out of bounds. The solution in the future might be to store explicitly the state of an SPair, or call it Lexeme, or something, so that we know the conditions under which slicing is safe. If I ever have time for that in this project. But the result of the lack of a proper abstraction really shows here: this is some of the most confusing code in TAMER, and it's really not doing anything all that complicated. It is disproportionately confusing. DEV-13162 |
||
---|---|---|
.. | ||
benches | ||
build-aux | ||
src | ||
tests | ||
.gitignore | ||
Cargo.lock | ||
Cargo.toml | ||
Makefile.am | ||
README.md | ||
autogen.sh | ||
bootstrap | ||
conf.sh.in | ||
configure.ac | ||
rustfmt.toml |
README.md
TAME in Rust (TAMER)
TAME was written to help tame the complexity of developing comparative insurance rating systems. This project aims to tame the complexity and performance issues of TAME itself. TAMER is therefore more tame than TAME.
TAME was originally written in XSLT. For more information about the
project, see the parent README.md
.
Building
To bootstrap from the source repository, run ./bootstrap
.
To configure the build for your system, run ./configure
. To build, run
make
. To run tests, run make check
.
You may also invoke cargo
directly, which make
will do for you using
options provided to configure
.
Note that the default development build results in terrible runtime performance! See [#Build Flags][] below for instructions on how to generate a release binary.
Build Flags
The environment variable CARGO_BUILD_FLAGS
can be used to provide
additional arguments to cargo build
when invoked via make
. This can be
provided optionally during configure
and can be overridden when invoking
make
. For example:
# release build
$ ./configure && make CARGO_BUILD_FLAGS=--release
$ ./configure CARGO_BUILD_FLAGS=--release && make
# dev build
$ ./configure && make
$ ./configure CARGO_BUILD_FLAGS=--release && make CARGO_BUILD_FLAGS=
Hacking
This section contains advice for those developing TAMER.
Running Tests
Developers should be using test-driven development (TDD). make check
will
run all necessary tests.
Code Format
Rust provides rustfmt
that can automatically format code for you. This
project mandates its use and therefore eliminates personal preference in
code style (for better or worse).
Formatting checks are run during make check
and, on failure, will output
the diff that would be applied if you ran make fmt
(or make fix
); this
will run cargo fmt
for you (and will use the binaries configured via
configure
).
Since developers should be doing test-driven development (TDD) and therefore
should be running make check
frequently, the hope is that frequent
feedback on formatting issues will allow developers to quickly adjust their
habits to avoid triggering formatting errors at all.
If you want to automatically fix formatting errors and then run tests:
$ make fmt check
Benchmarking
Benchmarks serve two purposes: external integration tests (which are subject
to module visibility constraints) and actual benchmarking. To run
benchmarks, invoke make bench
.
Note that link-time optimizations (LTO) are performed on the binary for benchmarking so that its performance reflects release builds that will be used in production.
The configure
script will automatically detect whether the test
feature
is unstable (as it was as of the time of writing) and, if so, will
automatically fall back to invoking nightly (by running cargo +nightly bench
).
If you do not have nightly, run you install it via rustup install nightly
.