From 97fa6083f244ceefec88fdd53774062b78a67434 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Oct 2023 13:30:34 +0200 Subject: [PATCH] sats: misc refactoring - prepare for getting rid of BuiltinValue & BuiltinType - prepare for slim slices --- crates/bench/benches/generic.rs | 8 +- crates/bench/src/schemas.rs | 56 +--- crates/bench/src/spacetime_module.rs | 18 +- crates/bench/src/spacetime_raw.rs | 11 +- crates/bench/src/sqlite.rs | 18 +- crates/bindings-macro/src/module.rs | 36 ++- crates/bindings/src/rt.rs | 2 +- .../db/datastore/locking_tx_datastore/mod.rs | 272 +++++------------- crates/core/src/db/relational_db.rs | 22 +- crates/core/src/sql/execute.rs | 16 +- crates/core/src/subscription/query.rs | 8 +- crates/core/src/vm.rs | 14 +- crates/lib/src/address.rs | 6 +- crates/lib/src/identity.rs | 6 +- crates/lib/tests/serde.rs | 2 +- crates/sats/src/algebraic_type.rs | 87 +++--- crates/sats/src/algebraic_value.rs | 28 +- crates/sats/src/builtin_type.rs | 15 +- crates/sats/src/builtin_value.rs | 2 +- crates/sats/src/convert.rs | 18 +- crates/sats/src/de/serde.rs | 2 +- crates/sats/src/meta_type.rs | 4 +- crates/sats/src/product_type.rs | 50 +++- crates/sats/src/product_type_element.rs | 8 +- crates/sats/src/resolve_refs.rs | 4 +- crates/sats/src/sum_type.rs | 33 ++- crates/sats/src/sum_type_variant.rs | 13 +- crates/sats/src/typespace.rs | 4 +- crates/sats/tests/encoding_roundtrip.rs | 5 +- crates/sqltest/src/sqlite.rs | 2 +- crates/vm/src/eval.rs | 27 +- crates/vm/src/ops/parse.rs | 36 +-- crates/vm/src/ops/shared.rs | 2 +- crates/vm/src/typecheck.rs | 7 +- crates/vm/src/types.rs | 39 ++- 35 files changed, 364 insertions(+), 517 deletions(-) diff --git a/crates/bench/benches/generic.rs b/crates/bench/benches/generic.rs index c71e7a0aa2c..8a350c5d570 100644 --- a/crates/bench/benches/generic.rs +++ b/crates/bench/benches/generic.rs @@ -9,7 +9,7 @@ use spacetimedb_bench::{ schemas::{create_sequential, BenchTable, IndexStrategy, Location, Person, RandomTable, BENCH_PKEY_INDEX}, spacetime_module, spacetime_raw, sqlite, ResultBench, }; -use spacetimedb_lib::{sats::BuiltinType, AlgebraicType}; +use spacetimedb_lib::sats::AlgebraicType; fn criterion_benchmark(c: &mut Criterion) { bench_suite::(c, true).unwrap(); bench_suite::(c, true).unwrap(); @@ -294,9 +294,9 @@ fn _filter_setup( buckets: u32, ) -> ResultBench<(String, TableSchema, Vec)> { let filter_column_type = match &T::product_type().elements[column_index as usize].algebraic_type { - AlgebraicType::Builtin(BuiltinType::String) => "string", - AlgebraicType::Builtin(BuiltinType::U32) => "u32", - AlgebraicType::Builtin(BuiltinType::U64) => "u64", + AlgebraicType::String => "string", + AlgebraicType::U32 => "u32", + AlgebraicType::U64 => "u64", _ => unimplemented!(), }; let mean_result_count = load / buckets; diff --git a/crates/bench/src/schemas.rs b/crates/bench/src/schemas.rs index 90ccf6f5077..950472da388 100644 --- a/crates/bench/src/schemas.rs +++ b/crates/bench/src/schemas.rs @@ -52,29 +52,15 @@ impl BenchTable for Person { } fn product_type() -> sats::ProductType { - sats::ProductType::new(vec![ - sats::ProductTypeElement { - name: Some("id".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::U32), - }, - sats::ProductTypeElement { - name: Some("name".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::String), - }, - sats::ProductTypeElement { - name: Some("age".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::U64), - }, - ]) + [ + ("id", sats::AlgebraicType::U32), + ("name", sats::AlgebraicType::String), + ("age", sats::AlgebraicType::U64), + ] + .into() } fn into_product_value(self) -> sats::ProductValue { - sats::ProductValue { - elements: vec![ - sats::AlgebraicValue::Builtin(sats::BuiltinValue::U32(self.id)), - sats::AlgebraicValue::Builtin(sats::BuiltinValue::String(self.name)), - sats::AlgebraicValue::Builtin(sats::BuiltinValue::U64(self.age)), - ], - } + sats::product![self.id, self.name, self.age] } type SqliteParams = (u32, String, u64); @@ -92,29 +78,15 @@ impl BenchTable for Location { } fn product_type() -> sats::ProductType { - sats::ProductType::new(vec![ - sats::ProductTypeElement { - name: Some("id".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::U32), - }, - sats::ProductTypeElement { - name: Some("x".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::U64), - }, - sats::ProductTypeElement { - name: Some("y".to_string()), - algebraic_type: sats::AlgebraicType::Builtin(sats::BuiltinType::U64), - }, - ]) + [ + ("id", sats::AlgebraicType::U32), + ("x", sats::AlgebraicType::U64), + ("y", sats::AlgebraicType::U64), + ] + .into() } fn into_product_value(self) -> sats::ProductValue { - sats::ProductValue { - elements: vec![ - sats::AlgebraicValue::Builtin(sats::BuiltinValue::U32(self.id)), - sats::AlgebraicValue::Builtin(sats::BuiltinValue::U64(self.x)), - sats::AlgebraicValue::Builtin(sats::BuiltinValue::U64(self.y)), - ], - } + sats::product![self.id, self.x, self.y] } type SqliteParams = (u32, u64, u64); diff --git a/crates/bench/src/spacetime_module.rs b/crates/bench/src/spacetime_module.rs index a68a2d57eac..ce1e2519cfd 100644 --- a/crates/bench/src/spacetime_module.rs +++ b/crates/bench/src/spacetime_module.rs @@ -1,6 +1,6 @@ use spacetimedb::db::datastore::traits::TableSchema; use spacetimedb::db::{Config, FsyncPolicy, Storage}; -use spacetimedb_lib::sats::BuiltinValue; +use spacetimedb_lib::sats::{product, BuiltinValue}; use spacetimedb_lib::{sats::ArrayValue, AlgebraicValue, ProductValue}; use spacetimedb_testing::modules::{start_runtime, CompiledModule, ModuleHandle}; use tokio::runtime::Runtime; @@ -150,11 +150,9 @@ impl BenchDatabase for SpacetimeModule { } fn insert_bulk(&mut self, table_id: &Self::TableId, rows: Vec) -> ResultBench<()> { - let args = ProductValue { - elements: vec![AlgebraicValue::Builtin(spacetimedb_lib::sats::BuiltinValue::Array { - val: ArrayValue::Product(rows.into_iter().map(|row| row.into_product_value()).collect()), - })], - }; + let args = product![AlgebraicValue::ArrayOf(ArrayValue::Product( + rows.into_iter().map(|row| row.into_product_value()).collect(), + ))]; let SpacetimeModule { runtime, module } = self; let module = module.as_mut().unwrap(); let reducer_name = format!("insert_bulk_{}", table_id.snake_case); @@ -218,10 +216,10 @@ impl BenchDatabase for SpacetimeModule { ) -> ResultBench<()> { let column = &table.columns[column_index as usize].col_name; - let value = match value.as_builtin().unwrap() { - BuiltinValue::U32(x) => x.to_string(), - BuiltinValue::U64(x) => x.to_string(), - BuiltinValue::String(x) => format!("'{}'", x), + let value = match value { + AlgebraicValue::Builtin(BuiltinValue::U32(x)) => x.to_string(), + AlgebraicValue::Builtin(BuiltinValue::U64(x)) => x.to_string(), + AlgebraicValue::Builtin(BuiltinValue::String(x)) => format!("'{}'", x), _ => { unreachable!() } diff --git a/crates/bench/src/spacetime_raw.rs b/crates/bench/src/spacetime_raw.rs index 79325c36278..619c8bc63fe 100644 --- a/crates/bench/src/spacetime_raw.rs +++ b/crates/bench/src/spacetime_raw.rs @@ -7,9 +7,8 @@ use spacetimedb::db::datastore::traits::{IndexDef, TableDef, TableSchema}; use spacetimedb::db::relational_db::{open_db, RelationalDB}; use spacetimedb::error::DBError; use spacetimedb::sql::execute::run; -use spacetimedb_lib::identity::AuthCtx; -use spacetimedb_lib::sats::BuiltinValue; use spacetimedb_lib::AlgebraicValue; +use spacetimedb_lib::{identity::AuthCtx, sats::BuiltinValue}; use std::hint::black_box; use tempdir::TempDir; @@ -150,10 +149,10 @@ impl BenchDatabase for SpacetimeRaw { let table_name = &table.table_name; - let value = match value.as_builtin().unwrap() { - BuiltinValue::U32(x) => x.to_string(), - BuiltinValue::U64(x) => x.to_string(), - BuiltinValue::String(x) => format!("'{}'", x), + let value = match value { + AlgebraicValue::Builtin(BuiltinValue::U32(x)) => x.to_string(), + AlgebraicValue::Builtin(BuiltinValue::U64(x)) => x.to_string(), + AlgebraicValue::Builtin(BuiltinValue::String(x)) => format!("'{}'", x), _ => { unreachable!() } diff --git a/crates/bench/src/sqlite.rs b/crates/bench/src/sqlite.rs index 4f9bd627010..e17683dc310 100644 --- a/crates/bench/src/sqlite.rs +++ b/crates/bench/src/sqlite.rs @@ -8,10 +8,7 @@ use ahash::AHashMap; use lazy_static::lazy_static; use rusqlite::Connection; use spacetimedb::db::datastore::traits::TableSchema; -use spacetimedb_lib::{ - sats::{self}, - AlgebraicType, AlgebraicValue, ProductType, -}; +use spacetimedb_lib::{sats::BuiltinValue, AlgebraicType, AlgebraicValue, ProductType}; use std::{ fmt::Write, hint::black_box, @@ -68,9 +65,8 @@ impl BenchDatabase for SQLite { for (i, column) in T::product_type().elements.iter().enumerate() { let column_name = column.name.clone().unwrap(); let type_ = match column.algebraic_type { - AlgebraicType::Builtin(sats::BuiltinType::U32) => "INTEGER", - AlgebraicType::Builtin(sats::BuiltinType::U64) => "INTEGER", - AlgebraicType::Builtin(sats::BuiltinType::String) => "TEXT", + AlgebraicType::U32 | AlgebraicType::U64 => "INTEGER", + AlgebraicType::String => "TEXT", _ => unimplemented!(), }; let extra = if index_strategy == IndexStrategy::Unique && i == 0 { @@ -192,19 +188,19 @@ impl BenchDatabase for SQLite { begin.execute(())?; match value { - AlgebraicValue::Builtin(sats::BuiltinValue::String(value)) => { - for _ in stmt.query_map((value,), |row| { + AlgebraicValue::Builtin(BuiltinValue::String(value)) => { + for _ in stmt.query_map((&*value,), |row| { black_box(row); Ok(()) })? {} } - AlgebraicValue::Builtin(sats::BuiltinValue::U32(value)) => { + AlgebraicValue::Builtin(BuiltinValue::U32(value)) => { for _ in stmt.query_map((value,), |row| { black_box(row); Ok(()) })? {} } - AlgebraicValue::Builtin(sats::BuiltinValue::U64(value)) => { + AlgebraicValue::Builtin(BuiltinValue::U64(value)) => { for _ in stmt.query_map((value,), |row| { black_box(row); Ok(()) diff --git a/crates/bindings-macro/src/module.rs b/crates/bindings-macro/src/module.rs index 0e6ff4b3e66..a86d1fe9215 100644 --- a/crates/bindings-macro/src/module.rs +++ b/crates/bindings-macro/src/module.rs @@ -126,16 +126,23 @@ pub(crate) fn derive_satstype(ty: &SatsType<'_>, gen_type_alias: bool) -> TokenS SatsTypeData::Product(fields) => { let fields = fields.iter().map(|field| { let field_name = match &field.name { - Some(name) => quote!(Some(#name.to_owned())), + Some(name) => quote!(Some(#name)), None => quote!(None), }; let ty = field.ty; - quote!(spacetimedb::sats::ProductTypeElement { - name: #field_name, - algebraic_type: <#ty as spacetimedb::SpacetimeType>::make_type(__typespace), - }) + quote!(( + #field_name, + <#ty as spacetimedb::SpacetimeType>::make_type(__typespace), + )) }); - quote!(spacetimedb::sats::AlgebraicType::product(vec![#(#fields),*])) + let len = fields.len(); + quote!( + spacetimedb::sats::AlgebraicType::product::< + [(Option<&str>, spacetimedb::sats::AlgebraicType); #len] + >( + [#(#fields),*] + ) + ) } SatsTypeData::Sum(variants) => { let unit = syn::Type::Tuple(syn::TypeTuple { @@ -145,12 +152,19 @@ pub(crate) fn derive_satstype(ty: &SatsType<'_>, gen_type_alias: bool) -> TokenS let variants = variants.iter().map(|var| { let variant_name = &var.name; let ty = var.ty.unwrap_or(&unit); - quote!(spacetimedb::sats::SumTypeVariant { - name: Some(#variant_name.to_owned()), - algebraic_type: <#ty as spacetimedb::SpacetimeType>::make_type(__typespace), - }) + quote!(( + #variant_name, + <#ty as spacetimedb::SpacetimeType>::make_type(__typespace), + )) }); - quote!(spacetimedb::sats::AlgebraicType::sum(vec![#(#variants),*])) + let len = variants.len(); + quote!( + spacetimedb::sats::AlgebraicType::sum::< + [(&str, spacetimedb::sats::AlgebraicType); #len] + >( + [#(#variants),*] + ) + ) // todo!() } // syn::Data::Union(u) => return Err(syn::Error::new(u.union_token.span, "unions not supported")), }; diff --git a/crates/bindings/src/rt.rs b/crates/bindings/src/rt.rs index 96920e71bf2..5b303b4e594 100644 --- a/crates/bindings/src/rt.rs +++ b/crates/bindings/src/rt.rs @@ -453,7 +453,7 @@ impl TypespaceBuilder for ModuleBuilder { btree_map::Entry::Occupied(o) => *o.get(), btree_map::Entry::Vacant(v) => { // Bind a fresh alias to the unit type. - let slot_ref = self.module.typespace.add(AlgebraicType::UNIT_TYPE); + let slot_ref = self.module.typespace.add(AlgebraicType::unit()); // Relate `typeid -> fresh alias`. v.insert(slot_ref); diff --git a/crates/core/src/db/datastore/locking_tx_datastore/mod.rs b/crates/core/src/db/datastore/locking_tx_datastore/mod.rs index f9d8ccdeb3c..b11313d0d40 100644 --- a/crates/core/src/db/datastore/locking_tx_datastore/mod.rs +++ b/crates/core/src/db/datastore/locking_tx_datastore/mod.rs @@ -53,9 +53,7 @@ use spacetimedb_lib::{ relation::RelValue, DataKey, Hash, }; -use spacetimedb_sats::{ - AlgebraicType, AlgebraicValue, BuiltinType, BuiltinValue, ProductType, ProductTypeElement, ProductValue, -}; +use spacetimedb_sats::{AlgebraicType, AlgebraicValue, BuiltinValue, ProductType, ProductValue}; use thiserror::Error; #[derive(Error, Debug, PartialEq, Eq)] @@ -809,10 +807,7 @@ impl Inner { let elements = table_schema .columns .into_iter() - .map(|col| ProductTypeElement { - name: None, - algebraic_type: col.col_type, - }) + .map(|col| col.col_type.into()) .collect(); Ok(ProductType { elements }) } @@ -1150,50 +1145,41 @@ impl Inner { ty: &AlgebraicType, sequence_value: i128, ) -> Result { - match ty { - AlgebraicType::Builtin(of) => Ok(match of { - BuiltinType::I8 => AlgebraicValue::I8(sequence_value as i8), - BuiltinType::U8 => AlgebraicValue::U8(sequence_value as u8), - BuiltinType::I16 => AlgebraicValue::I16(sequence_value as i16), - BuiltinType::U16 => AlgebraicValue::U16(sequence_value as u16), - BuiltinType::I32 => AlgebraicValue::I32(sequence_value as i32), - BuiltinType::U32 => AlgebraicValue::U32(sequence_value as u32), - BuiltinType::I64 => AlgebraicValue::I64(sequence_value as i64), - BuiltinType::U64 => AlgebraicValue::U64(sequence_value as u64), - BuiltinType::I128 => AlgebraicValue::I128(sequence_value), - BuiltinType::U128 => AlgebraicValue::U128(sequence_value as u128), - _ => { - return Err(SequenceError::NotInteger { - col: format!("{}.{}", table_name, col_name), - found: ty.clone(), - }) - } - }), - _ => Err(SequenceError::NotInteger { - col: format!("{}.{}", table_name, col_name), - found: ty.clone(), - }), - } + Ok(match *ty { + AlgebraicType::I8 => AlgebraicValue::I8(sequence_value as i8), + AlgebraicType::U8 => AlgebraicValue::U8(sequence_value as u8), + AlgebraicType::I16 => AlgebraicValue::I16(sequence_value as i16), + AlgebraicType::U16 => AlgebraicValue::U16(sequence_value as u16), + AlgebraicType::I32 => AlgebraicValue::I32(sequence_value as i32), + AlgebraicType::U32 => AlgebraicValue::U32(sequence_value as u32), + AlgebraicType::I64 => AlgebraicValue::I64(sequence_value as i64), + AlgebraicType::U64 => AlgebraicValue::U64(sequence_value as u64), + AlgebraicType::I128 => sequence_value.into(), + AlgebraicType::U128 => (sequence_value as u128).into(), + _ => { + return Err(SequenceError::NotInteger { + col: format!("{}.{}", table_name, col_name), + found: ty.clone(), + }) + } + }) } /// Check if the value is one of the `numeric` types and is `0`. fn can_replace_with_sequence(value: &AlgebraicValue) -> bool { - match value.as_builtin() { - Some(x) => match x { - BuiltinValue::I8(x) => *x == 0, - BuiltinValue::U8(x) => *x == 0, - BuiltinValue::I16(x) => *x == 0, - BuiltinValue::U16(x) => *x == 0, - BuiltinValue::I32(x) => *x == 0, - BuiltinValue::U32(x) => *x == 0, - BuiltinValue::I64(x) => *x == 0, - BuiltinValue::U64(x) => *x == 0, - BuiltinValue::I128(x) => *x == 0, - BuiltinValue::U128(x) => *x == 0, - BuiltinValue::F32(x) => *x == 0.0, - BuiltinValue::F64(x) => *x == 0.0, - _ => false, - }, + match value { + AlgebraicValue::Builtin(BuiltinValue::I8(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::U8(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::I16(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::U16(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::I32(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::U32(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::I64(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::U64(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::I128(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::U128(x)) => *x == 0, + AlgebraicValue::Builtin(BuiltinValue::F32(x)) => *x == 0.0, + AlgebraicValue::Builtin(BuiltinValue::F64(x)) => *x == 0.0, _ => false, } } @@ -2186,7 +2172,11 @@ mod tests { error::ResultTest, ColumnIndexAttribute, }; - use spacetimedb_sats::{AlgebraicType, AlgebraicValue, ProductValue}; + use spacetimedb_sats::{product, AlgebraicType, AlgebraicValue, ProductValue}; + + fn u32_str_u32(a: u32, b: &str, c: u32) -> ProductValue { + product![a, b, c] + } fn get_datastore() -> super::super::Result { Locking::bootstrap() @@ -2581,24 +2571,14 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; let rows = datastore .iter_mut_tx(&tx, table_id)? .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -2628,12 +2608,8 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); - datastore.insert_mut_tx(&mut tx, table_id, row)?; + // 0 will be ignored. + datastore.insert_mut_tx(&mut tx, table_id, u32_str_u32(0, "Foo", 18))?; datastore.commit_mut_tx(tx)?; let tx = datastore.begin_mut_tx(); let rows = datastore @@ -2641,13 +2617,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -2657,11 +2627,7 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(15), // A number which will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(15, "Foo", 18); // 15 is ignored. datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); datastore.insert_mut_tx(&mut tx, table_id, row)?; @@ -2682,19 +2648,11 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); - let created_row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let created_row = u32_str_u32(1, "Foo", 18); let num_deleted = datastore.delete_by_rel_mut_tx(&mut tx, table_id, vec![created_row])?; assert_eq!(num_deleted, Some(1)); let rows = datastore @@ -2702,24 +2660,14 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); assert_eq!(rows.len(), 0); - let created_row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(19), - ]); + let created_row = u32_str_u32(1, "Foo", 19); datastore.insert_mut_tx(&mut tx, table_id, created_row)?; let rows = datastore .iter_mut_tx(&tx, table_id)? .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(19), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 19)]); Ok(()) } @@ -2729,18 +2677,10 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; for _ in 0..2 { - let created_row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let created_row = u32_str_u32(1, "Foo", 18); let num_deleted = datastore.delete_by_rel_mut_tx(&mut tx, table_id, vec![created_row.clone()])?; assert_eq!(num_deleted, Some(1)); let rows = datastore @@ -2754,13 +2694,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); } Ok(()) } @@ -2771,11 +2705,7 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row.clone())?; let result = datastore.insert_mut_tx(&mut tx, table_id, row); match result { @@ -2792,13 +2722,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -2808,11 +2732,7 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row.clone())?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); @@ -2831,13 +2751,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -2849,11 +2763,7 @@ mod tests { let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row.clone())?; datastore.rollback_mut_tx(tx); let mut tx = datastore.begin_mut_tx(); @@ -2863,13 +2773,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(2), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(2, "Foo", 18)]); Ok(()) } @@ -2881,11 +2785,7 @@ mod tests { let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); @@ -2933,13 +2833,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -2949,11 +2843,7 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); @@ -2984,11 +2874,7 @@ mod tests { StIndexRow { index_id: 8, table_id: 6, cols: NonEmpty::new(2), index_name: "age_idx".to_string(), is_unique: true }, ]); - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Bar".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Bar", 18); // 0 will be ignored. let result = datastore.insert_mut_tx(&mut tx, table_id, row); match result { Err(DBError::Index(IndexError::UniqueConstraintViolation { @@ -3004,13 +2890,7 @@ mod tests { .map(|r| r.view().clone()) .collect::>(); #[rustfmt::skip] - assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]) - ]); + assert_eq!(rows, vec![u32_str_u32(1, "Foo", 18)]); Ok(()) } @@ -3020,11 +2900,7 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. datastore.insert_mut_tx(&mut tx, table_id, row)?; datastore.commit_mut_tx(tx)?; let mut tx = datastore.begin_mut_tx(); @@ -3065,16 +2941,8 @@ mod tests { .collect::>(); #[rustfmt::skip] assert_eq!(rows, vec![ - ProductValue::from_iter(vec![ - AlgebraicValue::U32(1), - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]), - ProductValue::from_iter(vec![ - AlgebraicValue::U32(2), - AlgebraicValue::String("Bar".to_string()), - AlgebraicValue::U32(18), - ]) + u32_str_u32(1, "Foo", 18), + u32_str_u32(2, "Bar", 18), ]); Ok(()) } @@ -3087,13 +2955,9 @@ mod tests { let mut tx = datastore.begin_mut_tx(); let schema = basic_table_schema(); let table_id = datastore.create_table_mut_tx(&mut tx, schema)?; - let row = ProductValue::from_iter(vec![ - AlgebraicValue::U32(0), // 0 will be ignored. - AlgebraicValue::String("Foo".to_string()), - AlgebraicValue::U32(18), - ]); - // Because of autoinc columns, we will get a slightly different - // value than the one we inserted. + let row = u32_str_u32(0, "Foo", 18); // 0 will be ignored. + // Because of autoinc columns, we will get a slightly different + // value than the one we inserted. let row = datastore.insert_mut_tx(&mut tx, table_id, row)?; datastore.commit_mut_tx(tx)?; diff --git a/crates/core/src/db/relational_db.rs b/crates/core/src/db/relational_db.rs index 1896e35cde8..0ada40ba803 100644 --- a/crates/core/src/db/relational_db.rs +++ b/crates/core/src/db/relational_db.rs @@ -668,7 +668,7 @@ mod tests { let (stdb, _tmp_dir) = make_test_db()?; let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); stdb.create_table(&mut tx, schema)?; stdb.commit_tx(tx)?; @@ -682,7 +682,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); stdb.create_table(&mut tx, schema)?; @@ -715,7 +715,7 @@ mod tests { let (stdb, _tmp_dir) = make_test_db()?; let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; let t_id = stdb.table_id_from_name(&tx, "MyTable")?; @@ -728,7 +728,7 @@ mod tests { let (stdb, _tmp_dir) = make_test_db()?; let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); stdb.create_table(&mut tx, schema)?; let table_id = stdb.table_id_from_name(&tx, "MyTable")?.unwrap(); @@ -743,7 +743,7 @@ mod tests { let (stdb, _tmp_dir) = make_test_db()?; let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); stdb.create_table(&mut tx, schema.clone())?; let result = stdb.create_table(&mut tx, schema); @@ -757,7 +757,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; @@ -781,7 +781,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; @@ -807,7 +807,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; @@ -831,7 +831,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; @@ -857,7 +857,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; stdb.rollback_tx(tx); @@ -874,7 +874,7 @@ mod tests { let mut tx = stdb.begin_tx(); - let mut schema = TableDef::from(ProductType::from_iter([("my_col", AlgebraicType::I32)])); + let mut schema = TableDef::from(ProductType::from([("my_col", AlgebraicType::I32)])); schema.table_name = "MyTable".to_string(); let table_id = stdb.create_table(&mut tx, schema)?; stdb.commit_tx(tx)?; diff --git a/crates/core/src/sql/execute.rs b/crates/core/src/sql/execute.rs index 32e2a59af5f..2273b9f243b 100644 --- a/crates/core/src/sql/execute.rs +++ b/crates/core/src/sql/execute.rs @@ -1,6 +1,6 @@ use spacetimedb_lib::identity::AuthCtx; use spacetimedb_lib::relation::MemTable; -use spacetimedb_lib::{ProductType, ProductValue}; +use spacetimedb_sats::{ProductType, ProductValue}; use spacetimedb_vm::eval::run_ast; use spacetimedb_vm::expr::{CodeResult, CrudExpr, Expr}; use tracing::info; @@ -104,7 +104,7 @@ pub(crate) mod tests { use spacetimedb_lib::auth::{StAccess, StTableType}; use spacetimedb_lib::error::ResultTest; use spacetimedb_lib::relation::{Header, RelValue}; - use spacetimedb_sats::{product, AlgebraicType, BuiltinType, ProductType}; + use spacetimedb_sats::{product, AlgebraicType, ProductType}; use spacetimedb_vm::dsl::{mem_table, scalar}; use spacetimedb_vm::eval::create_game_data; use tempdir::TempDir; @@ -118,7 +118,7 @@ pub(crate) mod tests { let (db, tmp_dir) = make_test_db()?; let mut tx = db.begin_tx(); - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let rows: Vec<_> = (1..=total_rows).map(|i| product!(i, format!("health{i}"))).collect(); create_table_with_rows(&db, &mut tx, "inventory", head.clone(), &rows)?; db.commit_tx(tx)?; @@ -165,7 +165,7 @@ pub(crate) mod tests { assert_eq!(result.len(), 1, "Not return results"); let result = result.first().unwrap().clone(); - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64)]); let row = product!(1u64); let input = mem_table(head, vec![row]); @@ -186,8 +186,8 @@ pub(crate) mod tests { assert_eq!(result.len(), 1, "Not return results"); let result = result.first().unwrap().clone(); - let schema = ProductType::from_iter([BuiltinType::I32]); - let row = product!(scalar(1)); + let schema = ProductType::from([AlgebraicType::I32]); + let row = product!(1); let input = mem_table(schema, vec![row]); assert_eq!(result.as_without_table_name(), input.as_without_table_name(), "Scalar"); @@ -389,7 +389,7 @@ pub(crate) mod tests { WHERE x > 0 AND x <= 32 AND z > 0 AND z <= 32", )?[0]; - let head = ProductType::from_iter([("entity_id", BuiltinType::U64), ("inventory_id", BuiltinType::U64)]); + let head = ProductType::from([("entity_id", AlgebraicType::U64), ("inventory_id", AlgebraicType::U64)]); let row1 = product!(100u64, 1u64); let input = mem_table(head, [row1]); @@ -413,7 +413,7 @@ pub(crate) mod tests { WHERE x > 0 AND x <= 32 AND z > 0 AND z <= 32", )?[0]; - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row1 = product!(1u64, "health"); let input = mem_table(head, [row1]); diff --git a/crates/core/src/subscription/query.rs b/crates/core/src/subscription/query.rs index c0115b009e4..dfb3b4dcec6 100644 --- a/crates/core/src/subscription/query.rs +++ b/crates/core/src/subscription/query.rs @@ -159,7 +159,7 @@ mod tests { use spacetimedb_lib::error::ResultTest; use spacetimedb_lib::relation::FieldName; use spacetimedb_lib::Identity; - use spacetimedb_sats::{product, BuiltinType, ProductType, ProductValue}; + use spacetimedb_sats::{product, ProductType, ProductValue}; use spacetimedb_vm::dsl::{db_table, mem_table, scalar}; use spacetimedb_vm::operator::OpCmp; @@ -244,7 +244,7 @@ mod tests { "_inventory" }; - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(1u64, "health"); let (schema, table, data, q) = make_data(db, tx, table_name, &head, &row)?; @@ -265,7 +265,7 @@ mod tests { tx: &mut MutTxId, ) -> ResultTest<(TableSchema, MemTable, DatabaseTableUpdate, QueryExpr)> { let table_name = "player"; - let head = ProductType::from_iter([("player_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("player_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(2u64, "jhon doe"); let (schema, table, data, q) = make_data(db, tx, table_name, &head, &row)?; @@ -356,7 +356,7 @@ mod tests { let (db, _) = make_test_db()?; let mut tx = db.begin_tx(); - let schema = ProductType::from_iter([("u8", BuiltinType::U8)]); + let schema = ProductType::from([("u8", AlgebraicType::U8)]); let row = product!(1u8); // generate row id from row diff --git a/crates/core/src/vm.rs b/crates/core/src/vm.rs index a8ec261fa91..19fe4eb457a 100644 --- a/crates/core/src/vm.rs +++ b/crates/core/src/vm.rs @@ -517,7 +517,7 @@ pub(crate) mod tests { use crate::db::relational_db::{ST_COLUMNS_NAME, ST_INDEXES_NAME, ST_SEQUENCES_NAME, ST_TABLES_NAME}; use spacetimedb_lib::error::ResultTest; use spacetimedb_lib::relation::{DbTable, FieldName}; - use spacetimedb_sats::{product, AlgebraicType, BuiltinType, ProductType, ProductValue}; + use spacetimedb_sats::{product, AlgebraicType, ProductType, ProductValue}; use spacetimedb_vm::dsl::*; use spacetimedb_vm::eval::run_ast; use spacetimedb_vm::operator::OpCmp; @@ -578,7 +578,7 @@ pub(crate) mod tests { let mut tx = stdb.begin_tx(); let p = &mut DbProgram::new(&stdb, &mut tx, AuthCtx::for_testing()); - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(1u64, "health"); let table_id = create_table_from_program(p, "inventory", head.clone(), &[row])?; @@ -595,10 +595,10 @@ pub(crate) mod tests { }; //The expected result - let inv = ProductType::from_iter([ - (Some("inventory_id"), BuiltinType::U64), - (Some("name"), BuiltinType::String), - (None, BuiltinType::U64), + let inv = ProductType::from([ + (Some("inventory_id"), AlgebraicType::U64), + (Some("name"), AlgebraicType::String), + (None, AlgebraicType::U64), ]); let row = product!(scalar(1u64), scalar("health"), scalar(1u64)); let input = mem_table(inv, vec![row]); @@ -692,7 +692,7 @@ pub(crate) mod tests { fn test_query_catalog_indexes() -> ResultTest<()> { let (db, _tmp_dir) = make_test_db()?; - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(1u64, "health"); let mut tx = db.begin_tx(); diff --git a/crates/lib/src/address.rs b/crates/lib/src/address.rs index eae4f18e686..588de1f7724 100644 --- a/crates/lib/src/address.rs +++ b/crates/lib/src/address.rs @@ -1,6 +1,6 @@ use anyhow::Context as _; use hex::FromHex as _; -use sats::{impl_deserialize, impl_serialize, impl_st, AlgebraicType, ProductTypeElement}; +use sats::{impl_deserialize, impl_serialize, impl_st, AlgebraicType}; use spacetimedb_bindings_macro::{Deserialize, Serialize}; use std::{fmt, net::Ipv6Addr}; @@ -20,9 +20,7 @@ pub struct Address { __address_bytes: [u8; 16], } -impl_st!([] Address, _ts => AlgebraicType::product(vec![ - ProductTypeElement::new_named(AlgebraicType::bytes(), "__address_bytes") -])); +impl_st!([] Address, _ts => AlgebraicType::product([("__address_bytes", AlgebraicType::bytes())])); impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/crates/lib/src/identity.rs b/crates/lib/src/identity.rs index 64cd6d787df..682d387603d 100644 --- a/crates/lib/src/identity.rs +++ b/crates/lib/src/identity.rs @@ -1,5 +1,5 @@ use spacetimedb_bindings_macro::{Deserialize, Serialize}; -use spacetimedb_sats::{impl_st, AlgebraicType, ProductTypeElement}; +use spacetimedb_sats::{impl_st, AlgebraicType}; use std::{fmt, str::FromStr}; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -30,9 +30,7 @@ pub struct Identity { __identity_bytes: [u8; 32], } -impl_st!([] Identity, _ts => AlgebraicType::product(vec![ - ProductTypeElement::new_named(AlgebraicType::bytes(), "__identity_bytes") -])); +impl_st!([] Identity, _ts => AlgebraicType::product([("__identity_bytes", AlgebraicType::bytes())])); impl Identity { const ABBREVIATION_LEN: usize = 16; diff --git a/crates/lib/tests/serde.rs b/crates/lib/tests/serde.rs index 0a152efb33d..c8ce0ae4fde 100644 --- a/crates/lib/tests/serde.rs +++ b/crates/lib/tests/serde.rs @@ -25,7 +25,7 @@ fn test_json_mappings() { "quux", AlgebraicType::Sum(enumm([ ("Hash", AlgebraicType::bytes()), - ("Unit", AlgebraicType::UNIT_TYPE), + ("Unit", AlgebraicType::unit()), ])), ), ("and_peggy", AlgebraicType::option(AlgebraicType::F64)), diff --git a/crates/sats/src/algebraic_type.rs b/crates/sats/src/algebraic_type.rs index ec8c59768e1..eb0912ae629 100644 --- a/crates/sats/src/algebraic_type.rs +++ b/crates/sats/src/algebraic_type.rs @@ -5,9 +5,7 @@ use crate::algebraic_value::de::{ValueDeserializeError, ValueDeserializer}; use crate::algebraic_value::ser::ValueSerializer; use crate::meta_type::MetaType; use crate::{de::Deserialize, ser::Serialize, MapType}; -use crate::{ - AlgebraicTypeRef, AlgebraicValue, ArrayType, BuiltinType, ProductType, ProductTypeElement, SumType, SumTypeVariant, -}; +use crate::{AlgebraicTypeRef, AlgebraicValue, ArrayType, BuiltinType, ProductType, SumType, SumTypeVariant}; use enum_as_inner::EnumAsInner; /// The SpacetimeDB Algebraic Type System (SATS) is a structural type system in @@ -117,6 +115,9 @@ pub enum AlgebraicType { #[allow(non_upper_case_globals)] impl AlgebraicType { + /// The first type in the typespace. + pub const ZERO_REF: Self = Self::Ref(AlgebraicTypeRef(0)); + /// The built-in Bool type. pub const Bool: Self = Self::Builtin(BuiltinType::Bool); @@ -160,10 +161,16 @@ impl AlgebraicType { pub const String: Self = Self::Builtin(BuiltinType::String); /// The canonical 0-element unit type. - pub const UNIT_TYPE: Self = Self::product(Vec::new()); + pub fn unit() -> Self { + let fs: [AlgebraicType; 0] = []; + Self::product(fs) + } /// The canonical 0-variant "never" / "absurd" / "void" type. - pub const NEVER_TYPE: Self = Self::sum(Vec::new()); + pub fn never() -> Self { + let vs: [SumTypeVariant; 0] = []; + Self::sum(vs) + } } impl MetaType for AlgebraicType { @@ -173,11 +180,11 @@ impl MetaType for AlgebraicType { /// This could alternatively be implemented /// as a regular AlgebraicValue or as a static variable. fn meta_type() -> Self { - AlgebraicType::sum(vec![ - SumTypeVariant::new_named(SumType::meta_type(), "sum"), - SumTypeVariant::new_named(ProductType::meta_type(), "product"), - SumTypeVariant::new_named(BuiltinType::meta_type(), "builtin"), - SumTypeVariant::new_named(AlgebraicTypeRef::meta_type(), "ref"), + AlgebraicType::sum([ + ("sum", SumType::meta_type()), + ("product", ProductType::meta_type()), + ("builtin", BuiltinType::meta_type()), + ("ref", AlgebraicTypeRef::meta_type()), ]) } } @@ -195,22 +202,19 @@ impl AlgebraicType { ) } - /// Returns a sum type with the given `variants`. - pub const fn sum(variants: Vec) -> Self { - AlgebraicType::Sum(SumType { variants }) + /// Returns a sum type with the given `sum`. + pub fn sum>(sum: S) -> Self { + AlgebraicType::Sum(sum.into()) } - /// Returns a product type with the given `factors`. - pub const fn product(factors: Vec) -> Self { - AlgebraicType::Product(ProductType::new(factors)) + /// Returns a product type with the given `prod`. + pub fn product>(prod: P) -> Self { + AlgebraicType::Product(prod.into()) } /// Returns a structural option type where `some_type` is the type for the `some` variant. pub fn option(some_type: Self) -> Self { - Self::sum(vec![ - SumTypeVariant::new_named(some_type, "some"), - SumTypeVariant::unit("none"), - ]) + Self::sum([("some", some_type), ("none", AlgebraicType::unit())]) } /// Returns an unsized array type where the element type is `ty`. @@ -226,7 +230,7 @@ impl AlgebraicType { /// Returns a sum type of unit variants with names taken from `var_names`. pub fn simple_enum<'a>(var_names: impl Iterator) -> Self { - Self::sum(var_names.into_iter().map(SumTypeVariant::unit).collect()) + Self::sum(var_names.into_iter().map(SumTypeVariant::unit).collect::>()) } pub fn as_value(&self) -> AlgebraicValue { @@ -245,28 +249,28 @@ mod tests { use crate::satn::Satn; use crate::{ algebraic_type::fmt::fmt_algebraic_type, algebraic_type::map_notation::fmt_algebraic_type as fmt_map, - algebraic_type_ref::AlgebraicTypeRef, product_type_element::ProductTypeElement, typespace::Typespace, + algebraic_type_ref::AlgebraicTypeRef, typespace::Typespace, }; use crate::{ValueWithType, WithTypespace}; #[test] fn never() { - assert_eq!("(|)", fmt_algebraic_type(&AlgebraicType::NEVER_TYPE).to_string()); + assert_eq!("(|)", fmt_algebraic_type(&AlgebraicType::never()).to_string()); } #[test] fn never_map() { - assert_eq!("{ ty_: Sum }", fmt_map(&AlgebraicType::NEVER_TYPE).to_string()); + assert_eq!("{ ty_: Sum }", fmt_map(&AlgebraicType::never()).to_string()); } #[test] fn unit() { - assert_eq!("()", fmt_algebraic_type(&AlgebraicType::UNIT_TYPE).to_string()); + assert_eq!("()", fmt_algebraic_type(&AlgebraicType::unit()).to_string()); } #[test] fn unit_map() { - assert_eq!("{ ty_: Product }", fmt_map(&AlgebraicType::UNIT_TYPE).to_string()); + assert_eq!("{ ty_: Product }", fmt_map(&AlgebraicType::unit()).to_string()); } #[test] @@ -281,13 +285,13 @@ mod tests { #[test] fn option() { - let option = AlgebraicType::option(AlgebraicType::NEVER_TYPE); + let option = AlgebraicType::option(AlgebraicType::never()); assert_eq!("(some: (|) | none: ())", fmt_algebraic_type(&option).to_string()); } #[test] fn option_map() { - let option = AlgebraicType::option(AlgebraicType::NEVER_TYPE); + let option = AlgebraicType::option(AlgebraicType::never()); assert_eq!( "{ ty_: Sum, some: { ty_: Sum }, none: { ty_: Product } }", fmt_map(&option).to_string() @@ -315,22 +319,13 @@ mod tests { #[test] fn nested_products_and_sums() { let builtin = AlgebraicType::U8; - let product = AlgebraicType::product(vec![ProductTypeElement { - name: Some("thing".into()), - algebraic_type: AlgebraicType::U8, - }]); - let next = AlgebraicType::sum(vec![builtin.clone().into(), builtin.clone().into(), product.into()]); - let next = AlgebraicType::product(vec![ - ProductTypeElement { - algebraic_type: builtin.clone(), - name: Some("test".into()), - }, - next.into(), - builtin.into(), - ProductTypeElement { - algebraic_type: AlgebraicType::NEVER_TYPE, - name: Some("never".into()), - }, + let product = AlgebraicType::product([("thing", AlgebraicType::U8)]); + let sum = AlgebraicType::sum([builtin.clone(), builtin.clone(), product]); + let next = AlgebraicType::product([ + (Some("test"), builtin.clone()), + (None, sum), + (None, builtin), + (Some("never"), AlgebraicType::never()), ]); assert_eq!( "(test: U8, 1: (U8 | U8 | (thing: U8)), 2: U8, never: (|))", @@ -344,7 +339,7 @@ mod tests { #[test] fn option_as_value() { - let option = AlgebraicType::option(AlgebraicType::NEVER_TYPE); + let option = AlgebraicType::option(AlgebraicType::never()); let algebraic_type = AlgebraicType::meta_type(); let typespace = Typespace::new(vec![algebraic_type]); let at_ref = AlgebraicType::Ref(AlgebraicTypeRef(0)); @@ -379,7 +374,7 @@ mod tests { #[test] fn option_from_value() { - let option = AlgebraicType::option(AlgebraicType::NEVER_TYPE); + let option = AlgebraicType::option(AlgebraicType::never()); AlgebraicType::from_value(&option.as_value()).expect("No errors."); } diff --git a/crates/sats/src/algebraic_value.rs b/crates/sats/src/algebraic_value.rs index 1e76e21b6a1..063a2b8a06b 100644 --- a/crates/sats/src/algebraic_value.rs +++ b/crates/sats/src/algebraic_value.rs @@ -43,7 +43,9 @@ impl AlgebraicValue { /// The canonical unit value defined as the nullary product value `()`. /// /// The type of `UNIT` is `()`. - pub const UNIT: Self = Self::product(Vec::new()); + pub fn unit() -> Self { + Self::product([].into()) + } /// Interpret the value as a `bool` or `None` if it isn't a `bool` value. #[inline] @@ -358,7 +360,7 @@ impl AlgebraicValue { /// The `none` variant is assigned the tag `1`. #[inline] pub fn OptionNone() -> Self { - Self::sum(1, Self::UNIT) + Self::sum(1, Self::unit()) } /// Returns an [`AlgebraicValue`] representing a sum value with `tag` and `value`. @@ -389,24 +391,24 @@ impl AlgebraicValue { // To assign this a correct type we either have to store the type with the value // or alternatively, we must have polymorphic variants (see row polymorphism) // *and* derive the correct variant name. - AlgebraicType::product(vec![x.value.type_of().into()]) + AlgebraicType::product([x.value.type_of()]) } /// Returns the [`AlgebraicType`] of the product value `x`. pub(crate) fn type_of_product(x: &ProductValue) -> AlgebraicType { - AlgebraicType::product(x.elements.iter().map(|x| x.type_of().into()).collect()) + AlgebraicType::product(x.elements.iter().map(|x| x.type_of().into()).collect::>()) } /// Returns the [`AlgebraicType`] of the map with key type `k` and value type `v`. pub(crate) fn type_of_map(val: &BTreeMap) -> AlgebraicType { AlgebraicType::product(if let Some((k, v)) = val.first_key_value() { - vec![k.type_of().into(), v.type_of().into()] + [k.type_of(), v.type_of()] } else { // TODO(centril): What is the motivation for this? // I think this requires a soundness argument. // I could see that it is OK with the argument that this is an empty map // under the requirement that we cannot insert elements into the map. - vec![AlgebraicType::NEVER_TYPE.into(); 2] + [AlgebraicType::never(), AlgebraicType::never()] }) } @@ -463,9 +465,7 @@ mod tests { use std::collections::BTreeMap; use crate::satn::Satn; - use crate::{ - AlgebraicType, AlgebraicValue, ArrayValue, ProductTypeElement, Typespace, ValueWithType, WithTypespace, - }; + use crate::{AlgebraicType, AlgebraicValue, ArrayValue, Typespace, ValueWithType, WithTypespace}; fn in_space<'a, T: crate::Value>(ts: &'a Typespace, ty: &'a T::Type, val: &'a T) -> ValueWithType<'a, T> { WithTypespace::new(ts, ty).with_value(val) @@ -473,17 +473,17 @@ mod tests { #[test] fn unit() { - let val = AlgebraicValue::UNIT; - let unit = AlgebraicType::UNIT_TYPE; + let val = AlgebraicValue::unit(); + let unit = AlgebraicType::unit(); let typespace = Typespace::new(vec![]); assert_eq!(in_space(&typespace, &unit, &val).to_satn(), "()"); } #[test] fn product_value() { - let product_type = AlgebraicType::product(vec![ProductTypeElement::new_named(AlgebraicType::I32, "foo")]); + let product_type = AlgebraicType::product([("foo", AlgebraicType::I32)]); let typespace = Typespace::new(vec![]); - let product_value = AlgebraicValue::product(vec![AlgebraicValue::I32(42)]); + let product_value = AlgebraicValue::product([AlgebraicValue::I32(42)].into()); assert_eq!( "(foo = 42)", in_space(&typespace, &product_type, &product_value).to_satn(), @@ -492,7 +492,7 @@ mod tests { #[test] fn option_some() { - let option = AlgebraicType::option(AlgebraicType::NEVER_TYPE); + let option = AlgebraicType::option(AlgebraicType::never()); let sum_value = AlgebraicValue::OptionNone(); let typespace = Typespace::new(vec![]); assert_eq!("(none = ())", in_space(&typespace, &option, &sum_value).to_satn(),); diff --git a/crates/sats/src/builtin_type.rs b/crates/sats/src/builtin_type.rs index b409e7f6cb3..537bc83c795 100644 --- a/crates/sats/src/builtin_type.rs +++ b/crates/sats/src/builtin_type.rs @@ -2,10 +2,7 @@ use crate::algebraic_value::de::{ValueDeserializeError, ValueDeserializer}; use crate::algebraic_value::ser::ValueSerializer; use crate::meta_type::MetaType; use crate::{de::Deserialize, ser::Serialize}; -use crate::{ - impl_deserialize, impl_serialize, AlgebraicType, AlgebraicTypeRef, AlgebraicValue, ProductTypeElement, - SumTypeVariant, -}; +use crate::{impl_deserialize, impl_serialize, AlgebraicType, AlgebraicValue, SumTypeVariant}; use enum_as_inner::EnumAsInner; /// Represents the built-in types in SATS. @@ -91,9 +88,8 @@ impl MapType { impl MetaType for BuiltinType { fn meta_type() -> AlgebraicType { - let zero_ref = || AlgebraicType::Ref(AlgebraicTypeRef(0)); // TODO: sats(rename_all = "lowercase"), otherwise json won't work. - AlgebraicType::sum(vec![ + AlgebraicType::sum([ SumTypeVariant::unit("bool"), SumTypeVariant::unit("i8"), SumTypeVariant::unit("u8"), @@ -108,12 +104,9 @@ impl MetaType for BuiltinType { SumTypeVariant::unit("f32"), SumTypeVariant::unit("f64"), SumTypeVariant::unit("string"), - SumTypeVariant::new_named(zero_ref(), "array"), + SumTypeVariant::new_named(AlgebraicType::ZERO_REF, "array"), SumTypeVariant::new_named( - AlgebraicType::product(vec![ - ProductTypeElement::new_named(zero_ref(), "key_ty"), - ProductTypeElement::new_named(zero_ref(), "ty"), - ]), + AlgebraicType::product([("key_ty", AlgebraicType::ZERO_REF), ("ty", AlgebraicType::ZERO_REF)]), "map", ), ]) diff --git a/crates/sats/src/builtin_value.rs b/crates/sats/src/builtin_value.rs index ff71d27ffc3..7105d9fca15 100644 --- a/crates/sats/src/builtin_value.rs +++ b/crates/sats/src/builtin_value.rs @@ -194,7 +194,7 @@ impl ArrayValue { /// Helper for `type_of` above. /// Infers the `AlgebraicType` from the first element by running `then` on it. fn first_type_of(arr: &[T], then: impl FnOnce(&T) -> AlgebraicType) -> AlgebraicType { - arr.first().map(then).unwrap_or_else(|| AlgebraicType::NEVER_TYPE) + arr.first().map(then).unwrap_or_else(AlgebraicType::never) } /// Returns the length of the array. diff --git a/crates/sats/src/convert.rs b/crates/sats/src/convert.rs index eee3565fd63..33eef79495c 100644 --- a/crates/sats/src/convert.rs +++ b/crates/sats/src/convert.rs @@ -2,7 +2,7 @@ use crate::algebraic_type::AlgebraicType; use crate::algebraic_value::AlgebraicValue; use crate::builtin_type::BuiltinType; use crate::builtin_value::BuiltinValue; -use crate::{ProductType, ProductTypeElement, ProductValue}; +use crate::{ProductType, ProductValue}; impl From for AlgebraicType { fn from(x: BuiltinType) -> Self { @@ -40,27 +40,21 @@ impl From<&AlgebraicValue> for ProductValue { impl From for ProductType { fn from(x: AlgebraicType) -> Self { - Self::new(vec![x.into()]) + Self::new([x.into()].into()) } } -impl From for ProductTypeElement { - fn from(x: BuiltinType) -> Self { - Self::new(x.into(), None) +impl From for AlgebraicType { + fn from(x: ProductType) -> Self { + Self::Product(x) } } macro_rules! built_in { ($native:ty, $kind:ident) => { - impl From<$native> for BuiltinValue { - fn from(x: $native) -> Self { - BuiltinValue::$kind(x) - } - } - impl From<$native> for AlgebraicValue { fn from(x: $native) -> Self { - AlgebraicValue::Builtin(x.into()) + AlgebraicValue::Builtin(BuiltinValue::$kind(x)) } } }; diff --git a/crates/sats/src/de/serde.rs b/crates/sats/src/de/serde.rs index c258d29c88d..4dc8bc4dca8 100644 --- a/crates/sats/src/de/serde.rs +++ b/crates/sats/src/de/serde.rs @@ -339,7 +339,7 @@ impl<'de, E: super::Error> super::VariantAccess<'de> for NoneAccess { type Error = E; fn deserialize_seed>(self, seed: T) -> Result { use crate::algebraic_value::de::*; - seed.deserialize(ValueDeserializer::new(crate::AlgebraicValue::UNIT)) + seed.deserialize(ValueDeserializer::new(crate::AlgebraicValue::unit())) .map_err(|err| match err { ValueDeserializeError::MismatchedType => E::custom("mismatched type"), ValueDeserializeError::Custom(err) => E::custom(err), diff --git a/crates/sats/src/meta_type.rs b/crates/sats/src/meta_type.rs index fe8369302cd..debd5a548c1 100644 --- a/crates/sats/src/meta_type.rs +++ b/crates/sats/src/meta_type.rs @@ -10,9 +10,9 @@ use crate::AlgebraicType; /// /// For example, the `MetaType` of [`ProductType`](crate::ProductType) is /// ```ignore -/// AlgebraicType::product(vec![ProductTypeElement::new_named( -/// AlgebraicType::array(ProductTypeElement::meta_type()), +/// AlgebraicType::product([( /// "elements", +/// AlgebraicType::array(ProductTypeElement::meta_type()), /// )]) /// ``` pub trait MetaType { diff --git a/crates/sats/src/product_type.rs b/crates/sats/src/product_type.rs index 0c7698daef5..8c7898d663e 100644 --- a/crates/sats/src/product_type.rs +++ b/crates/sats/src/product_type.rs @@ -43,26 +43,25 @@ impl ProductType { Self { elements } } - /// Returns whether this is the special case of `spacetimedb_lib::Identity`. - pub fn is_identity(&self) -> bool { + /// Returns whether this is a "newtype" over bytes. + fn is_bytes_newtype(&self, check: &str) -> bool { match &*self.elements { [ProductTypeElement { name: Some(name), algebraic_type, - }] => name == "__identity_bytes" && algebraic_type.is_bytes(), + }] => name == check && algebraic_type.is_bytes(), _ => false, } } + /// Returns whether this is the special case of `spacetimedb_lib::Identity`. + pub fn is_identity(&self) -> bool { + self.is_bytes_newtype("__identity_bytes") + } + /// Returns whether this is the special case of `spacetimedb_lib::Address`. pub fn is_address(&self) -> bool { - match &*self.elements { - [ProductTypeElement { - name: Some(name), - algebraic_type, - }] => name == "__address_bytes" && algebraic_type.is_bytes(), - _ => false, - } + self.is_bytes_newtype("__address_bytes") } /// Returns whether this is a special known type, currently `Address` or `Identity`. @@ -92,12 +91,35 @@ impl<'a, I: Into> FromIterator<(Option<&'a str>, I)> for ProductT } } +impl From> for ProductType { + fn from(fields: Vec) -> Self { + ProductType::new(fields) + } +} +impl From<[ProductTypeElement; N]> for ProductType { + fn from(fields: [ProductTypeElement; N]) -> Self { + ProductType::new(fields.into()) + } +} +impl From<[(Option<&str>, AlgebraicType); N]> for ProductType { + fn from(fields: [(Option<&str>, AlgebraicType); N]) -> Self { + fields.into_iter().collect() + } +} +impl From<[(&str, AlgebraicType); N]> for ProductType { + fn from(fields: [(&str, AlgebraicType); N]) -> Self { + fields.into_iter().collect() + } +} +impl From<[AlgebraicType; N]> for ProductType { + fn from(fields: [AlgebraicType; N]) -> Self { + fields.into_iter().collect() + } +} + impl MetaType for ProductType { fn meta_type() -> AlgebraicType { - AlgebraicType::product(vec![ProductTypeElement::new_named( - AlgebraicType::array(ProductTypeElement::meta_type()), - "elements", - )]) + AlgebraicType::product([("elements", AlgebraicType::array(ProductTypeElement::meta_type()))]) } } diff --git a/crates/sats/src/product_type_element.rs b/crates/sats/src/product_type_element.rs index 3e2aa3c882e..de88a67d2ad 100644 --- a/crates/sats/src/product_type_element.rs +++ b/crates/sats/src/product_type_element.rs @@ -1,6 +1,6 @@ use crate::meta_type::MetaType; +use crate::AlgebraicType; use crate::{de::Deserialize, ser::Serialize}; -use crate::{AlgebraicType, AlgebraicTypeRef}; /// A factor / element of a product type. /// @@ -47,9 +47,9 @@ impl ProductTypeElement { impl MetaType for ProductTypeElement { fn meta_type() -> AlgebraicType { - AlgebraicType::product(vec![ - Self::new_named(AlgebraicType::option(AlgebraicType::String), "name"), - Self::new_named(AlgebraicType::Ref(AlgebraicTypeRef(0)), "algebraic_type"), + AlgebraicType::product([ + ("name", AlgebraicType::option(AlgebraicType::String)), + ("algebraic_type", AlgebraicType::ZERO_REF), ]) } } diff --git a/crates/sats/src/resolve_refs.rs b/crates/sats/src/resolve_refs.rs index af941f5d8b8..a1db00957fe 100644 --- a/crates/sats/src/resolve_refs.rs +++ b/crates/sats/src/resolve_refs.rs @@ -120,7 +120,7 @@ impl ResolveRefs for ProductType { impl ResolveRefs for ProductTypeElement { type Output = Self; fn resolve_refs(this: WithTypespace<'_, Self>, state: &mut ResolveRefState) -> Option { - Some(ProductTypeElement { + Some(Self { algebraic_type: this.map(|e| &e.algebraic_type)._resolve_refs(state)?, name: this.ty().name.clone(), }) @@ -143,7 +143,7 @@ impl ResolveRefs for SumType { impl ResolveRefs for SumTypeVariant { type Output = Self; fn resolve_refs(this: WithTypespace<'_, Self>, state: &mut ResolveRefState) -> Option { - Some(SumTypeVariant { + Some(Self { algebraic_type: this.map(|v| &v.algebraic_type)._resolve_refs(state)?, name: this.ty().name.clone(), }) diff --git a/crates/sats/src/sum_type.rs b/crates/sats/src/sum_type.rs index f4f3f443e8b..0dc50b40bff 100644 --- a/crates/sats/src/sum_type.rs +++ b/crates/sats/src/sum_type.rs @@ -2,7 +2,7 @@ use crate::algebraic_value::de::{ValueDeserializeError, ValueDeserializer}; use crate::algebraic_value::ser::ValueSerializer; use crate::meta_type::MetaType; use crate::{de::Deserialize, ser::Serialize}; -use crate::{AlgebraicType, AlgebraicValue, ProductTypeElement, SumTypeVariant}; +use crate::{AlgebraicType, AlgebraicValue, SumTypeVariant}; /// A structural sum type. /// @@ -72,12 +72,35 @@ impl SumType { } } +impl From> for SumType { + fn from(fields: Vec) -> Self { + SumType::new(fields) + } +} +impl From<[SumTypeVariant; N]> for SumType { + fn from(fields: [SumTypeVariant; N]) -> Self { + SumType::new(fields.into()) + } +} +impl From<[(Option<&str>, AlgebraicType); N]> for SumType { + fn from(fields: [(Option<&str>, AlgebraicType); N]) -> Self { + fields.map(|(s, t)| SumTypeVariant::new(t, s.map(<_>::into))).into() + } +} +impl From<[(&str, AlgebraicType); N]> for SumType { + fn from(fields: [(&str, AlgebraicType); N]) -> Self { + fields.map(|(s, t)| SumTypeVariant::new_named(t, s)).into() + } +} +impl From<[AlgebraicType; N]> for SumType { + fn from(fields: [AlgebraicType; N]) -> Self { + fields.map(SumTypeVariant::from).into() + } +} + impl MetaType for SumType { fn meta_type() -> AlgebraicType { - AlgebraicType::product(vec![ProductTypeElement::new_named( - AlgebraicType::array(SumTypeVariant::meta_type()), - "variants", - )]) + AlgebraicType::product([("variants", AlgebraicType::array(SumTypeVariant::meta_type()))]) } } diff --git a/crates/sats/src/sum_type_variant.rs b/crates/sats/src/sum_type_variant.rs index e0565f17fdb..410b54d98f3 100644 --- a/crates/sats/src/sum_type_variant.rs +++ b/crates/sats/src/sum_type_variant.rs @@ -1,7 +1,6 @@ use crate::algebraic_type::AlgebraicType; use crate::meta_type::MetaType; use crate::{de::Deserialize, ser::Serialize}; -use crate::{AlgebraicTypeRef, ProductTypeElement}; /// A variant of a sum type. /// @@ -37,8 +36,8 @@ impl SumTypeVariant { } /// Returns a unit variant with `name`. - pub fn unit(name: impl AsRef) -> Self { - Self::new_named(AlgebraicType::UNIT_TYPE, name) + pub fn unit(name: &str) -> Self { + Self::new_named(AlgebraicType::unit(), name) } /// Returns the name of the variant. @@ -53,15 +52,15 @@ impl SumTypeVariant { /// Returns whether this is a unit variant. pub fn is_unit(&self) -> bool { - self.algebraic_type == AlgebraicType::UNIT_TYPE + self.algebraic_type == AlgebraicType::unit() } } impl MetaType for SumTypeVariant { fn meta_type() -> AlgebraicType { - AlgebraicType::product(vec![ - ProductTypeElement::new_named(AlgebraicType::option(AlgebraicType::String), "name"), - ProductTypeElement::new_named(AlgebraicType::Ref(AlgebraicTypeRef(0)), "algebraic_type"), + AlgebraicType::product([ + ("name", AlgebraicType::option(AlgebraicType::String)), + ("algebraic_type", AlgebraicType::ZERO_REF), ]) } } diff --git a/crates/sats/src/typespace.rs b/crates/sats/src/typespace.rs index 6cb27f07f91..aa07da35ded 100644 --- a/crates/sats/src/typespace.rs +++ b/crates/sats/src/typespace.rs @@ -120,7 +120,7 @@ pub trait TypespaceBuilder { /// ['a, T: SpacetimeType] Foo<'a, T>, /// // The `make_type` implementation where `ts: impl TypespaceBuilder` /// // and the expression right of `=>` is an `AlgebraicType`. -/// ts => AlgebraicType::product(vec![T::make_type(ts).into(), AlgebraicType::U8.into()]) +/// ts => AlgebraicType::product([T::make_type(ts), AlgebraicType::U8]) /// ); /// ``` #[macro_export] @@ -157,7 +157,7 @@ impl_primitives! { String => String, } -impl_st!([] (), _ts => AlgebraicType::UNIT_TYPE); +impl_st!([] (), _ts => AlgebraicType::unit()); impl_st!([] &str, _ts => AlgebraicType::String); impl_st!([T: SpacetimeType] Vec, ts => AlgebraicType::array(T::make_type(ts))); impl_st!([T: SpacetimeType] Option, ts => AlgebraicType::option(T::make_type(ts))); diff --git a/crates/sats/tests/encoding_roundtrip.rs b/crates/sats/tests/encoding_roundtrip.rs index 7ea55d5d529..0351c9dda25 100644 --- a/crates/sats/tests/encoding_roundtrip.rs +++ b/crates/sats/tests/encoding_roundtrip.rs @@ -5,8 +5,7 @@ use proptest::proptest; use spacetimedb_sats::buffer::DecodeError; use spacetimedb_sats::builtin_value::{F32, F64}; use spacetimedb_sats::{ - meta_type::MetaType, product, AlgebraicType, AlgebraicValue, BuiltinValue, ProductType, ProductTypeElement, - ProductValue, + meta_type::MetaType, product, AlgebraicType, AlgebraicValue, BuiltinValue, ProductType, ProductValue, }; #[test] @@ -106,7 +105,7 @@ fn algebraic_values() -> impl Strategy { fn round_trip(value: AlgebraicValue) -> Result<(ProductValue, ProductValue), DecodeError> { let ty = value.type_of(); - let schema = ProductType::new(vec![ProductTypeElement::new(ty, Some("x".to_string()))]); + let schema = ProductType::from([("x", ty)]); let row = product!(value); diff --git a/crates/sqltest/src/sqlite.rs b/crates/sqltest/src/sqlite.rs index 33588f18948..72dd3445823 100644 --- a/crates/sqltest/src/sqlite.rs +++ b/crates/sqltest/src/sqlite.rs @@ -91,7 +91,7 @@ impl AsyncDB for Sqlite { for (name, dectype) in &mut columns { let value = row.get::<_, Value>(name.as_str())?; let (value, kind) = match value { - Value::Null => ("null".into(), AlgebraicType::NEVER_TYPE), + Value::Null => ("null".into(), AlgebraicType::never()), Value::Integer(x) => (x.to_string(), AlgebraicType::I64), Value::Real(x) => (format!("{:?}", x), AlgebraicType::F64), Value::Text(x) => (format!("'{}'", x), AlgebraicType::String), diff --git a/crates/vm/src/eval.rs b/crates/vm/src/eval.rs index 129a7a60568..be7b7ca60de 100644 --- a/crates/vm/src/eval.rs +++ b/crates/vm/src/eval.rs @@ -3,7 +3,6 @@ use std::collections::HashMap; use spacetimedb_lib::relation::{FieldExpr, MemTable, RelIter, Relation, Table}; use spacetimedb_sats::algebraic_type::AlgebraicType; use spacetimedb_sats::algebraic_value::AlgebraicValue; -use spacetimedb_sats::builtin_type::BuiltinType; use spacetimedb_sats::{product, ProductType, ProductValue}; use crate::dsl::{bin_op, call_fn, if_, mem_table, scalar, var}; @@ -532,20 +531,20 @@ pub struct GameData { // Used internally for testing SQL JOINS #[doc(hidden)] pub fn create_game_data() -> GameData { - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from_iter([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(1u64, "health"); let inv = mem_table(head, [row]); - let head = ProductType::from_iter([("entity_id", BuiltinType::U64), ("inventory_id", BuiltinType::U64)]); + let head = ProductType::from_iter([("entity_id", AlgebraicType::U64), ("inventory_id", AlgebraicType::U64)]); let row1 = product!(100u64, 1u64); let row2 = product!(200u64, 1u64); let row3 = product!(300u64, 1u64); let player = mem_table(head, [row1, row2, row3]); let head = ProductType::from_iter([ - ("entity_id", BuiltinType::U64), - ("x", BuiltinType::F32), - ("z", BuiltinType::F32), + ("entity_id", AlgebraicType::U64), + ("x", AlgebraicType::F32), + ("z", AlgebraicType::F32), ]); let row1 = product!(100u64, 0.0f32, 32.0f32); let row2 = product!(100u64, 1.0f32, 31.0f32); @@ -789,7 +788,7 @@ mod tests { }; //The expected result - let inv = ProductType::from_iter([(None, BuiltinType::I32), (Some("0_0"), BuiltinType::I32)]); + let inv = ProductType::from_iter([(None, AlgebraicType::I32), (Some("0_0"), AlgebraicType::I32)]); let row = product!(scalar(1), scalar(1)); let input = mem_table(inv, vec![row]); @@ -803,7 +802,7 @@ mod tests { fn test_query_logic() { let p = &mut Program::new(AuthCtx::for_testing()); - let inv = ProductType::from_iter([("id", BuiltinType::U64), ("name", BuiltinType::String)]); + let inv = ProductType::from_iter([("id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(scalar(1u64), scalar("health")); @@ -829,7 +828,7 @@ mod tests { fn test_query() { let p = &mut Program::new(AuthCtx::for_testing()); - let inv = ProductType::from_iter([("id", BuiltinType::U64), ("name", BuiltinType::String)]); + let inv = ProductType::from_iter([("id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row = product!(scalar(1u64), scalar("health")); @@ -845,9 +844,9 @@ mod tests { //The expected result let inv = ProductType::from_iter([ - (None, BuiltinType::U64), - (Some("id"), BuiltinType::U64), - (Some("name"), BuiltinType::String), + (None, AlgebraicType::U64), + (Some("id"), AlgebraicType::U64), + (Some("name"), AlgebraicType::String), ]); let row = product!(scalar(1u64), scalar("health"), scalar(1u64), scalar("health")); let input = mem_table(inv, vec![row]); @@ -899,7 +898,7 @@ mod tests { let result = run_query(p, q.into()); - let head = ProductType::from_iter([("entity_id", BuiltinType::U64), ("inventory_id", BuiltinType::U64)]); + let head = ProductType::from_iter([("entity_id", AlgebraicType::U64), ("inventory_id", AlgebraicType::U64)]); let row1 = product!(100u64, 1u64); let input = mem_table(head, [row1]); @@ -925,7 +924,7 @@ mod tests { let result = run_query(p, q.into()); - let head = ProductType::from_iter([("inventory_id", BuiltinType::U64), ("name", BuiltinType::String)]); + let head = ProductType::from_iter([("inventory_id", AlgebraicType::U64), ("name", AlgebraicType::String)]); let row1 = product!(1u64, "health"); let input = mem_table(head, [row1]); diff --git a/crates/vm/src/ops/parse.rs b/crates/vm/src/ops/parse.rs index 0851145f33d..a40b82bdbfc 100644 --- a/crates/vm/src/ops/parse.rs +++ b/crates/vm/src/ops/parse.rs @@ -1,6 +1,6 @@ use crate::errors::{ErrorType, ErrorVm}; use spacetimedb_sats::satn::Satn; -use spacetimedb_sats::{AlgebraicType, AlgebraicValue, BuiltinType}; +use spacetimedb_sats::{AlgebraicType, AlgebraicValue}; use std::fmt::Display; use std::str::FromStr; @@ -34,26 +34,20 @@ where /// ``` pub fn parse(value: &str, ty: &AlgebraicType) -> Result { match ty { - AlgebraicType::Builtin(x) => match x { - BuiltinType::Bool => _parse::(value, ty), - BuiltinType::I8 => _parse::(value, ty), - BuiltinType::U8 => _parse::(value, ty), - BuiltinType::I16 => _parse::(value, ty), - BuiltinType::U16 => _parse::(value, ty), - BuiltinType::I32 => _parse::(value, ty), - BuiltinType::U32 => _parse::(value, ty), - BuiltinType::I64 => _parse::(value, ty), - BuiltinType::U64 => _parse::(value, ty), - BuiltinType::I128 => _parse::(value, ty), - BuiltinType::U128 => _parse::(value, ty), - BuiltinType::F32 => _parse::(value, ty), - BuiltinType::F64 => _parse::(value, ty), - BuiltinType::String => Ok(AlgebraicValue::String(value.to_string())), - x => Err(ErrorVm::Unsupported(format!( - "Can't parse '{value}' to {}", - x.to_satn_pretty() - ))), - }, + &AlgebraicType::Bool => _parse::(value, ty), + &AlgebraicType::I8 => _parse::(value, ty), + &AlgebraicType::U8 => _parse::(value, ty), + &AlgebraicType::I16 => _parse::(value, ty), + &AlgebraicType::U16 => _parse::(value, ty), + &AlgebraicType::I32 => _parse::(value, ty), + &AlgebraicType::U32 => _parse::(value, ty), + &AlgebraicType::I64 => _parse::(value, ty), + &AlgebraicType::U64 => _parse::(value, ty), + &AlgebraicType::I128 => _parse::(value, ty), + &AlgebraicType::U128 => _parse::(value, ty), + &AlgebraicType::F32 => _parse::(value, ty), + &AlgebraicType::F64 => _parse::(value, ty), + &AlgebraicType::String => Ok(AlgebraicValue::String(value.to_string())), x => Err(ErrorVm::Unsupported(format!( "Can't parse '{value}' to {}", x.to_satn_pretty() diff --git a/crates/vm/src/ops/shared.rs b/crates/vm/src/ops/shared.rs index d4555c9a00a..a43b90cff42 100644 --- a/crates/vm/src/ops/shared.rs +++ b/crates/vm/src/ops/shared.rs @@ -9,5 +9,5 @@ where } pub(crate) fn to_bool(of: &AlgebraicValue) -> Option { - of.as_builtin().and_then(|x| x.as_bool()).copied() + of.as_bool().copied() } diff --git a/crates/vm/src/typecheck.rs b/crates/vm/src/typecheck.rs index 671c5b46dae..2e7aed6ad21 100644 --- a/crates/vm/src/typecheck.rs +++ b/crates/vm/src/typecheck.rs @@ -157,7 +157,6 @@ mod tests { use spacetimedb_lib::identity::AuthCtx; use spacetimedb_sats::algebraic_type::AlgebraicType; - use spacetimedb_sats::builtin_type::BuiltinType; use crate::dsl::{bin_op, scalar}; use crate::eval::optimize; @@ -179,10 +178,8 @@ mod tests { // #[test] // fn ty_value() { // let p = &mut Program::new(); - // // let zero = scalar(0); - // - // _expect(p, zero, BuiltinType::I32.into()) + // _expect_ast(p, zero, AlgebraicType::I32) // } #[test] @@ -190,6 +187,6 @@ mod tests { let p = &mut Program::new(AuthCtx::for_testing()); let ast = bin_op(OpMath::Add, scalar(0), scalar(1)); - _expect_ast(p, ast, BuiltinType::I32.into()) + _expect_ast(p, ast, AlgebraicType::I32) } } diff --git a/crates/vm/src/types.rs b/crates/vm/src/types.rs index bd2cb5d6f91..f5dfe35e336 100644 --- a/crates/vm/src/types.rs +++ b/crates/vm/src/types.rs @@ -6,7 +6,6 @@ use crate::operator::*; use spacetimedb_sats::algebraic_type::map_notation::fmt_algebraic_type; use spacetimedb_sats::algebraic_type::AlgebraicType; use spacetimedb_sats::algebraic_value::AlgebraicValue; -use spacetimedb_sats::builtin_type::BuiltinType; /// Describe a `type`. In the case of [Ty::Unknown] the type of [Expr] is /// not yet know and should be resolved by the type-checker. @@ -43,12 +42,6 @@ impl fmt::Display for Ty { } } -impl From for Ty { - fn from(x: BuiltinType) -> Self { - Ty::Val(x.into()) - } -} - pub trait TypeOf { fn type_of(&self) -> Ty; } @@ -67,25 +60,25 @@ impl TypeOf for AlgebraicValue { pub(crate) fn ty_op(op: Op) -> Vec { match op { - Op::Cmp(_) | Op::Logic(_) => vec![BuiltinType::Bool.into()], + Op::Cmp(_) | Op::Logic(_) => vec![AlgebraicType::Bool.into()], Op::Unary(x) => match x { - OpUnary::Not => vec![BuiltinType::Bool.into()], + OpUnary::Not => vec![AlgebraicType::Bool.into()], }, Op::Math(_) => vec![ - BuiltinType::I8.into(), - BuiltinType::U8.into(), - BuiltinType::I16.into(), - BuiltinType::U16.into(), - BuiltinType::I32.into(), - BuiltinType::U32.into(), - BuiltinType::I32.into(), - BuiltinType::U32.into(), - BuiltinType::I64.into(), - BuiltinType::U64.into(), - BuiltinType::I128.into(), - BuiltinType::U128.into(), - BuiltinType::F32.into(), - BuiltinType::F64.into(), + AlgebraicType::I8.into(), + AlgebraicType::U8.into(), + AlgebraicType::I16.into(), + AlgebraicType::U16.into(), + AlgebraicType::I32.into(), + AlgebraicType::U32.into(), + AlgebraicType::I32.into(), + AlgebraicType::U32.into(), + AlgebraicType::I64.into(), + AlgebraicType::U64.into(), + AlgebraicType::I128.into(), + AlgebraicType::U128.into(), + AlgebraicType::F32.into(), + AlgebraicType::F64.into(), ], } }