2022-05-19 12:02:38 -04:00
|
|
|
|
// General numeric types for TAMER
|
2022-05-19 10:09:49 -04:00
|
|
|
|
//
|
2023-01-17 23:09:25 -05:00
|
|
|
|
// Copyright (C) 2014-2023 Ryan Specialty, LLC.
|
2022-05-19 10:09:49 -04:00
|
|
|
|
//
|
|
|
|
|
// This file is part of TAME.
|
|
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
//! General numeric types used throughout the system.
|
|
|
|
|
|
|
|
|
|
use crate::sym::{st, SymbolId};
|
|
|
|
|
|
|
|
|
|
/// Value dimensionality.
|
|
|
|
|
///
|
|
|
|
|
/// This indicates the number of subscripts needed to access a scalar
|
|
|
|
|
/// value.
|
|
|
|
|
/// This the value
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
#[repr(u8)]
|
|
|
|
|
pub enum Dim {
|
|
|
|
|
Scalar = 0,
|
|
|
|
|
Vector = 1,
|
|
|
|
|
Matrix = 2,
|
|
|
|
|
}
|
|
|
|
|
|
tamer: Initial concept for AIR/ASG Expr
This begins to place expressions on the graph---something that I've been
thinking about for a couple of years now, so it's interesting to finally be
doing it.
This is going to evolve; I want to get some things committed so that it's
clear how I'm moving forward. The ASG makes things a bit awkward for a
number of reasons:
1. I'm dealing with older code where I had a different model of doing
things;
2. It's mutable, rather than the mostly-functional lowering pipeline;
3. We're dealing with an aggregate ever-evolving blob of data (the graph)
rather than a stream of tokens; and
4. We don't have as many type guarantees.
I've shown with the lowering pipeline that I'm able to take a mutable
reference and convert it into something that's both functional and
performant, where I remove it from its container (an `Option`), create a new
version of it, and place it back. Rust is able to optimize away the memcpys
and such and just directly manipulate the underlying value, which is often a
register with all of the inlining.
_But_ this is a different scenario now. The lowering pipeline has a narrow
context. The graph has to keep hitting memory. So we'll see how this
goes. But it's most important to get this working and measure how it
performs; I'm not trying to prematurely optimize. My attempts right now are
for the way that I wish to develop.
Speaking to #4 above, it also sucks that I'm not able to type the
relationships between nodes on the graph. Rather, it's not that I _can't_,
but a project to created a typed graph library is beyond the scope of this
work and would take far too much time. I'll leave that to a personal,
non-work project. Instead, I'm going to have to narrow the type any time
the graph is accessed. And while that sucks, I'm going to do my best to
encapsulate those details to make it as seamless as possible API-wise. The
performance hit of performing the narrowing I'm hoping will be very small
relative to all the business logic going on (a single cache miss is bound to
be far more expensive than many narrowings which are just integer
comparisons and branching)...but we'll see. Introducing branching sucks,
but branch prediction is pretty damn good in modern CPUs.
DEV-13160
2022-12-21 16:47:04 -05:00
|
|
|
|
assert_eq_size!(Option<Dim>, Dim);
|
|
|
|
|
|
2022-05-19 10:09:49 -04:00
|
|
|
|
impl From<Dim> for u8 {
|
|
|
|
|
fn from(dim: Dim) -> Self {
|
|
|
|
|
dim as u8
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Dim> for SymbolId {
|
|
|
|
|
fn from(dim: Dim) -> Self {
|
|
|
|
|
st::decimal1(dim as u8).as_sym()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Dim {
|
|
|
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
|
(*self as u8).fmt(fmt)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Machine representation of scalar data.
|
|
|
|
|
///
|
|
|
|
|
/// _NB: This was not enforced by the XSLT-based compiler._
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
|
|
|
|
pub enum Dtype {
|
|
|
|
|
/// {⊥,⊤} = {0,1} ⊂ ℤ
|
|
|
|
|
Boolean,
|
|
|
|
|
/// ℤ
|
|
|
|
|
Integer,
|
|
|
|
|
/// ℝ
|
|
|
|
|
Float,
|
|
|
|
|
/// ∅
|
|
|
|
|
Empty,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Dtype {
|
|
|
|
|
pub fn as_sym(&self) -> SymbolId {
|
|
|
|
|
match self {
|
|
|
|
|
Dtype::Boolean => st::L_BOOLEAN,
|
|
|
|
|
Dtype::Integer => st::L_INTEGER,
|
|
|
|
|
Dtype::Float => st::L_FLOAT,
|
|
|
|
|
Dtype::Empty => st::L_EMPTY,
|
|
|
|
|
}
|
|
|
|
|
.as_sym()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
tamer: Integrate clippy
This invokes clippy as part of `make check` now, which I had previously
avoided doing (I'll elaborate on that below).
This commit represents the changes needed to resolve all the warnings
presented by clippy. Many changes have been made where I find the lints to
be useful and agreeable, but there are a number of lints, rationalized in
`src/lib.rs`, where I found the lints to be disagreeable. I have provided
rationale, primarily for those wondering why I desire to deviate from the
default lints, though it does feel backward to rationalize why certain lints
ought to be applied (the reverse should be true).
With that said, this did catch some legitimage issues, and it was also
helpful in getting some older code up-to-date with new language additions
that perhaps I used in new code but hadn't gone back and updated old code
for. My goal was to get clippy working without errors so that, in the
future, when others get into TAMER and are still getting used to Rust,
clippy is able to help guide them in the right direction.
One of the reasons I went without clippy for so long (though I admittedly
forgot I wasn't using it for a period of time) was because there were a
number of suggestions that I found disagreeable, and I didn't take the time
to go through them and determine what I wanted to follow. Furthermore, it
was hard to make that judgment when I was new to the language and lacked
the necessary experience to do so.
One thing I would like to comment further on is the use of `format!` with
`expect`, which is also what the diagnostic system convenience methods
do (which clippy does not cover). Because of all the work I've done trying
to understand Rust and looking at disassemblies and seeing what it
optimizes, I falsely assumed that Rust would convert such things into
conditionals in my otherwise-pure code...but apparently that's not the case,
when `format!` is involved.
I noticed that, after making the suggested fix with `get_ident`, Rust
proceeded to then inline it into each call site and then apply further
optimizations. It was also previously invoking the thread lock (for the
interner) unconditionally and invoking the `Display` implementation. That
is not at all what I intended for, despite knowing the eager semantics of
function calls in Rust.
Anyway, possibly more to come on that, I'm just tired of typing and need to
move on. I'll be returning to investigate further diagnostic messages soon.
2023-01-12 10:46:48 -05:00
|
|
|
|
impl From<Dtype> for SymbolId {
|
|
|
|
|
fn from(val: Dtype) -> Self {
|
|
|
|
|
val.as_sym()
|
2022-05-19 10:09:49 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Dtype {
|
|
|
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
|
write!(fmt, "{}", self.as_sym())
|
|
|
|
|
}
|
|
|
|
|
}
|