Skip to content

Commit

Permalink
fix hashmap lookups and add map formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Dec 28, 2023
1 parent 11e0fd7 commit 8443bd7
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 12 deletions.
3 changes: 2 additions & 1 deletion src/algorithm/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ impl<'a> PairMut<'a> {
}
}

trait MapItem {
pub(crate) trait MapItem {
fn num(&self) -> f64;
fn from_num(num: f64) -> Self;
fn is_empty_cell(&self) -> bool {
Expand Down Expand Up @@ -668,6 +668,7 @@ impl MapItem for Value {
}
match self {
Value::Num(arr) => arr.data[0],
Value::Box(arr) => arr.data[0].num(),
_ => 0.0,
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,13 @@ impl<T: ArrayValue> Ord for Array<T> {

impl<T: ArrayValue> Hash for Array<T> {
fn hash<H: Hasher>(&self, hasher: &mut H) {
if let Some(scalar) = self.as_scalar() {
if let Some(value) = scalar.nested_value() {
value.hash(hasher);
return;
}
}
T::TYPE_ID.hash(hasher);
self.shape.hash(hasher);
self.data.iter().for_each(|x| x.array_hash(hasher));
}
Expand Down Expand Up @@ -491,6 +498,8 @@ pub trait ArrayValue:
const NAME: &'static str;
/// A glyph indicating the type
const SYMBOL: char;
/// An ID for the type
const TYPE_ID: u8;
/// Get the fill value from the environment
fn get_fill(env: &Uiua) -> Result<Self, &'static str>;
/// Hash the value
Expand Down Expand Up @@ -521,11 +530,16 @@ pub trait ArrayValue:
fn compress_list_grid() -> bool {
false
}
/// Get a nested value
fn nested_value(&self) -> Option<&Value> {
None
}
}

impl ArrayValue for f64 {
const NAME: &'static str = "number";
const SYMBOL: char = 'ℝ';
const TYPE_ID: u8 = 0;
fn get_fill(env: &Uiua) -> Result<Self, &'static str> {
env.num_fill()
}
Expand All @@ -547,6 +561,7 @@ impl ArrayValue for f64 {
impl ArrayValue for u8 {
const NAME: &'static str = "number";
const SYMBOL: char = 'ℝ';
const TYPE_ID: u8 = 0;
fn get_fill(env: &Uiua) -> Result<Self, &'static str> {
env.byte_fill()
}
Expand All @@ -561,6 +576,7 @@ impl ArrayValue for u8 {
impl ArrayValue for char {
const NAME: &'static str = "character";
const SYMBOL: char = '@';
const TYPE_ID: u8 = 2;
fn get_fill(env: &Uiua) -> Result<Self, &'static str> {
env.char_fill()
}
Expand Down Expand Up @@ -591,6 +607,7 @@ impl ArrayValue for char {
impl ArrayValue for Boxed {
const NAME: &'static str = "box";
const SYMBOL: char = '□';
const TYPE_ID: u8 = 3;
fn get_fill(env: &Uiua) -> Result<Self, &'static str> {
env.box_fill()
}
Expand All @@ -603,11 +620,15 @@ impl ArrayValue for Boxed {
fn empty_list_inner() -> &'static str {
"□"
}
fn nested_value(&self) -> Option<&Value> {
Some(&self.0)
}
}

impl ArrayValue for Complex {
const NAME: &'static str = "complex";
const SYMBOL: char = 'ℂ';
const TYPE_ID: u8 = 1;
fn get_fill(env: &Uiua) -> Result<Self, &'static str> {
env.complex_fill()
}
Expand Down
44 changes: 39 additions & 5 deletions src/grid_fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::{
};

use crate::{
algorithm::map::{EMPTY_NAN, TOMBSTONE_NAN},
algorithm::map::{MapItem, EMPTY_NAN, TOMBSTONE_NAN},
array::{Array, ArrayValue},
boxed::Boxed,
value::Value,
Expand Down Expand Up @@ -152,10 +152,12 @@ impl GridFmt for Boxed {

impl<T: GridFmt + ArrayValue> GridFmt for Array<T> {
fn fmt_grid(&self, boxed: bool) -> Grid {
// Scalar
if self.shape.is_empty() {
return self.data[0].fmt_grid(boxed);
}
if *self.shape == [0] {
// Empty list
if self.shape == [0] {
let (left, right) = T::grid_fmt_delims(boxed);
let inner = T::empty_list_inner();
let mut row = vec![left];
Expand All @@ -164,12 +166,44 @@ impl<T: GridFmt + ArrayValue> GridFmt for Array<T> {
return vec![row];
}

// Fill the metagrid
let mut metagrid = Metagrid::new();
let mut metagrid: Option<Metagrid> = None;

// Hashmap
if self.meta().map_len.is_some() && self.shape == [2] {
if let Some((keys, values)) =
self.data[0].nested_value().zip(self.data[1].nested_value())
{
if keys.row_count() == values.row_count() {
let mut empty_entries = 0;
let metagrid = metagrid.get_or_insert_with(Metagrid::new);
for (key, value) in keys.rows().zip(values.rows()) {
if key.is_empty_cell() || key.is_tombstone() {
empty_entries += 1;
continue;
}
let key = key.fmt_grid(false);
let value = value.fmt_grid(false);
metagrid.push(vec![key, vec![vec![' ', '→', ' ']], value]);
}
if empty_entries > 0 {
metagrid.push(vec![vec![format!("… {empty_entries} empty")
.chars()
.collect()]])
}
}
}
}

// Default array formatting
let mut metagrid = metagrid.unwrap_or_else(|| {
let mut metagrid = Metagrid::new();
fmt_array(&self.shape, &self.data, &mut metagrid);
metagrid
});

// Synthesize a grid from the metagrid
let mut grid: Grid = Grid::new();

fmt_array(&self.shape, &self.data, &mut metagrid);
// Determine max row heights and column widths
let metagrid_width = metagrid.iter().map(|row| row.len()).max().unwrap();
let metagrid_height = metagrid.len();
Expand Down
11 changes: 5 additions & 6 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ impl Value {
}
pub(crate) fn type_id(&self) -> u8 {
match self {
Self::Num(_) => 0,
Self::Num(_) => f64::TYPE_ID,
#[cfg(feature = "bytes")]
Self::Byte(_) => 0,
Self::Complex(_) => 1,
Self::Char(_) => 2,
Self::Box(_) => 3,
Self::Byte(_) => u8::TYPE_ID,
Self::Complex(_) => Complex::TYPE_ID,
Self::Char(_) => char::TYPE_ID,
Self::Box(_) => Boxed::TYPE_ID,
}
}
/// Get a reference to a possible number array
Expand Down Expand Up @@ -1564,7 +1564,6 @@ impl Ord for Value {

impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
self.type_id().hash(state);
match self {
Value::Num(arr) => arr.hash(state),
#[cfg(feature = "bytes")]
Expand Down

0 comments on commit 8443bd7

Please sign in to comment.