Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
yannham committed Dec 12, 2024
1 parent a5708aa commit f9eecb4
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 299 deletions.
10 changes: 10 additions & 0 deletions core/src/bytecode/ast/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub enum TailPattern {
}

impl Pattern<'_> {
/// Creates an `Any` pattern with the corresponding capture name.
pub fn any(id: LocIdent) -> Self {
let pos = id.pos;

Expand All @@ -140,6 +141,15 @@ impl Pattern<'_> {
pos,
}
}

/// Returns `Some(id)` if this pattern is an [DataPattern::Any] pattern, `None` otherwise.
pub fn try_as_any(&self) -> Option<LocIdent> {
if let PatternData::Any(id) = &self.data {
Some(*id)
} else {
None
}
}
}

impl TailPattern {
Expand Down
27 changes: 21 additions & 6 deletions core/src/bytecode/ast/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<'ast> FieldPathElem<'ast> {
alloc.alloc_singleton(FieldPathElem::Ident(ident))
}

/// Crate a path composed of a single dynamic expression.
/// Create a path composed of a single dynamic expression.
pub fn single_expr_path(alloc: &'ast AstAlloc, expr: Ast<'ast>) -> &'ast [FieldPathElem<'ast>] {
alloc.alloc_singleton(FieldPathElem::Expr(expr))
}
Expand All @@ -48,9 +48,10 @@ impl<'ast> FieldPathElem<'ast> {
pub fn try_as_ident(&self) -> Option<LocIdent> {
match self {
FieldPathElem::Ident(ident) => Some(*ident),
FieldPathElem::Expr(expr) => {
expr.node.try_str_chunk_as_static_str().map(LocIdent::from)
}
FieldPathElem::Expr(expr) => expr
.node
.try_str_chunk_as_static_str()
.map(|s| LocIdent::from(s).with_pos(expr.pos)),
}
}
}
Expand All @@ -62,9 +63,9 @@ pub struct FieldDef<'ast> {
/// A sequence of field path elements, composing the left hand side (with respect to the `=`)
/// of the field definition.
///
/// # Invariant
/// # Invariants
///
/// **Important**: The path must be non-empty, or some
/// **Important**: The path must be non-empty, or some of `FieldDef` methods will panic.
pub path: &'ast [FieldPathElem<'ast>],
/// The metadata and the optional value bundled as a field.
pub metadata: FieldMetadata<'ast>,
Expand All @@ -83,6 +84,12 @@ impl FieldDef<'_> {
None
}
}

/// Try to get the declared field name, that is the last element of the path, as a static
/// identifier.
pub fn name_as_ident(&self) -> Option<LocIdent> {
self.path.last().expect("empty field path").try_as_ident()
}
}

/// The metadata attached to record fields.
Expand Down Expand Up @@ -143,4 +150,12 @@ impl Record<'_> {
pub fn open(self) -> Self {
Record { open: true, ..self }
}

/// Returns `false` if at least one field in the first layer of the record (that is the first
/// element of each field path) is defined dynamically, and `true` otherwise.
pub fn has_static_structure(&self) -> bool {
self.field_defs
.iter()
.all(|field| field.path.iter().any(|elem| elem.try_as_ident().is_some()))
}
}
10 changes: 10 additions & 0 deletions core/src/bytecode/typecheck/mk_uniftype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ pub fn arrow<'ast>(
))
}

pub fn nary_arrow<'ast, I, U>(args: I, codomain: U) -> UnifType<'ast>
where
U: Into<UnifType<'ast>>,
I: IntoIterator<Item: Into<UnifType<'ast>>, IntoIter: std::iter::DoubleEndedIterator>,
{
args.into_iter()
.rev()
.fold(codomain.into(), |acc, ty| mk_buty_arrow!(ty.into(), acc))
}

// dyn is a reserved keyword
generate_builder!(dynamic, Dyn);
generate_builder!(str, String);
Expand Down
Loading

0 comments on commit f9eecb4

Please sign in to comment.