Skip to content

Commit

Permalink
excise AlgebraicType/Value::Map
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Sep 30, 2024
1 parent 661988d commit d668005
Show file tree
Hide file tree
Showing 40 changed files with 34 additions and 857 deletions.
8 changes: 0 additions & 8 deletions crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,13 @@ public partial struct AggregateElement(string? name, AlgebraicType algebraicType
public AlgebraicType AlgebraicType = algebraicType;
}

[SpacetimeDB.Type]
public partial struct MapElement(AlgebraicType key, AlgebraicType value)
{
public AlgebraicType Key = key;
public AlgebraicType Value = value;
}

[SpacetimeDB.Type]
public partial record AlgebraicType
: SpacetimeDB.TaggedEnum<(
int Ref,
AggregateElement[] Sum,
AggregateElement[] Product,
AlgebraicType Array,
MapElement Map,
Unit String,
Unit Bool,
Unit I8,
Expand Down
35 changes: 0 additions & 35 deletions crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,38 +438,3 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) =>
public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) =>
enumerable.GetAlgebraicType(registrar);
}

public readonly struct Dictionary<Key, Value, KeyRW, ValueRW> : IReadWrite<Dictionary<Key, Value>>
where Key : notnull
where KeyRW : IReadWrite<Key>, new()
where ValueRW : IReadWrite<Value>, new()
{
private static readonly KeyRW keyRW = new();
private static readonly ValueRW valueRW = new();

public Dictionary<Key, Value> Read(BinaryReader reader)
{
var count = reader.ReadInt32();
var result = new Dictionary<Key, Value>(count);
for (var i = 0; i < count; i++)
{
result.Add(keyRW.Read(reader), valueRW.Read(reader));
}
return result;
}

public void Write(BinaryWriter writer, Dictionary<Key, Value> value)
{
writer.Write(value.Count);
foreach (var (key, val) in value)
{
keyRW.Write(writer, key);
valueRW.Write(writer, val);
}
}

public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) =>
new AlgebraicType.Map(
new(keyRW.GetAlgebraicType(registrar), valueRW.GetAlgebraicType(registrar))
);
}
7 changes: 0 additions & 7 deletions crates/cli/src/subcommands/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,6 @@ mod write_type {
write_type(ctx, out, elem_ty)?;
write!(out, ">")?;
}
AlgebraicType::Map(ty) => {
write!(out, "Map<")?;
write_type(ctx, out, &ty.key_ty)?;
write!(out, ", ")?;
write_type(ctx, out, &ty.ty)?;
write!(out, ">")?;
}
AlgebraicType::Ref(r) => {
write!(out, "{}", ctx(*r))?;
}
Expand Down
18 changes: 4 additions & 14 deletions crates/cli/src/subcommands/generate/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ fn scalar_or_string_name(b: &AlgebraicType) -> Option<&str> {
AlgebraicType::String => "string",
AlgebraicType::F32 => "float",
AlgebraicType::F64 => "double",
AlgebraicType::Ref(_)
| AlgebraicType::Sum(_)
| AlgebraicType::Product(_)
| AlgebraicType::Array(_)
| AlgebraicType::Map(_) => return None,
AlgebraicType::Ref(_) | AlgebraicType::Sum(_) | AlgebraicType::Product(_) | AlgebraicType::Array(_) => {
return None
}
})
}

Expand All @@ -62,14 +60,6 @@ fn ty_fmt<'a>(ctx: &'a GenCtx, ty: &'a AlgebraicType, namespace: &'a str) -> imp
ty_fmt(ctx, elem_ty, namespace)
)
}
AlgebraicType::Map(ty) => {
write!(
f,
"System.Collections.Generic.Dictionary<{}, {}>",
ty_fmt(ctx, &ty.ty, namespace),
ty_fmt(ctx, &ty.key_ty, namespace)
)
}
AlgebraicType::Ref(r) => {
let name = csharp_typename(ctx, *r);
match &ctx.typespace[*r] {
Expand Down Expand Up @@ -105,7 +95,7 @@ fn default_init(ctx: &GenCtx, ty: &AlgebraicType) -> Option<&'static str> {
// Byte arrays must be initialized to an empty array.
ty if ty.is_bytes() => Some("Array.Empty<byte>()"),
// For product types, arrays, and maps, we can use the default constructor.
AlgebraicType::Product(_) | AlgebraicType::Array(_) | AlgebraicType::Map(_) => Some("new()"),
AlgebraicType::Product(_) | AlgebraicType::Array(_) => Some("new()"),
// Strings must have explicit default value of "".
AlgebraicType::String => Some(r#""""#),
AlgebraicType::Ref(r) => default_init(ctx, &ctx.typespace[*r]),
Expand Down
1 change: 0 additions & 1 deletion crates/cli/src/subcommands/generate/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,6 @@ pub fn write_type<W: Write>(module: &ModuleDef, out: &mut W, ty: &AlgebraicTypeU
write_type(module, out, elem_ty)?;
write!(out, ">")?;
}
AlgebraicTypeUse::Map { .. } => unimplemented!("AlgebraicType::Map is unsupported and will be removed"),
AlgebraicTypeUse::Ref(r) => {
write!(out, "{}", type_ref_name(module, *r))?;
}
Expand Down
22 changes: 2 additions & 20 deletions crates/cli/src/subcommands/generate/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ fn ty_fmt<'a>(ctx: &'a GenCtx, ty: &'a AlgebraicType, ref_prefix: &'a str) -> im
AlgebraicType::Product(_) => unimplemented!(),
ty if ty.is_bytes() => f.write_str("Uint8Array"),
AlgebraicType::Array(ty) => write!(f, "{}[]", ty_fmt(ctx, &ty.elem_ty, ref_prefix)),
AlgebraicType::Map(ty) => {
write!(
f,
"Map<{}, {}>",
ty_fmt(ctx, &ty.ty, ref_prefix),
ty_fmt(ctx, &ty.key_ty, ref_prefix)
)
}
AlgebraicType::Ref(r) => write!(f, "{}{}", ref_prefix, typescript_typename(ctx, *r)),
ty => f.write_str(scalar_or_string_to_ts(ty).unwrap().0),
})
Expand Down Expand Up @@ -117,7 +109,6 @@ fn convert_type<'a>(
let el_conv = convert_type(ctx, elem_ty, "el", ref_prefix);
writeln!(f, "{value}.asArray().map(el => {el_conv}) as {typescript_type}[];")
}
AlgebraicType::Map(_) => todo!(),
AlgebraicType::Ref(r) => {
let name = typescript_typename(ctx, *r);
write!(f, "{ref_prefix}{name}.fromValue({value})")
Expand Down Expand Up @@ -158,7 +149,6 @@ fn convert_algebraic_type<'a>(ctx: &'a GenCtx, ty: &'a AlgebraicType, ref_prefix
"AlgebraicType.createArrayType({})",
convert_algebraic_type(ctx, &ty.elem_ty, ref_prefix)
),
AlgebraicType::Map(_) => todo!(),
AlgebraicType::Ref(r) => write!(f, "{ref_prefix}{}.getAlgebraicType()", typescript_typename(ctx, *r)),
ty => write!(f, "AlgebraicType.create{ty:?}Type()"),
})
Expand Down Expand Up @@ -243,7 +233,7 @@ fn serialize_type<'a>(
}
ty if ty.is_bytes() => write!(f, "Array.from({value})"),
AlgebraicType::Array(ArrayType { elem_ty }) => match &**elem_ty {
ty if ty.is_scalar_or_string() || ty.is_map() => write!(f, "{value}"),
ty if ty.is_scalar_or_string() => write!(f, "{value}"),
t => write!(f, "{value}.map(el => {})", serialize_type(ctx, t, "el", prefix)),
},
_ => write!(f, "{value}"),
Expand Down Expand Up @@ -530,10 +520,6 @@ fn generate_imports_variants(
fn _generate_imports(ctx: &GenCtx, ty: &AlgebraicType, imports: &mut Vec<String>, prefix: Option<&str>) {
match ty {
AlgebraicType::Array(ty) => _generate_imports(ctx, &ty.elem_ty, imports, prefix),
AlgebraicType::Map(map_type) => {
_generate_imports(ctx, &map_type.key_ty, imports, prefix);
_generate_imports(ctx, &map_type.ty, imports, prefix);
}
AlgebraicType::Ref(r) => {
let class_name = typescript_typename(ctx, *r).to_string();
let filename = typescript_filename(ctx, *r);
Expand Down Expand Up @@ -779,11 +765,7 @@ fn autogen_typescript_access_funcs_for_struct(
let typescript_field_type = match field_type {
ty if ty.is_identity() => "Identity",
ty if ty.is_address() => "Address",
AlgebraicType::Product(_)
| AlgebraicType::Ref(_)
| AlgebraicType::Sum(_)
| AlgebraicType::Array(_)
| AlgebraicType::Map(_) => {
AlgebraicType::Product(_) | AlgebraicType::Ref(_) | AlgebraicType::Sum(_) | AlgebraicType::Array(_) => {
// TODO: We don't allow filtering on enums, tuples, arrays, and maps right now.
// Its possible we may consider it for the future.
continue;
Expand Down
18 changes: 1 addition & 17 deletions crates/sats/src/algebraic_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use crate::meta_type::MetaType;
use crate::product_type::{ADDRESS_TAG, IDENTITY_TAG};
use crate::sum_type::{OPTION_NONE_TAG, OPTION_SOME_TAG};
use crate::{i256, u256};
use crate::{
AlgebraicTypeRef, AlgebraicValue, ArrayType, MapType, ProductType, SpacetimeType, SumType, SumTypeVariant,
};
use crate::{AlgebraicTypeRef, AlgebraicValue, ArrayType, ProductType, SpacetimeType, SumType, SumTypeVariant};
use derive_more::From;
use enum_as_inner::EnumAsInner;

Expand Down Expand Up @@ -81,10 +79,6 @@ pub enum AlgebraicType {
/// The type of array values where elements are of a base type `elem_ty`.
/// Values [`AlgebraicValue::Array(array)`](crate::AlgebraicValue::Array) will have this type.
Array(ArrayType),
/// The type of map values consisting of a key type `key_ty` and value `ty`.
/// Values [`AlgebraicValue::Map(map)`](crate::AlgebraicValue::Map) will have this type.
/// The order of entries in a map value is observable.
Map(Box<MapType>),
/// The UTF-8 encoded `String` type.
/// Values [`AlgebraicValue::String(s)`](crate::AlgebraicValue::String) will have this type.
///
Expand Down Expand Up @@ -135,7 +129,6 @@ impl MetaType for AlgebraicType {
("sum", SumType::meta_type()),
("product", ProductType::meta_type()),
("array", ArrayType::meta_type()),
("map", MapType::meta_type()),
("string", AlgebraicType::unit()),
("bool", AlgebraicType::unit()),
("i8", AlgebraicType::unit()),
Expand Down Expand Up @@ -272,7 +265,6 @@ impl AlgebraicType {
variants.iter().any(|variant| variant.algebraic_type.contains_refs())
}
AlgebraicType::Array(array) => array.elem_ty.contains_refs(),
AlgebraicType::Map(map) => map.key_ty.contains_refs() || map.ty.contains_refs(),
_ => false,
}
}
Expand All @@ -297,11 +289,6 @@ impl AlgebraicType {
ArrayType { elem_ty: Box::new(ty) }.into()
}

/// Returns a map type from the type `key` to the type `value`.
pub fn map(key: Self, value: Self) -> Self {
MapType::new(key, value).into()
}

/// Construct a copy of the `Identity` type.
pub fn identity() -> Self {
AlgebraicType::product([(IDENTITY_TAG, AlgebraicType::bytes())])
Expand Down Expand Up @@ -428,9 +415,6 @@ impl AlgebraicType {
}
AlgebraicType::Product(product) => product.is_special() || product.is_unit(),
AlgebraicType::Array(array) => array.elem_ty.is_valid_for_client_type_use(),
AlgebraicType::Map(map) => {
map.key_ty.is_valid_for_client_type_use() && map.ty.is_valid_for_client_type_use()
}
AlgebraicType::Ref(_) => true,
_ => true,
}
Expand Down
1 change: 0 additions & 1 deletion crates/sats/src/algebraic_type/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub fn fmt_algebraic_type(ty: &AlgebraicType) -> impl '_ + Display {
AlgebraicType::Sum(ty) => write!(f, "{}", fmt_sum_type(ty)),
AlgebraicType::Product(ty) => write!(f, "{}", fmt_product_type(ty)),
AlgebraicType::Array(a) => write!(f, "Array<{}>", fmt(&a.elem_ty)),
AlgebraicType::Map(m) => write!(f, "Map<{}, {}>", fmt(&m.key_ty), fmt(&m.ty)),
AlgebraicType::Bool => write!(f, "Bool"),
AlgebraicType::I8 => write!(f, "I8"),
AlgebraicType::U8 => write!(f, "U8"),
Expand Down
1 change: 0 additions & 1 deletion crates/sats/src/algebraic_type/map_notation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub fn fmt_algebraic_type(ty: &AlgebraicType) -> impl '_ + fmt::Display {
write!(f, " }}")
}
AlgebraicType::Array(ty) => write!(f, "{{ ty_: Array, 0: {} }}", fmt(&ty.elem_ty)),
AlgebraicType::Map(map) => write!(f, "{{ ty_: Map, 0: {}, 1: {} }}", fmt(&map.key_ty), fmt(&map.ty)),
AlgebraicType::Bool => write!(f, "{{ ty_: Bool }}"),
AlgebraicType::I8 => write!(f, "{{ ty_: I8 }}"),
AlgebraicType::U8 => write!(f, "{{ ty_: U8 }}"),
Expand Down
53 changes: 1 addition & 52 deletions crates/sats/src/algebraic_value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod de;
pub mod ser;

use crate::{AlgebraicType, ArrayValue, MapValue, ProductValue, SumValue};
use crate::{AlgebraicType, ArrayValue, ProductValue, SumValue};
use core::mem;
use core::ops::{Bound, RangeBounds};
use derive_more::From;
Expand Down Expand Up @@ -53,25 +53,6 @@ pub enum AlgebraicValue {
/// The contained values are stored packed in a representation appropriate for their type.
/// See [`ArrayValue`] for details on the representation.
Array(ArrayValue),
/// An ordered map value of `key: AlgebraicValue`s mapped to `value: AlgebraicValue`s.
/// Each `key` must be of the same [`AlgebraicType`] as all the others
/// and the same applies to each `value`.
/// A map as a whole has the type [`AlgebraicType::Map(key_ty, val_ty)`].
///
/// Maps are implemented internally as [`BTreeMap<AlgebraicValue, AlgebraicValue>`].
/// This implies that key/values are ordered first by key and then value
/// as if they were a sorted slice `[(key, value)]`.
/// This order is observable as maps are exposed both directly
/// and indirectly via `Ord for `[`AlgebraicValue`].
/// The latter lets us observe that e.g., `{ a: 42 } < { b: 42 }`.
/// However, we cannot observe any difference between `{ a: 0, b: 0 }` and `{ b: 0, a: 0 }`,
/// as the natural order is used as opposed to insertion order.
/// Where insertion order is relevant,
/// a [`AlgebraicValue::Array`] with `(key, value)` pairs can be used instead.
///
/// We box the `MapValue` to reduce size
/// and because we assume that map values will be uncommon.
Map(Box<MapValue>),
/// A [`bool`] value of type [`AlgebraicType::Bool`].
Bool(bool),
/// An [`i8`] value of type [`AlgebraicType::I8`].
Expand Down Expand Up @@ -213,11 +194,6 @@ impl AlgebraicValue {
Self::Product(elements.into())
}

/// Returns an [`AlgebraicValue`] representing a map value defined by the given `map`.
pub fn map(map: MapValue) -> Self {
Self::Map(Box::new(map))
}

/// Returns the [`AlgebraicType`] of the product value `x`.
pub(crate) fn type_of_product(x: &ProductValue) -> Option<AlgebraicType> {
let mut elems = Vec::with_capacity(x.elements.len());
Expand All @@ -227,12 +203,6 @@ impl AlgebraicValue {
Some(AlgebraicType::product(elems.into_boxed_slice()))
}

/// Returns the [`AlgebraicType`] of the map with key type `k` and value type `v`.
pub(crate) fn type_of_map(val: &MapValue) -> Option<AlgebraicType> {
let (k, v) = val.first_key_value().and_then(|(k, v)| k.type_of().zip(v.type_of()))?;
Some(AlgebraicType::product([k, v]))
}

/// Infer the [`AlgebraicType`] of an [`AlgebraicValue`].
///
/// This function is partial
Expand All @@ -254,7 +224,6 @@ impl AlgebraicValue {
Self::Sum(_) => None,
Self::Product(x) => Self::type_of_product(x),
Self::Array(x) => x.type_of().map(Into::into),
Self::Map(x) => Self::type_of_map(x),
Self::Bool(_) => Some(AlgebraicType::Bool),
Self::I8(_) => Some(AlgebraicType::I8),
Self::U8(_) => Some(AlgebraicType::U8),
Expand Down Expand Up @@ -352,8 +321,6 @@ impl RangeBounds<AlgebraicValue> for AlgebraicValue {

#[cfg(test)]
mod tests {
use std::collections::BTreeMap;

use crate::satn::Satn;
use crate::{AlgebraicType, AlgebraicValue, ArrayValue, Typespace, ValueWithType, WithTypespace};

Expand Down Expand Up @@ -411,22 +378,4 @@ mod tests {
let typespace = Typespace::new(vec![]);
assert_eq!(in_space(&typespace, &array, &value).to_satn(), "0x03");
}

#[test]
fn map() {
let map = AlgebraicType::map(AlgebraicType::U8, AlgebraicType::U8);
let value = AlgebraicValue::map(BTreeMap::new());
let typespace = Typespace::new(vec![]);
assert_eq!(in_space(&typespace, &map, &value).to_satn(), "[:]");
}

#[test]
fn map_of_values() {
let map = AlgebraicType::map(AlgebraicType::U8, AlgebraicType::U8);
let mut val = BTreeMap::<AlgebraicValue, AlgebraicValue>::new();
val.insert(AlgebraicValue::U8(2), AlgebraicValue::U8(3));
let value = AlgebraicValue::map(val);
let typespace = Typespace::new(vec![]);
assert_eq!(in_space(&typespace, &map, &value).to_satn(), "[2: 3]");
}
}
Loading

0 comments on commit d668005

Please sign in to comment.