Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/new_type_checking' into new_type…
Browse files Browse the repository at this point in the history
…_checking
  • Loading branch information
Vlamonster committed Nov 10, 2023
2 parents ab01208 + 0802e0c commit e3829e8
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 15 deletions.
10 changes: 5 additions & 5 deletions compiler/src/passes/eliminate/eliminate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::passes::eliminate::{EExpr, ETail, PrgEliminated};
use crate::passes::explicate::{CExpr, CTail, PrgExplicated};
use crate::passes::parse::types::Type;
use crate::passes::parse::TypeDef;
use crate::utils::gen_sym::{gen_sym, UniqueSym};
use crate::utils::gen_sym::UniqueSym;
use functor_derive::Functor;
use std::collections::HashMap;

Expand Down Expand Up @@ -80,7 +80,7 @@ fn eliminate_seq<'p>(
let strct = strct.var();
let new_sym = *ctx
.entry((strct, field))
.or_insert_with(|| gen_sym(sym.sym));
.or_insert_with(|| sym.fresh());

return eliminate_seq(
sym,
Expand Down Expand Up @@ -120,10 +120,10 @@ fn eliminate_seq<'p>(
TypeDef::Struct { fields: def_fields } => match bnd {
CExpr::Atom { atm, .. } => {
def_fields.iter().fold(tail, |tail, (field, field_type)| {
let sym_lhs = *ctx.entry((sym, field)).or_insert_with(|| gen_sym(sym.sym));
let sym_lhs = *ctx.entry((sym, field)).or_insert_with(|| sym.fresh());
let sym_rhs = *ctx
.entry((atm.var(), field))
.or_insert_with(|| gen_sym(atm.var().sym));
.or_insert_with(|| atm.var().fresh());

eliminate_seq(
sym_lhs,
Expand All @@ -141,7 +141,7 @@ fn eliminate_seq<'p>(
let field_values = fields.into_iter().collect::<HashMap<_, _>>();

def_fields.iter().fold(tail, |tail, (field, field_type)| {
let sym_lhs = *ctx.entry((sym, field)).or_insert_with(|| gen_sym(sym.sym));
let sym_lhs = *ctx.entry((sym, field)).or_insert_with(|| sym.fresh());
let sym_rhs = field_values[field];

eliminate_seq(
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/passes/eliminate/eliminate_params.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::passes::eliminate::eliminate::Ctx;
use crate::passes::parse::types::Type;
use crate::passes::parse::{Param, TypeDef};
use crate::utils::gen_sym::{gen_sym, UniqueSym};
use crate::utils::gen_sym::UniqueSym;
use std::collections::HashMap;

pub fn eliminate_params<'p>(
Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn flatten_type<'p>(
.flat_map(|(field_name, field_type)| {
let new_sym = *ctx
.entry((sym, field_name))
.or_insert_with(|| gen_sym(sym.sym));
.or_insert_with(|| sym.fresh());

flatten_type(new_sym, field_type, ctx, defs).into_iter()
})
Expand Down
38 changes: 36 additions & 2 deletions compiler/src/utils/gen_sym.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,49 @@
use std::fmt::{Display, Formatter};
use std::marker::PhantomData;
use derive_more::Display;
use std::sync::atomic::{AtomicUsize, Ordering};

static COUNT: AtomicUsize = AtomicUsize::new(0);

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd, Display)]
#[display(fmt = "{sym}.{id}")]
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, Ord, PartialOrd)]
pub struct UniqueSym<'p> {
#[cfg(release)]
pub sym: &'p str,
#[cfg(not(release))]
pub sym: PhantomData<&'p str>,
pub id: usize,
}

impl<'p> UniqueSym<'p> {
pub fn fresh(self) -> Self {
Self {
sym: self.sym,
id: COUNT.fetch_add(1, Ordering::SeqCst),
}
}
}

impl Display for UniqueSym<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
#[cfg(release)]
let r = write!(f, "{}{}", self.sym, self.id);
#[cfg(not(release))]
let r = write!(f, "v{}", self.id);

r
}
}


#[cfg(not(release))]
pub fn gen_sym(_sym: &str) -> UniqueSym<'_> {
UniqueSym {
sym: PhantomData,
id: COUNT.fetch_add(1, Ordering::SeqCst),
}
}

#[cfg(release)]
pub fn gen_sym(sym: &str) -> UniqueSym<'_> {
UniqueSym {
sym,
Expand Down
1 change: 1 addition & 0 deletions compiler/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pub mod expect;
pub mod gen_sym;
pub mod push_map;
pub mod split_test;
pub mod union_find;
137 changes: 137 additions & 0 deletions compiler/src/utils/union_find.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::ops::{Index, IndexMut};

pub struct UnionFind<T> {
parents: Vec<usize>,
data: Vec<T>,
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct UnionIndex(usize);

impl<T> UnionFind<T> {
pub fn new() -> Self {
Self {
parents: Vec::new(),
data: Vec::new(),
}
}

pub fn add(&mut self, value: T) -> UnionIndex {
let index = self.data.len();
self.parents.push(index);
self.data.push(value);
UnionIndex(index)
}

pub fn add_iter(&mut self, values: impl Iterator<Item=T>) -> impl Iterator<Item=UnionIndex> {
let i = self.parents.len();
self.data.extend(values);
self.parents.extend(i..self.data.len());
(i..self.data.len()).into_iter().map(UnionIndex)
}

pub fn find(&mut self, index: UnionIndex) -> UnionIndex {
let mut child = index.0;
let mut parent = self.parents[child];

// early exit if root
if parent == child {
return UnionIndex(parent)
}

let parent_parent = self.parents[parent];

// early exit if one away from root
if parent_parent == parent {
return UnionIndex(parent_parent)
}

let mut child_indexes = vec![child, parent];
child = parent_parent;

// loop until root is found
loop {
parent = self.parents[child];
if parent == child {
break;
}
child_indexes.push(child);
child = parent;
}

// set parent of each child to root
for child_index in child_indexes {
self.parents[child_index] = child
}

UnionIndex(parent)
}

pub fn union(&mut self, a: UnionIndex, b: UnionIndex) -> UnionIndex {
let a_root = self.find(a);
let b_root = self.find(b);
self.parents[b_root.0] = a_root.0;
self.parents[b.0] = a_root.0;
a_root
}

pub fn len(&self) -> usize {
self.data.len()
}
}

impl<T> Index<UnionIndex> for UnionFind<T> {
type Output = T;

fn index(&self, index: UnionIndex) -> &Self::Output {
&self.data[index.0]
}
}

impl<T> IndexMut<UnionIndex> for UnionFind<T> {
fn index_mut(&mut self, index: UnionIndex) -> &mut Self::Output {
&mut self.data[index.0]
}
}

#[cfg(test)]
mod tests {
use itertools::Itertools;
use super::*;

#[test]
fn test_simple() {
let mut uf = UnionFind::new();
let x = uf.add(0);
let y= uf.add(1);

assert_eq!(uf.find(x), x);
assert_eq!(uf.find(y), y);

uf.union(x, y);

assert_eq!(uf.find(x), uf.find(y));
}

#[test]
fn test_iter() {
let mut uf = UnionFind::new();
let ids = uf.add_iter(0..420690);

for (left, _, right) in ids.tuple_windows() {
uf.union(left, right);
}

assert_ne!(uf.find(UnionIndex(0)), uf.find(UnionIndex(1)));

for i in (0..42069).step_by(2) {
assert_eq!(uf.find(UnionIndex(0)), uf.find(UnionIndex(i)))
}

for i in (0..42069).skip(1).step_by(2) {
assert_eq!(uf.find(UnionIndex(1)), uf.find(UnionIndex(i)))
}

assert_ne!(uf.find(UnionIndex(0)), uf.find(UnionIndex(1)));
}
}
10 changes: 4 additions & 6 deletions compiler/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ use std::os::unix::prelude::OpenOptionsExt;
use std::process::{Command, Stdio};
use tempfile::TempDir;
use test_each_file::test_each_file;
use compiler::passes::parse::parse::parse_program;

fn integration([test]: [&str; 1]) {
let tempdir = TempDir::with_prefix("rust-compiler-construction-integration").unwrap();

let (input, expected_output, expected_return, program) = split_test(test);
let (input, expected_output, expected_return, _) = split_test(test);
let expected_return: i64 = expected_return.into();

let input_path = tempdir.path().join("output");
Expand All @@ -23,18 +24,15 @@ fn integration([test]: [&str; 1]) {
.open(input_path)
.unwrap();

program
parse_program(test).unwrap()
.validate()
.unwrap()
.reveal()
.atomize()
.explicate()
.eliminate()
.select()
.add_liveness()
.compute_interference()
.color_interference()
.assign_homes()
.assign()
.patch()
.conclude()
.emit()
Expand Down

0 comments on commit e3829e8

Please sign in to comment.