Skip to content

Commit 9d379ce

Browse files
committed
human_encoding: introduce NamedConstructNode
For now NamedConstructNode has no disconnect right child. A later PR will introduce typed holes, and then we can add disconnect children, but for now we'll just have single-child disconnects in the human readable encoding.
1 parent 64c6ea4 commit 9d379ce

File tree

2 files changed

+194
-3
lines changed

2 files changed

+194
-3
lines changed

src/human_encoding/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ use std::sync::Arc;
3333

3434
pub use self::named_node::NamedCommitNode;
3535

36+
/// Line/column pair
37+
///
38+
/// There is a similar type provided by the `santiago` library but it does not implement
39+
/// `Copy`, among many other traits, which makes it unergonomic to use. Santiago positions
40+
/// can be converted using `.into()`.
41+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
42+
pub struct Position {
43+
line: usize,
44+
column: usize,
45+
}
46+
3647
#[derive(Clone, Debug, PartialEq, Eq)]
3748
pub struct Forest<J: Jet> {
3849
roots: HashMap<Arc<str>, Arc<NamedCommitNode<J>>>,

src/human_encoding/named_node.rs

Lines changed: 183 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@
1414

1515
//! Human-readable Nodes
1616
17-
use crate::dag::{MaxSharing, PostOrderIterItem};
17+
use crate::dag::{InternalSharing, MaxSharing, PostOrderIterItem};
1818
use crate::encode;
19+
use crate::human_encoding::Position;
1920
use crate::jet::Jet;
2021
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};
2225
use crate::{BitWriter, Cmr};
2326

2427
use std::io;
28+
use std::marker::PhantomData;
2529
use std::sync::Arc;
2630

2731
pub type NamedCommitNode<J> = Node<Named<Commit<J>>>;
@@ -50,7 +54,7 @@ impl<J: Jet> node::Marker for Named<Commit<J>> {
5054
pub struct NamedCommitData<J> {
5155
/// Data related to the node itself
5256
internal: Arc<CommitData<J>>,
53-
/// Name assigned to the node
57+
/// Name assigned to the node.
5458
name: Arc<str>,
5559
}
5660

@@ -90,6 +94,182 @@ impl<J: Jet> NamedCommitNode<J> {
9094
}
9195
}
9296

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+
93273
pub struct Namer {
94274
const_idx: usize,
95275
wit_idx: usize,

0 commit comments

Comments
 (0)