Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use patterns in more of the ast #270

Merged
merged 5 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions src/net/hvmc_to_net.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{INet, INode, INodes, NodeId, NodeKind::*, Port, SlotId, ROOT};
use crate::term::Name;
use crate::{
net::{CtrKind, NodeKind},
term::Name,
};
use hvmc::ast::{Net, Tree};

pub fn hvmc_to_net(net: &Net) -> INet {
Expand Down Expand Up @@ -88,15 +91,7 @@ fn tree_to_inodes(tree: &Tree, tree_root: String, net_root: &str, n_vars: &mut N
subtrees.push((principal, &ports[0]));
} else {
// build a 2-ary node
let kind = if lab == 0 {
Con { lab: None }
} else if lab == 1 {
Tup
} else if lab & 1 == 0 {
Con { lab: Some((lab as u32 >> 1) - 1) }
} else {
Dup { lab: (lab as u32 >> 1) - 1 }
};
let kind = NodeKind::Ctr(CtrKind::from_lab(lab));
let rgt = process_sub_ctr(inodes, lab, &ports[1 ..], net_root, subtrees, n_vars);
let lft = process_node_subtree(&ports[0], net_root, subtrees, n_vars);
inodes.push(INode { kind, ports: [principal.clone(), lft.clone(), rgt.clone()] });
Expand Down Expand Up @@ -136,7 +131,7 @@ fn tree_to_inodes(tree: &Tree, tree_root: String, net_root: &str, n_vars: &mut N
let zero = process_node_subtree(zero, net_root, &mut subtrees, n_vars);
let succ = process_node_subtree(succ, net_root, &mut subtrees, n_vars);
let sel_var = new_var(n_vars);
inodes.push(INode { kind: Con { lab: None }, ports: [sel_var.clone(), zero, succ] });
inodes.push(INode { kind: NodeKind::Ctr(CtrKind::Con(None)), ports: [sel_var.clone(), zero, succ] });
let ret = process_node_subtree(out, net_root, &mut subtrees, n_vars);
inodes.push(INode { kind, ports: [subtree_root, sel_var, ret] });
}
Expand Down
54 changes: 36 additions & 18 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod hvmc_to_net;
pub mod net_to_hvmc;

use crate::term::Name;
pub type HvmlLab = u32;
pub type HvmlLab = u16;
use NodeKind::*;

#[derive(Debug, Clone)]
Expand All @@ -28,30 +28,48 @@ pub enum NodeKind {
Rot,
/// Erasure nodes
Era,
/// Lambdas and applications
Con {
lab: Option<HvmlLab>,
},
Tup,
Dup {
lab: HvmlLab,
},
/// Binary combinators
Ctr(CtrKind),
/// Reference to function definitions
Ref {
def_name: Name,
},
Ref { def_name: Name },
/// Numbers
Num {
val: u64,
},
Num { val: u64 },
/// Numeric operations
Op2 {
opr: hvmc::ops::Op,
},
Op2 { opr: hvmc::ops::Op },
/// Pattern matching on numbers
Mat,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CtrKind {
Con(Option<HvmlLab>),
Tup(Option<HvmlLab>),
Dup(HvmlLab),
}

impl CtrKind {
fn to_lab(self) -> HvmlLab {
#[allow(clippy::identity_op)]
match self {
CtrKind::Con(None) => 0,
CtrKind::Con(Some(x)) => ((x + 1) << 2) | 0b00,
CtrKind::Tup(None) => 1,
CtrKind::Tup(Some(x)) => ((x + 1) << 2) | 0b01,
CtrKind::Dup(x) => (x << 2) | 0b10,
}
}
fn from_lab(lab: u16) -> Self {
match (lab >> 2, lab & 0b11) {
(0, 0b00) => CtrKind::Con(None),
(x, 0b00) => CtrKind::Con(Some(x - 1)),
(0, 0b01) => CtrKind::Tup(None),
(x, 0b01) => CtrKind::Tup(Some(x - 1)),
(x, 0b10) => CtrKind::Dup(x),
_ => unreachable!(),
}
}
}

pub type NodeId = u64;
pub type SlotId = u64;

Expand Down
30 changes: 4 additions & 26 deletions src/net/net_to_hvmc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{INet, NodeId, NodeKind, Port, ROOT};
use super::{CtrKind, INet, NodeId, NodeKind, Port, ROOT};

use crate::{
diagnostics::{Diagnostics, ToStringVerbose},
Expand Down Expand Up @@ -49,30 +49,8 @@ pub fn net_to_hvmc(inet: &INet) -> Result<Net, ViciousCycleErr> {
fn net_tree_to_hvmc_tree(inet: &INet, tree_root: NodeId, port_to_var_id: &mut HashMap<Port, VarId>) -> Tree {
match &inet.node(tree_root).kind {
NodeKind::Era => Tree::Era,
NodeKind::Con { lab: None } => Tree::Ctr {
lab: 0,
ports: vec![
var_or_subtree(inet, Port(tree_root, 1), port_to_var_id),
var_or_subtree(inet, Port(tree_root, 2), port_to_var_id),
],
},
NodeKind::Tup => Tree::Ctr {
lab: 1,
ports: vec![
var_or_subtree(inet, Port(tree_root, 1), port_to_var_id),
var_or_subtree(inet, Port(tree_root, 2), port_to_var_id),
],
},
NodeKind::Con { lab: Some(lab) } => Tree::Ctr {
#[allow(clippy::identity_op)]
lab: (*lab as u16 + 1) << 1 | 0,
ports: vec![
var_or_subtree(inet, Port(tree_root, 1), port_to_var_id),
var_or_subtree(inet, Port(tree_root, 2), port_to_var_id),
],
},
NodeKind::Dup { lab } => Tree::Ctr {
lab: (*lab as u16 + 1) << 1 | 1,
NodeKind::Ctr(kind) => Tree::Ctr {
lab: kind.to_lab(),
ports: vec![
var_or_subtree(inet, Port(tree_root, 1), port_to_var_id),
var_or_subtree(inet, Port(tree_root, 2), port_to_var_id),
Expand All @@ -87,7 +65,7 @@ fn net_tree_to_hvmc_tree(inet: &INet, tree_root: NodeId, port_to_var_id: &mut Ha
},
NodeKind::Mat => {
let node = inet.node(inet.enter_port(Port(tree_root, 1)).node());
if node.kind != (NodeKind::Con { lab: None }) {
if node.kind != NodeKind::Ctr(CtrKind::Con(None)) {
panic!("hvm-lang produced an INet where the first port is not a Con node. This is not supported.");
}

Expand Down
5 changes: 2 additions & 3 deletions src/term/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,11 @@ impl Pattern {
match self {
Pattern::Lst(pats) => *self = Self::encode_list(std::mem::take(pats)),
Pattern::Str(str) => *self = Self::encode_str(str),
Pattern::Ctr(_, pats) | Pattern::Tup(pats) => {
for pat in pats {
_ => {
for pat in self.children_mut() {
pat.encode_builtins();
}
}
Pattern::Var(..) | Pattern::Num(..) => {}
}
}

Expand Down
28 changes: 19 additions & 9 deletions src/term/check/unbound_vars.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
diagnostics::{Diagnostics, ToStringVerbose},
maybe_grow,
term::{Ctx, Name, Term},
term::{Ctx, Name, Pattern, Term},
};
use std::collections::{hash_map::Entry, HashMap};

Expand Down Expand Up @@ -60,7 +60,7 @@ impl Term {
pub fn check_uses<'a>(
term: &'a mut Term,
scope: &mut HashMap<&'a Name, u64>,
globals: &mut HashMap<&'a Name, (usize, usize)>,
globals: &mut HashMap<Name, (usize, usize)>,
errs: &mut Vec<UnboundVarErr>,
) {
maybe_grow(move || match term {
Expand All @@ -70,17 +70,14 @@ pub fn check_uses<'a>(
*term = Term::Err;
}
}
Term::Chn { nam, bod, .. } => {
if let Some(nam) = nam {
globals.entry(nam).or_default().0 += 1;
}
check_uses(bod, scope, globals, errs);
}
Term::Lnk { nam } => {
globals.entry(nam).or_default().1 += 1;
globals.entry(nam.clone()).or_default().1 += 1;
}

_ => {
if let Some(pat) = term.pattern() {
check_global_binds(pat, globals)
}
for (child, binds) in term.children_mut_with_binds() {
for bind in binds.clone() {
push_scope(bind.as_ref(), scope);
Expand All @@ -94,6 +91,19 @@ pub fn check_uses<'a>(
})
}

pub fn check_global_binds(pat: &Pattern, globals: &mut HashMap<Name, (usize, usize)>) {
match pat {
Pattern::Chn(nam) => {
globals.entry(nam.clone()).or_default().0 += 1;
}
_ => {
for child in pat.children() {
check_global_binds(child, globals)
}
}
}
}

fn push_scope<'a>(nam: Option<&'a Name>, scope: &mut HashMap<&'a Name, u64>) {
if let Some(nam) = nam {
*scope.entry(nam).or_default() += 1;
Expand Down
77 changes: 17 additions & 60 deletions src/term/display.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Book, Definition, Name, Pattern, Rule, Tag, Term};
use super::{Book, Definition, FanKind, Name, Pattern, Rule, Tag, Term};
use crate::maybe_grow;
use std::{fmt, ops::Deref};

Expand Down Expand Up @@ -43,16 +43,13 @@ macro_rules! display {
impl fmt::Display for Term {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
maybe_grow(|| match self {
Term::Lam { tag, nam, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), var_as_str(nam), bod)
Term::Lam { tag, pat, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), pat, bod)
}
Term::Var { nam } => write!(f, "{nam}"),
Term::Chn { tag, nam, bod } => {
write!(f, "{}λ${} {}", tag.display_padded(), var_as_str(nam), bod)
}
Term::Lnk { nam } => write!(f, "${nam}"),
Term::Let { nam, val, nxt } => {
write!(f, "let {} = {}; {}", var_as_str(nam), val, nxt)
Term::Let { pat, val, nxt } => {
write!(f, "let {} = {}; {}", pat, val, nxt)
}
Term::Use { nam, val, nxt } => {
let Some(nam) = nam else { unreachable!() };
Expand Down Expand Up @@ -93,16 +90,8 @@ impl fmt::Display for Term {
);
write!(f, "switch {} = {}{} {{ {} }}", bnd.as_ref().unwrap(), arg, with, arms)
}
Term::Ltp { bnd, val, nxt } => {
write!(f, "let ({}) = {}; {}", DisplayJoin(|| bnd.iter().map(var_as_str), ", "), val, nxt)
}
Term::Tup { els } => write!(f, "({})", DisplayJoin(|| els.iter(), ", "),),
Term::Dup { tag, bnd, val, nxt } => {
write!(f, "let {}{{{}}} = {}; {}", tag, DisplayJoin(|| bnd.iter().map(var_as_str), " "), val, nxt)
}
Term::Sup { tag, els } => {
write!(f, "{}{{{}}}", tag, DisplayJoin(|| els, " "))
}
Term::Fan { fan: FanKind::Tup, tag, els } => write!(f, "{}({})", tag, DisplayJoin(|| els.iter(), ", ")),
Term::Fan { fan: FanKind::Dup, tag, els } => write!(f, "{}{{{}}}", tag, DisplayJoin(|| els, " ")),
Term::Era => write!(f, "*"),
Term::Num { val } => write!(f, "{val}"),
Term::Nat { val } => write!(f, "#{val}"),
Expand Down Expand Up @@ -132,11 +121,13 @@ impl fmt::Display for Pattern {
match self {
Pattern::Var(None) => write!(f, "*"),
Pattern::Var(Some(nam)) => write!(f, "{nam}"),
Pattern::Chn(nam) => write!(f, "${nam}"),
Pattern::Ctr(nam, pats) => {
write!(f, "({}{})", nam, DisplayJoin(|| pats.iter().map(|p| display!(" {p}")), ""))
}
Pattern::Num(num) => write!(f, "{num}"),
Pattern::Tup(pats) => write!(f, "({})", DisplayJoin(|| pats, ", ")),
Pattern::Fan(FanKind::Tup, tag, pats) => write!(f, "{}({})", tag, DisplayJoin(|| pats, ", ")),
Pattern::Fan(FanKind::Dup, tag, pats) => write!(f, "{}{{{}}}", tag, DisplayJoin(|| pats, " ")),
Pattern::Lst(pats) => write!(f, "[{}]", DisplayJoin(|| pats, ", ")),
Pattern::Str(str) => write!(f, "\"{str}\""),
}
Expand Down Expand Up @@ -229,27 +220,16 @@ impl Term {
pub fn display_pretty(&self, tab: usize) -> impl fmt::Display + '_ {
maybe_grow(|| {
DisplayFn(move |f| match self {
Term::Lam { tag, nam, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), var_as_str(nam), bod.display_pretty(tab))
Term::Lam { tag, pat, bod } => {
write!(f, "{}λ{} {}", tag.display_padded(), pat, bod.display_pretty(tab))
}

Term::Var { nam } => write!(f, "{nam}"),

Term::Chn { tag, nam, bod } => {
write!(f, "{}λ${} {}", tag, var_as_str(nam), bod.display_pretty(tab))
}

Term::Lnk { nam } => write!(f, "${nam}"),

Term::Let { nam, val, nxt } => {
write!(
f,
"let {} = {};\n{:tab$}{}",
var_as_str(nam),
val.display_pretty(tab),
"",
nxt.display_pretty(tab)
)
Term::Let { pat, val, nxt } => {
write!(f, "let {} = {};\n{:tab$}{}", pat, val.display_pretty(tab), "", nxt.display_pretty(tab))
}

Term::Use { nam, val, nxt } => {
Expand All @@ -273,34 +253,11 @@ impl Term {
)
}

Term::Ltp { bnd, val, nxt } => {
write!(
f,
"let ({}) = {};\n{:tab$}{}",
DisplayJoin(|| bnd.iter().map(var_as_str), ", "),
val.display_pretty(tab),
"",
nxt.display_pretty(tab),
)
}

Term::Tup { els } => {
write!(f, "({})", DisplayJoin(|| els.iter().map(|e| e.display_pretty(tab)), " "))
}

Term::Dup { tag, bnd, val, nxt } => {
write!(
f,
"let {}{{{}}} = {};\n{:tab$}{}",
tag.display_padded(),
DisplayJoin(|| bnd.iter().map(var_as_str), " "),
val.display_pretty(tab),
"",
nxt.display_pretty(tab),
)
Term::Fan { fan: FanKind::Tup, tag, els } => {
write!(f, "{}({})", tag, DisplayJoin(|| els.iter().map(|e| e.display_pretty(tab)), ", "))
}

Term::Sup { tag, els } => {
Term::Fan { fan: FanKind::Dup, tag, els } => {
write!(
f,
"{}{{{}}}",
Expand Down
Loading
Loading