|
14 | 14 |
|
15 | 15 | //! Human-readable Nodes
|
16 | 16 |
|
17 |
| -use crate::dag::{MaxSharing, PostOrderIterItem}; |
| 17 | +use crate::dag::{InternalSharing, MaxSharing, PostOrderIterItem}; |
18 | 18 | use crate::encode;
|
| 19 | +use crate::human_encoding::Position; |
19 | 20 | use crate::jet::Jet;
|
20 | 21 | use crate::node::{self, Commit, CommitData, CommitNode, Converter, NoDisconnect, NoWitness, Node};
|
21 |
| -use crate::types::arrow::FinalArrow; |
| 22 | +use crate::node::{Construct, ConstructData, Constructible}; |
| 23 | +use crate::types; |
| 24 | +use crate::types::arrow::{Arrow, FinalArrow}; |
22 | 25 | use crate::{BitWriter, Cmr};
|
23 | 26 |
|
24 | 27 | use std::io;
|
| 28 | +use std::marker::PhantomData; |
25 | 29 | use std::sync::Arc;
|
26 | 30 |
|
27 | 31 | pub type NamedCommitNode<J> = Node<Named<Commit<J>>>;
|
@@ -50,7 +54,7 @@ impl<J: Jet> node::Marker for Named<Commit<J>> {
|
50 | 54 | pub struct NamedCommitData<J> {
|
51 | 55 | /// Data related to the node itself
|
52 | 56 | internal: Arc<CommitData<J>>,
|
53 |
| - /// Name assigned to the node |
| 57 | + /// Name assigned to the node. |
54 | 58 | name: Arc<str>,
|
55 | 59 | }
|
56 | 60 |
|
@@ -90,6 +94,182 @@ impl<J: Jet> NamedCommitNode<J> {
|
90 | 94 | }
|
91 | 95 | }
|
92 | 96 |
|
| 97 | +pub type NamedConstructNode<J> = Node<Named<Construct<J>>>; |
| 98 | + |
| 99 | +impl<J: Jet> node::Marker for Named<Construct<J>> { |
| 100 | + type CachedData = NamedConstructData<J>; |
| 101 | + type Witness = <Construct<J> as node::Marker>::Witness; |
| 102 | + type Disconnect = NoDisconnect; |
| 103 | + type SharingId = Arc<str>; |
| 104 | + type Jet = J; |
| 105 | + |
| 106 | + fn compute_sharing_id(_: Cmr, cached_data: &Self::CachedData) -> Option<Arc<str>> { |
| 107 | + Some(Arc::clone(&cached_data.name)) |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +#[derive(Clone, Debug)] |
| 112 | +pub struct NamedConstructData<J> { |
| 113 | + /// Data related to the node itself |
| 114 | + internal: ConstructData<J>, |
| 115 | + /// Name assigned to the node |
| 116 | + name: Arc<str>, |
| 117 | + /// Position of the node, if it comes from source code. |
| 118 | + position: Position, |
| 119 | + /// User-provided type bounds on the source (will be checked for consistency |
| 120 | + /// but only after the type checking has completed.) |
| 121 | + user_source_types: Arc<[types::Type]>, |
| 122 | + /// User-provided type bounds on the target (will be checked for consistency |
| 123 | + /// but only after the type checking has completed.) |
| 124 | + user_target_types: Arc<[types::Type]>, |
| 125 | +} |
| 126 | + |
| 127 | +impl<J: Jet> NamedConstructNode<J> { |
| 128 | + /// Construct a named construct node from parts. |
| 129 | + pub fn new( |
| 130 | + name: Arc<str>, |
| 131 | + position: Position, |
| 132 | + user_source_types: Arc<[types::Type]>, |
| 133 | + user_target_types: Arc<[types::Type]>, |
| 134 | + inner: node::Inner<Arc<Self>, J, NoDisconnect, NoWitness>, |
| 135 | + ) -> Result<Self, types::Error> { |
| 136 | + let construct_data = ConstructData::from_inner( |
| 137 | + inner |
| 138 | + .as_ref() |
| 139 | + .map(|data| &data.cached_data().internal) |
| 140 | + .map_disconnect(|_| &None) |
| 141 | + .copy_witness(), |
| 142 | + )?; |
| 143 | + let named_data = NamedConstructData { |
| 144 | + internal: construct_data, |
| 145 | + name, |
| 146 | + position, |
| 147 | + user_source_types, |
| 148 | + user_target_types, |
| 149 | + }; |
| 150 | + Ok(Node::from_parts(inner, named_data)) |
| 151 | + } |
| 152 | + |
| 153 | + /// Accessor for the node's name |
| 154 | + pub fn name(&self) -> &Arc<str> { |
| 155 | + &self.cached_data().name |
| 156 | + } |
| 157 | + |
| 158 | + /// Accessor for the node's position |
| 159 | + pub fn position(&self) -> Position { |
| 160 | + self.cached_data().position |
| 161 | + } |
| 162 | + |
| 163 | + /// Accessor for the node's arrow |
| 164 | + pub fn arrow(&self) -> &Arrow { |
| 165 | + self.cached_data().internal.arrow() |
| 166 | + } |
| 167 | + |
| 168 | + /// Finalizes the types of the underlying [`ConstructNode`]. |
| 169 | + pub fn finalize_types_main(&self) -> Result<Arc<NamedCommitNode<J>>, types::Error> { |
| 170 | + self.finalize_types_inner(true) |
| 171 | + } |
| 172 | + |
| 173 | + /// Finalizes the types of the underlying [`ConstructNode`], without setting |
| 174 | + /// the root node's arrow to 1->1. |
| 175 | + pub fn finalize_types_non_main(&self) -> Result<Arc<NamedCommitNode<J>>, types::Error> { |
| 176 | + self.finalize_types_inner(false) |
| 177 | + } |
| 178 | + |
| 179 | + pub fn finalize_types_inner( |
| 180 | + &self, |
| 181 | + for_main: bool, |
| 182 | + ) -> Result<Arc<NamedCommitNode<J>>, types::Error> { |
| 183 | + struct FinalizeTypes<J: Jet> { |
| 184 | + for_main: bool, |
| 185 | + phantom: PhantomData<J>, |
| 186 | + } |
| 187 | + |
| 188 | + impl<J: Jet> Converter<Named<Construct<J>>, Named<Commit<J>>> for FinalizeTypes<J> { |
| 189 | + type Error = types::Error; |
| 190 | + fn convert_witness( |
| 191 | + &mut self, |
| 192 | + _: &PostOrderIterItem<&NamedConstructNode<J>>, |
| 193 | + _: &NoWitness, |
| 194 | + ) -> Result<NoWitness, Self::Error> { |
| 195 | + Ok(NoWitness) |
| 196 | + } |
| 197 | + |
| 198 | + fn convert_disconnect( |
| 199 | + &mut self, |
| 200 | + _: &PostOrderIterItem<&NamedConstructNode<J>>, |
| 201 | + _: Option<&Arc<NamedCommitNode<J>>>, |
| 202 | + _: &NoDisconnect, |
| 203 | + ) -> Result<NoDisconnect, Self::Error> { |
| 204 | + Ok(NoDisconnect) |
| 205 | + } |
| 206 | + |
| 207 | + fn convert_data( |
| 208 | + &mut self, |
| 209 | + data: &PostOrderIterItem<&NamedConstructNode<J>>, |
| 210 | + inner: node::Inner<&Arc<NamedCommitNode<J>>, J, &NoDisconnect, &NoWitness>, |
| 211 | + ) -> Result<NamedCommitData<J>, Self::Error> { |
| 212 | + let converted_data = inner.map(|node| &node.cached_data().internal); |
| 213 | + |
| 214 | + if !self.for_main { |
| 215 | + // For non-`main` fragments, treat the ascriptions as normative, and apply them |
| 216 | + // before finalizing the type. |
| 217 | + let arrow = data.node.arrow(); |
| 218 | + for ty in data.node.cached_data().user_source_types.as_ref() { |
| 219 | + arrow.source.unify(ty, "binding source type annotation")?; |
| 220 | + } |
| 221 | + for ty in data.node.cached_data().user_target_types.as_ref() { |
| 222 | + arrow.target.unify(ty, "binding target type annotation")?; |
| 223 | + } |
| 224 | + } |
| 225 | + |
| 226 | + let commit_data = Arc::new(CommitData::new(data.node.arrow(), converted_data)?); |
| 227 | + |
| 228 | + if self.for_main { |
| 229 | + // For `main`, only apply type ascriptions *after* inference has completely |
| 230 | + // determined the type. |
| 231 | + let source_bound = |
| 232 | + types::Bound::Complete(Arc::clone(&commit_data.arrow().source)); |
| 233 | + let source_ty = types::Type::from(source_bound); |
| 234 | + for ty in data.node.cached_data().user_source_types.as_ref() { |
| 235 | + source_ty.unify(ty, "binding source type annotation")?; |
| 236 | + } |
| 237 | + let target_bound = |
| 238 | + types::Bound::Complete(Arc::clone(&commit_data.arrow().target)); |
| 239 | + let target_ty = types::Type::from(target_bound); |
| 240 | + for ty in data.node.cached_data().user_target_types.as_ref() { |
| 241 | + target_ty.unify(ty, "binding target type annotation")?; |
| 242 | + } |
| 243 | + } |
| 244 | + |
| 245 | + Ok(NamedCommitData { |
| 246 | + name: Arc::clone(&data.node.cached_data().name), |
| 247 | + internal: commit_data, |
| 248 | + }) |
| 249 | + } |
| 250 | + } |
| 251 | + |
| 252 | + if for_main { |
| 253 | + let unit_ty = types::Type::unit(); |
| 254 | + if self.cached_data().user_source_types.is_empty() { |
| 255 | + self.arrow() |
| 256 | + .source |
| 257 | + .unify(&unit_ty, "setting root source to unit")?; |
| 258 | + } |
| 259 | + if self.cached_data().user_target_types.is_empty() { |
| 260 | + self.arrow() |
| 261 | + .target |
| 262 | + .unify(&unit_ty, "setting root source to unit")?; |
| 263 | + } |
| 264 | + } |
| 265 | + |
| 266 | + self.convert::<InternalSharing, _, _>(&mut FinalizeTypes { |
| 267 | + for_main, |
| 268 | + phantom: PhantomData, |
| 269 | + }) |
| 270 | + } |
| 271 | +} |
| 272 | + |
93 | 273 | pub struct Namer {
|
94 | 274 | const_idx: usize,
|
95 | 275 | wit_idx: usize,
|
|
0 commit comments