diff --git a/syndicate-macros/src/lib.rs b/syndicate-macros/src/lib.rs index 28303d5..29b73b5 100644 --- a/syndicate-macros/src/lib.rs +++ b/syndicate-macros/src/lib.rs @@ -170,11 +170,10 @@ fn compile_pattern(v: &IOValue) -> TokenStream { lit(ValueCompiler::for_patterns().compile(v)), } Value::Record(r) => { - let arity = r.arity() as u128; match r.label().value().as_symbol() { None => panic!("Record labels in patterns must be symbols"), Some(label) => - if label.starts_with("$") && arity == 1 { + if label.starts_with("$") && r.arity() == 1 { let nested = compile_pattern(&r.fields()[0]); quote!(#P_::Pattern::DBind(Box::new(#P_::DBind { pattern: #nested @@ -188,23 +187,16 @@ fn compile_pattern(v: &IOValue) -> TokenStream { }; let members = compile_sequence_members(r.fields()); quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Rec { - ctor: Box::new(#P_::CRec { - label: #label_stx, - arity: #arity .into(), - }), - members: #MapFromIterator_(vec![#(#members),*]) + label: #label_stx, + fields: vec![#(#members),*], }))) } } } Value::Sequence(vs) => { - let arity = vs.len() as u128; let members = compile_sequence_members(vs); quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Arr { - ctor: Box::new(#P_::CArr { - arity: #arity .into(), - }), - members: #MapFromIterator_(vec![#(#members),*]) + items: vec![#(#members),*], }))) } Value::Set(_) => @@ -216,8 +208,7 @@ fn compile_pattern(v: &IOValue) -> TokenStream { quote!((#k, #v)) }).collect::>(); quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Dict { - ctor: Box::new(#P_::CDict), - members: #MapFromIterator_(vec![#(#members),*]) + entries: #MapFromIterator_(vec![#(#members),*]) }))) } _ => lit(ValueCompiler::for_patterns().compile(v)), diff --git a/syndicate-macros/src/pat.rs b/syndicate-macros/src/pat.rs index 8e5e3d6..fc73f34 100644 --- a/syndicate-macros/src/pat.rs +++ b/syndicate-macros/src/pat.rs @@ -7,20 +7,18 @@ use quote::quote; use syn::parse_macro_input; use crate::stx::Stx; -use crate::val::emit_set; use crate::val::to_value_expr; use crate::val::value_to_value_expr; pub fn lit(e: T) -> TokenStream2 { - quote!( - syndicate::schemas::dataspace_patterns::Pattern::DLit(Box::new( - syndicate::schemas::dataspace_patterns::DLit { value: #e }))) + quote!(syndicate::pattern::lift_literal(#e)) } fn compile_sequence_members(stxs: &Vec) -> Result, &'static str> { - stxs.iter().enumerate().map(|(i, stx)| { - let p = to_pattern_expr(stx)?; - Ok(quote!((#i .into(), #p))) + stxs.iter().map(|stx| { + // let p = to_pattern_expr(stx)?; + // Ok(quote!(#p)) + to_pattern_expr(stx) }).collect() } @@ -51,24 +49,21 @@ pub fn to_pattern_expr(stx: &Stx) -> Result { Ok(quote!(#P_::Pattern::DDiscard(Box::new(#P_::DDiscard)))), Stx::Rec(l, fs) => { - let arity = fs.len() as u128; let label = to_value_expr(&*l)?; let members = compile_sequence_members(fs)?; Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Rec { - ctor: Box::new(#P_::CRec { label: #label, arity: #arity .into() }), - members: #MapFromIterator_(vec![#(#members),*]) + label: #label, + fields: vec![#(#members),*], })))) }, Stx::Seq(stxs) => { - let arity = stxs.len() as u128; let members = compile_sequence_members(stxs)?; Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Arr { - ctor: Box::new(#P_::CArr { arity: #arity .into() }), - members: #MapFromIterator_(vec![#(#members),*]) + items: vec![#(#members),*], })))) } - Stx::Set(stxs) => - Ok(lit(emit_set(&stxs.iter().map(to_value_expr).collect::,_>>()?))), + Stx::Set(_stxs) => + Err("Set literals not supported in patterns"), Stx::Dict(d) => { let members = d.iter().map(|(k, v)| { let k = to_value_expr(k)?; @@ -76,8 +71,7 @@ pub fn to_pattern_expr(stx: &Stx) -> Result { Ok(quote!((#k, #v))) }).collect::, &'static str>>()?; Ok(quote!(#P_::Pattern::DCompound(Box::new(#P_::DCompound::Dict { - ctor: Box::new(#P_::CDict), - members: #MapFromIterator_(vec![#(#members),*]) + entries: #MapFromIterator_(vec![#(#members),*]) })))) } } diff --git a/syndicate-macros/src/stx.rs b/syndicate-macros/src/stx.rs index 194e56b..b88e5cf 100644 --- a/syndicate-macros/src/stx.rs +++ b/syndicate-macros/src/stx.rs @@ -1,6 +1,6 @@ use proc_macro2::Delimiter; use proc_macro2::LineColumn; -use proc_macro2::TokenTree; +use proc_macro2::TokenStream; use syn::ExprLit; use syn::Ident; @@ -24,7 +24,7 @@ pub enum Stx { Atom(IOValue), Binder(Option, Option, Option>), Discard, - Subst(TokenTree), + Subst(TokenStream), Rec(Box, Vec), Seq(Vec), Set(Vec), @@ -230,8 +230,10 @@ fn parse1(c: Cursor) -> Result<(Stx, Cursor)> { '#' => { if let Some((inner, _, next)) = next.group(Delimiter::Brace) { parse_group_inner(inner, parse1, next).map(|(q,c)| (Stx::Set(q),c)) + } else if let Some((inner, _, next)) = next.group(Delimiter::Parenthesis) { + Ok((Stx::Subst(inner.token_stream()), next)) } else if let Some((tt, next)) = next.token_tree() { - Ok((Stx::Subst(tt), next)) + Ok((Stx::Subst(vec![tt].into_iter().collect()), next)) } else { Err(Error::new(c.span(), "Expected expression to substitute")) } diff --git a/syndicate-server/build.rs b/syndicate-server/build.rs index 96b6ad8..e5b6d60 100644 --- a/syndicate-server/build.rs +++ b/syndicate-server/build.rs @@ -10,11 +10,11 @@ mod pattern_plugin { use std::iter::FromIterator; + use syndicate::pattern::lift_literal; use syndicate::schemas::dataspace_patterns as P; use syndicate::value::IOValue; use syndicate::value::Map; use syndicate::value::NestedValue; - use syndicate::value::signed_integer::SignedInteger; #[derive(Debug)] pub struct PatternPlugin; @@ -88,20 +88,15 @@ mod pattern_plugin { match self { CompoundPattern::Tuple { patterns } => Some(P::Pattern::DCompound(Box::new(P::DCompound::Arr { - ctor: Box::new(P::CArr { arity: patterns.len().into() }), - members: Map::from_iter( - patterns.iter().enumerate() - .map(|(i, p)| Some((i.into(), unname(p).wc(s)?))) - .filter(|e| discard() != e.as_ref().unwrap().1) - .collect::>>()? - .into_iter()), + items: patterns.iter() + .map(|p| unname(p).wc(s)) + .collect::>>()?, }))), CompoundPattern::TuplePrefix { .. } => Some(discard()), CompoundPattern::Dict { entries } => Some(P::Pattern::DCompound(Box::new(P::DCompound::Dict { - ctor: Box::new(P::CDict), - members: Map::from_iter( + entries: Map::from_iter( entries.0.iter() .map(|(k, p)| Some((from_io(k)?, unname_simple(p).wc(s)?))) .filter(|e| discard() != e.as_ref().unwrap().1) @@ -113,16 +108,10 @@ mod pattern_plugin { match (*label, *fields) { (SimplePattern::Lit { value }, CompoundPattern::Tuple { patterns }) => Some(P::Pattern::DCompound(Box::new(P::DCompound::Rec { - ctor: Box::new(P::CRec { - label: from_io(&value)?, - arity: patterns.len().into(), - }), - members: Map::from_iter( - patterns.iter().enumerate() - .map(|(i, p)| Some((i.into(), unname(p).wc(s)?))) - .filter(|e| discard() != e.as_ref().unwrap().1) - .collect::>>()? - .into_iter()), + label: from_io(&value)?, + fields: patterns.iter() + .map(|p| unname(p).wc(s)) + .collect::>>()?, }))), _ => None, }, @@ -141,11 +130,7 @@ mod pattern_plugin { SimplePattern::Seqof { .. } | SimplePattern::Setof { .. } | SimplePattern::Dictof { .. } => Some(discard()), - - SimplePattern::Lit { value } => Some(P::Pattern::DLit(Box::new(P::DLit { - value: from_io(&value)?, - }))), - + SimplePattern::Lit { value } => Some(lift_literal(&from_io(value)?)), SimplePattern::Ref(r) => s.cycle_check( r, |ctxt, r| ctxt.bundle.lookup_definition(r), diff --git a/syndicate-server/src/dependencies.rs b/syndicate-server/src/dependencies.rs index fc78808..0dfab4e 100644 --- a/syndicate-server/src/dependencies.rs +++ b/syndicate-server/src/dependencies.rs @@ -47,7 +47,7 @@ fn run(t: &mut Activation, ds: Arc, service_name: AnyValue) -> ActorResult })) .create_cap(t); ds.assert(t, language(), &Observe { - pattern: syndicate_macros::pattern!{}, + pattern: syndicate_macros::pattern!{}, observer: milestone_monitor, }); } @@ -74,7 +74,7 @@ fn run(t: &mut Activation, ds: Arc, service_name: AnyValue) -> ActorResult })?; enclose!((ds, obstacle_count) during!( - t, ds, language(), , + t, ds, language(), , enclose!((ds, obstacle_count) move |t: &mut Activation| { if let Ok(dependee) = language().parse::(&dependee) { tracing::trace!(on = ?dependee, "new dependency"); @@ -87,8 +87,8 @@ fn run(t: &mut Activation, ds: Arc, service_name: AnyValue) -> ActorResult counter::adjust(t, &obstacle_count, 1); - let d = dependee.clone(); - during!(t, ds, language(), #(d), enclose!( + let d = &dependee.clone(); + during!(t, ds, language(), #d, enclose!( (obstacle_count, dependee) move |t: &mut Activation| { tracing::trace!(on = ?dependee, "dependency satisfied"); counter::adjust(t, &obstacle_count, -1); diff --git a/syndicate-server/src/gatekeeper.rs b/syndicate-server/src/gatekeeper.rs index aaddd97..036ee7d 100644 --- a/syndicate-server/src/gatekeeper.rs +++ b/syndicate-server/src/gatekeeper.rs @@ -56,7 +56,7 @@ pub fn handle_resolve( .create_cap(t); if let Some(oh) = ds.assert(t, language(), &dataspace::Observe { // TODO: codegen plugin to generate pattern constructors - pattern: syndicate_macros::pattern!{}, + pattern: syndicate_macros::pattern!{}, observer: handler, }) { Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh))))) diff --git a/syndicate-server/src/script/mod.rs b/syndicate-server/src/script/mod.rs index 1df4189..169cdcb 100644 --- a/syndicate-server/src/script/mod.rs +++ b/syndicate-server/src/script/mod.rs @@ -1,3 +1,5 @@ +use preserves_schema::Codec; + use std::io; use std::borrow::Cow; use std::path::PathBuf; @@ -7,6 +9,7 @@ use syndicate::actor::*; use syndicate::dataspace::Dataspace; use syndicate::during; use syndicate::enclose; +use syndicate::pattern::{lift_literal, drop_literal}; use syndicate::schemas::dataspace; use syndicate::schemas::dataspace_patterns as P; use syndicate::schemas::sturdy; @@ -15,7 +18,6 @@ use syndicate::value::NestedValue; use syndicate::value::Record; use syndicate::value::Set; use syndicate::value::Value; -use syndicate::value::signed_integer::SignedInteger; use crate::language::language; @@ -154,7 +156,7 @@ fn discard() -> P::Pattern { } fn dlit(value: AnyValue) -> P::Pattern { - P::Pattern::DLit(Box::new(P::DLit { value })) + lift_literal(&value) } fn tlit(value: AnyValue) -> sturdy::Template { @@ -239,40 +241,28 @@ impl<'env> PatternInstantiator<'env> { Value::Record(r) => match parse_attenuation(r)? { Some((base_name, alternatives)) => dlit(self.env.eval_attenuation(base_name, alternatives)?), - None => { - // TODO: properly consolidate constant patterns into literals. - match self.instantiate_pattern(r.label())? { - P::Pattern::DLit(b) => - P::Pattern::DCompound(Box::new(P::DCompound::Rec { - ctor: Box::new(P::CRec { - label: b.value, - arity: r.fields().len().into(), - }), - members: r.fields().iter().enumerate() - .map(|(i, p)| Ok((i.into(), self.instantiate_pattern(p)?))) - .filter(|e| discard() != e.as_ref().unwrap().1) - .collect::>>()?, - })), - _ => Err(bad_instruction("Record pattern must have literal label"))?, - } - }, + None => { + let label = self.instantiate_pattern(r.label())?; + let fields = r.fields().iter().map(|p| self.instantiate_pattern(p)) + .collect::>>()?; + P::Pattern::DCompound(Box::new(P::DCompound::Rec { + label: drop_literal(&label) + .ok_or(bad_instruction("Record pattern must have literal label"))?, + fields, + })) + } }, Value::Sequence(v) => P::Pattern::DCompound(Box::new(P::DCompound::Arr { - ctor: Box::new(P::CArr { - arity: v.len().into(), - }), - members: v.iter().enumerate() - .map(|(i, p)| Ok((i.into(), self.instantiate_pattern(p)?))) - .filter(|e| discard() != e.as_ref().unwrap().1) - .collect::>>()?, + items: v.iter() + .map(|p| self.instantiate_pattern(p)) + .collect::>>()?, })), Value::Set(_) => Err(bad_instruction(&format!("Sets not permitted in patterns: {:?}", template)))?, Value::Dictionary(v) => P::Pattern::DCompound(Box::new(P::DCompound::Dict { - ctor: Box::new(P::CDict), - members: v.iter() + entries: v.iter() .map(|(a, b)| Ok((a.clone(), self.instantiate_pattern(b)?))) .collect::>>()?, })), @@ -618,31 +608,33 @@ fn embed_pattern(p: &P::Pattern) -> sturdy::Pattern { pattern: embed_pattern(&b.pattern), })), P::Pattern::DLit(b) => sturdy::Pattern::Lit(Box::new(sturdy::Lit { - value: b.value.clone(), + value: language().unparse(&b.value), })), P::Pattern::DCompound(b) => sturdy::Pattern::PCompound(Box::new(match &**b { - P::DCompound::Rec { ctor, members } => + P::DCompound::Rec { label, fields } => sturdy::PCompound { ctor: sturdy::ConstructorSpec::CRec(Box::new(sturdy::CRec { - label: ctor.label.clone(), - arity: ctor.arity.clone(), + label: label.clone(), + arity: fields.len().into(), })), members: sturdy::PCompoundMembers( - members.iter().map(|(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()), + fields.iter().enumerate().map( + |(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()), }, - P::DCompound::Arr { ctor, members } => + P::DCompound::Arr { items } => sturdy::PCompound { ctor: sturdy::ConstructorSpec::CArr(Box::new(sturdy::CArr { - arity: ctor.arity.clone(), + arity: items.len().into(), })), members: sturdy::PCompoundMembers( - members.iter().map(|(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()), + items.iter().enumerate().map( + |(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()), }, - P::DCompound::Dict { ctor: _, members } => + P::DCompound::Dict { entries } => sturdy::PCompound { ctor: sturdy::ConstructorSpec::CDict(Box::new(sturdy::CDict)), members: sturdy::PCompoundMembers( - members.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect()), + entries.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect()), }, })), } diff --git a/syndicate-server/src/services/daemon.rs b/syndicate-server/src/services/daemon.rs index 67581b3..ec30bfd 100644 --- a/syndicate-server/src/services/daemon.rs +++ b/syndicate-server/src/services/daemon.rs @@ -352,7 +352,7 @@ fn run( }))?; enclose!((config_ds, unready_configs, completed_processes) - during!(t, config_ds.clone(), language(), , { + during!(t, config_ds.clone(), language(), , { enclose!((spec, config_ds, root_ds, unready_configs, completed_processes) |t: &mut Activation| { tracing::debug!(?config, "new config"); diff --git a/syndicate/benches/bench_dataspace.rs b/syndicate/benches/bench_dataspace.rs index 5d1ba6e..810da0b 100644 --- a/syndicate/benches/bench_dataspace.rs +++ b/syndicate/benches/bench_dataspace.rs @@ -1,6 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use std::iter::FromIterator; use std::sync::Arc; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; @@ -13,7 +12,6 @@ use syndicate::dataspace::Dataspace; use syndicate::enclose; use syndicate::schemas::dataspace::Observe; use syndicate::schemas::dataspace_patterns as p; -use syndicate::value::Map; use syndicate::value::NestedValue; use syndicate::value::Value; @@ -99,7 +97,7 @@ pub fn bench_pub(c: &mut Criterion) { ds.assert(t, language(), &Observe { pattern: p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::DLit(Box::new(p::DLit { - value: AnyValue::symbol("consumer"), + value: p::AnyAtom::Symbol("consumer".to_owned()), })), })), observer: shutdown, @@ -120,25 +118,21 @@ pub fn bench_pub(c: &mut Criterion) { ds.assert(t, &(), &AnyValue::symbol("consumer")); ds.assert(t, language(), &Observe { pattern: p::Pattern::DCompound(Box::new(p::DCompound::Rec { - ctor: Box::new(p::CRec { - label: AnyValue::symbol("Says"), - arity: 2.into(), - }), - members: Map::from_iter(vec![ - (0.into(), p::Pattern::DLit(Box::new(p::DLit { - value: AnyValue::new("bench_pub"), - }))), - (1.into(), p::Pattern::DBind(Box::new(p::DBind { + label: AnyValue::symbol("Says"), + fields: vec![ + p::Pattern::DLit(Box::new(p::DLit { + value: p::AnyAtom::String("bench_pub".to_owned()), + })), + p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::DDiscard(Box::new(p::DDiscard)), - }))), - ].into_iter()), - })), + })), + ]})), observer: receiver, }); ds.assert(t, language(), &Observe { pattern: p::Pattern::DBind(Box::new(p::DBind { pattern: p::Pattern::DLit(Box::new(p::DLit { - value: AnyValue::new(true), + value: p::AnyAtom::Bool(true), })), })), observer: shutdown, diff --git a/syndicate/src/pattern.rs b/syndicate/src/pattern.rs index 5c14c76..2c22387 100644 --- a/syndicate/src/pattern.rs +++ b/syndicate/src/pattern.rs @@ -1,9 +1,12 @@ use crate::schemas::dataspace_patterns::*; -use preserves::value::NestedValue; +use super::language; -use std::convert::TryFrom; -use std::convert::TryInto; +use preserves::value::Map; +use preserves::value::NestedValue; +use preserves::value::Record; +use preserves::value::Value; +use preserves_schema::Codec; #[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] pub enum PathStep { @@ -26,8 +29,8 @@ pub struct PatternAnalysis { pub capture_paths: Paths, } -struct PatternMatcher { - captures: Vec, +struct PatternMatcher { + captures: Vec<_Any>, } impl PatternAnalysis { @@ -56,14 +59,18 @@ impl Analyzer { fn walk(&mut self, path: &mut Path, p: &Pattern) { match p { Pattern::DCompound(b) => match &**b { - DCompound::Rec { members, .. } | - DCompound::Arr { members, .. } => { - for (i, p) in members { - self.walk_step(path, PathStep::Index(usize::try_from(i).unwrap_or(0)), p); + DCompound::Rec { fields, .. } => { + for (i, p) in fields.iter().enumerate() { + self.walk_step(path, PathStep::Index(i), p); } } - DCompound::Dict { members, .. } => { - for (k, p) in members { + DCompound::Arr { items, .. } => { + for (i, p) in items.iter().enumerate() { + self.walk_step(path, PathStep::Index(i), p); + } + } + DCompound::Dict { entries, .. } => { + for (k, p) in entries { self.walk_step(path, PathStep::Key(k.clone()), p); } } @@ -78,14 +85,14 @@ impl Analyzer { Pattern::DLit(b) => { let DLit { value } = &**b; self.const_paths.push(path.clone()); - self.const_values.push(value.clone()); + self.const_values.push(language().unparse(value)); } } } } -impl Pattern { - pub fn match_value(&self, value: &N) -> Option> { +impl Pattern<_Any> { + pub fn match_value(&self, value: &_Any) -> Option> { let mut matcher = PatternMatcher::new(); if matcher.run(self, value) { Some(matcher.captures) @@ -95,29 +102,30 @@ impl Pattern { } } -impl PatternMatcher { +impl PatternMatcher { fn new() -> Self { PatternMatcher { captures: Vec::new(), } } - fn run(&mut self, pattern: &Pattern, value: &N) -> bool { + fn run(&mut self, pattern: &Pattern<_Any>, value: &_Any) -> bool { match pattern { Pattern::DDiscard(_) => true, Pattern::DBind(b) => { self.captures.push(value.clone()); self.run(&b.pattern, value) } - Pattern::DLit(b) => value == &b.value, + Pattern::DLit(b) => value == &language().unparse(&b.value), Pattern::DCompound(b) => match &**b { - DCompound::Rec { ctor, members } => { - let arity = (&ctor.arity).try_into().expect("reasonable arity"); - match value.value().as_record(Some(arity)) { + DCompound::Rec { label, fields } => { + match value.value().as_record(Some(fields.len())) { None => false, Some(r) => { - for (i, p) in members.iter() { - let i: usize = i.try_into().expect("reasonable index"); + if r.label() != label { + return false; + } + for (i, p) in fields.iter().enumerate() { if !self.run(p, &r.fields()[i]) { return false; } @@ -126,16 +134,14 @@ impl PatternMatcher { } } } - DCompound::Arr { ctor, members } => { - let arity: usize = (&ctor.arity).try_into().expect("reasonable arity"); + DCompound::Arr { items } => { match value.value().as_sequence() { None => false, Some(vs) => { - if vs.len() != arity { + if vs.len() != items.len() { return false; } - for (i, p) in members.iter() { - let i: usize = i.try_into().expect("reasonable index"); + for (i, p) in items.iter().enumerate() { if !self.run(p, &vs[i]) { return false; } @@ -144,12 +150,12 @@ impl PatternMatcher { } } } - DCompound::Dict { ctor: _, members } => { + DCompound::Dict { entries: expected_entries } => { match value.value().as_dictionary() { None => false, - Some(entries) => { - for (k, p) in members.iter() { - if !entries.get(k).map(|v| self.run(p, v)).unwrap_or(false) { + Some(actual_entries) => { + for (k, p) in expected_entries.iter() { + if !actual_entries.get(k).map(|v| self.run(p, v)).unwrap_or(false) { return false; } } @@ -161,3 +167,45 @@ impl PatternMatcher { } } } + +pub fn lift_literal(v: &_Any) -> Pattern { + match v.value() { + Value::Record(r) => Pattern::DCompound(Box::new(DCompound::Rec { + label: r.label().clone(), + fields: r.fields().iter().map(lift_literal).collect(), + })), + Value::Sequence(items) => Pattern::DCompound(Box::new(DCompound::Arr { + items: items.iter().map(lift_literal).collect(), + })), + Value::Set(_members) => panic!("Cannot express literal set in pattern"), + Value::Dictionary(entries) => Pattern::DCompound(Box::new(DCompound::Dict { + entries: entries.iter().map(|(k, v)| (k.clone(), lift_literal(v))).collect(), + })), + _other => Pattern::DLit(Box::new(DLit { + value: language().parse(v).expect("Non-compound datum can be converted to AnyAtom"), + })), + } +} + +pub fn drop_literal(p: &Pattern) -> Option<_Any> { + match p { + Pattern::DCompound(b) => match &**b { + DCompound::Rec { label, fields } => { + let mut r = vec![label.clone()]; + for f in fields.iter() { + r.push(drop_literal(f)?); + } + Some(Value::Record(Record(r)).wrap()) + } + DCompound::Arr { items } => + Some(Value::Sequence(items.iter().map(drop_literal) + .collect::>>()?).wrap()), + DCompound::Dict { entries } => + Some(Value::Dictionary(entries.iter() + .map(|(k, p)| Some((k.clone(), drop_literal(p)?))) + .collect::>>()?).wrap()), + }, + Pattern::DLit(b) => Some(language().unparse(&b.value)), + _ => None, + } +} diff --git a/syndicate/src/skeleton.rs b/syndicate/src/skeleton.rs index 3857686..1dbd24a 100644 --- a/syndicate/src/skeleton.rs +++ b/syndicate/src/skeleton.rs @@ -9,8 +9,6 @@ use super::bag; use preserves::value::{Map, NestedValue, Set, Value}; use std::collections::btree_map::Entry; -use std::convert::TryFrom; -use std::convert::TryInto; use std::sync::Arc; use crate::actor::AnyValue; @@ -216,15 +214,15 @@ impl Node { ) -> (usize, &mut Node) { let (guard, members): (Guard, Vec<(PathStep, &ds::Pattern)>) = match pat { ds::Pattern::DCompound(b) => match &**b { - ds::DCompound::Arr { ctor, members } => - (Guard::Seq(usize::try_from(&ctor.arity).unwrap_or(0)), - members.iter().map(|(i, p)| (PathStep::Index(i.try_into().unwrap_or(0)), p)).collect()), - ds::DCompound::Rec { ctor, members } => - (Guard::Rec(ctor.label.clone(), usize::try_from(&ctor.arity).unwrap_or(0)), - members.iter().map(|(i, p)| (PathStep::Index(i.try_into().unwrap_or(0)), p)).collect()), - ds::DCompound::Dict { members, .. } => + ds::DCompound::Arr { items } => + (Guard::Seq(items.len()), + items.iter().enumerate().map(|(i, p)| (PathStep::Index(i), p)).collect()), + ds::DCompound::Rec { label, fields } => + (Guard::Rec(label.clone(), fields.len()), + fields.iter().enumerate().map(|(i, p)| (PathStep::Index(i), p)).collect()), + ds::DCompound::Dict { entries, .. } => (Guard::Map, - members.iter().map(|(k, p)| (PathStep::Key(k.clone()), p)).collect()), + entries.iter().map(|(k, p)| (PathStep::Key(k.clone()), p)).collect()), } ds::Pattern::DBind(b) => { let ds::DBind { pattern, .. } = &**b;