Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
268 changes: 172 additions & 96 deletions analysis/src/class.rs

Large diffs are not rendered by default.

766 changes: 512 additions & 254 deletions analysis/src/concrete.rs

Large diffs are not rendered by default.

718 changes: 446 additions & 272 deletions analysis/src/context.rs

Large diffs are not rendered by default.

51 changes: 39 additions & 12 deletions analysis/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,41 @@ impl Datas {
}

pub fn get_alias(&self, alias: AliasId) -> Option<&Alias> {
self.aliases[alias.0]
.1
.as_ref()
self.aliases[alias.0].1.as_ref()
}

pub fn get_alias_span(&self, alias: AliasId) -> Span {
self.aliases[alias.0].0
}

pub fn declare_data(&mut self, name: SrcNode<Ident>, gen_scope: GenScopeId, attr: &[SrcNode<ast::Attr>]) -> Result<DataId, Error> {
pub fn declare_data(
&mut self,
name: SrcNode<Ident>,
gen_scope: GenScopeId,
attr: &[SrcNode<ast::Attr>],
) -> Result<DataId, Error> {
let id = DataId(self.datas.len(), *name);
if let Err(old) = self.name_lut.try_insert(*name, (name.span(), Ok(id), gen_scope)) {
Err(Error::DuplicateTypeName(*name, old.entry.get().0, name.span()))
if let Err(old) = self
.name_lut
.try_insert(*name, (name.span(), Ok(id), gen_scope))
{
Err(Error::DuplicateTypeName(
*name,
old.entry.get().0,
name.span(),
))
} else {
if let Some(lang) = attr
.iter()
.find(|a| &**a.name == "lang")
.and_then(|a| a.args.as_ref())
{
if lang.iter().find(|a| &**a.name == "go").is_some() { self.lang.go = Some(id); }
if lang.iter().find(|a| &**a.name == "bool").is_some() { self.lang.r#bool = Some(id); }
if lang.iter().find(|a| &**a.name == "go").is_some() {
self.lang.go = Some(id);
}
if lang.iter().find(|a| &**a.name == "bool").is_some() {
self.lang.r#bool = Some(id);
}
}

self.datas.push((name.span(), None, gen_scope, *name));
Expand All @@ -125,13 +139,22 @@ impl Datas {
pub fn check_lang_items(&self) -> Vec<Error> {
let mut errors = Vec::new();

if self.lang.go.is_none() { errors.push(Error::MissingLangItem("go")); }
if self.lang.r#bool.is_none() { errors.push(Error::MissingLangItem("bool")); }
if self.lang.go.is_none() {
errors.push(Error::MissingLangItem("go"));
}
if self.lang.r#bool.is_none() {
errors.push(Error::MissingLangItem("bool"));
}

errors
}

pub fn declare_alias(&mut self, name: Ident, span: Span, gen_scope: GenScopeId) -> Result<AliasId, Error> {
pub fn declare_alias(
&mut self,
name: Ident,
span: Span,
gen_scope: GenScopeId,
) -> Result<AliasId, Error> {
let id = AliasId(self.aliases.len());
if let Err(old) = self.name_lut.try_insert(name, (span, Err(id), gen_scope)) {
Err(Error::DuplicateTypeName(name, old.entry.get().0, span))
Expand All @@ -145,7 +168,11 @@ impl Datas {
let mut errors = Vec::new();
for (cons, _) in &data.cons {
if let Err(old) = self.cons_lut.try_insert(**cons, (cons.span(), id)) {
errors.push(Error::DuplicateConsName(**cons, old.entry.get().0, cons.span()));
errors.push(Error::DuplicateConsName(
**cons,
old.entry.get().0,
cons.span(),
));
}
}
self.datas[id.0].1 = Some(data);
Expand Down
26 changes: 15 additions & 11 deletions analysis/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ impl<'hir, 'a> dot::Labeller<'a, Node, Edge> for CallGraph<'hir> {

impl<'hir, 'a> dot::GraphWalk<'a, Node, Edge> for CallGraph<'hir> {
fn nodes(&'a self) -> dot::Nodes<'a, Node> {
self.ctx.defs
self.ctx
.defs
.iter()
.filter_map(|(id, def)| if def.attr.iter().find(|a| &**a.name == "util").is_none() {
Some((id, *def.name))
} else {
None
.filter_map(|(id, def)| {
if def.attr.iter().find(|a| &**a.name == "util").is_none() {
Some((id, *def.name))
} else {
None
}
})
.collect()
}
Expand All @@ -51,10 +54,7 @@ impl<'hir, 'a> dot::GraphWalk<'a, Node, Edge> for CallGraph<'hir> {
if let hir::Expr::Global(global) = &**expr {
let def = ctx.defs.get(global.0);
if def.attr.iter().find(|a| &**a.name == "util").is_none() {
edges.insert((
parent,
(global.0, *def.name),
));
edges.insert((parent, (global.0, *def.name)));
}
}

Expand All @@ -70,6 +70,10 @@ impl<'hir, 'a> dot::GraphWalk<'a, Node, Edge> for CallGraph<'hir> {
}
edges.into_iter().collect()
}
fn source(&self, e: &Edge) -> Node { e.0 }
fn target(&self, e: &Edge) -> Node { e.1 }
fn source(&self, e: &Edge) -> Node {
e.0
}
fn target(&self, e: &Edge) -> Node {
e.1
}
}
3 changes: 2 additions & 1 deletion analysis/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ impl Defs {
if let Err(old) = self.lut.try_insert(name, (span, id)) {
Err(Error::DuplicateDefName(name, old.entry.get().0, span))
} else {
if let Some(lang) = def.attr
if let Some(lang) = def
.attr
.iter()
.find(|a| &**a.name == "lang")
.and_then(|a| a.args.as_ref())
Expand Down
26 changes: 21 additions & 5 deletions analysis/src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ impl Effects {
}

pub fn iter(&self) -> impl Iterator<Item = (EffectDeclId, &EffectDecl)> {
self.effect_decls.iter().enumerate().map(|(i, eff)| (EffectDeclId(i, *eff.name), eff))
self.effect_decls
.iter()
.enumerate()
.map(|(i, eff)| (EffectDeclId(i, *eff.name), eff))
}

// pub fn iter(&self) -> impl Iterator<Item = (EffectDeclId, &EffectDecl)> {
Expand All @@ -65,9 +68,14 @@ impl Effects {
let id = EffectDeclId(self.effect_decls.len(), *eff.name);
let span = eff.name.span();
if let Err(old) = self.lut.try_insert(*eff.name, (span, Ok(id))) {
Err(Error::DuplicateEffectDecl(*eff.name, old.entry.get().0, span))
Err(Error::DuplicateEffectDecl(
*eff.name,
old.entry.get().0,
span,
))
} else {
if let Some(lang) = eff.attr
if let Some(lang) = eff
.attr
.iter()
.find(|a| &**a.name == "lang")
.and_then(|a| a.args.as_ref())
Expand All @@ -86,7 +94,11 @@ impl Effects {
let id = EffectAliasId(self.effect_aliases.len());
let span = alias.name.span();
if let Err(old) = self.lut.try_insert(*alias.name, (span, Err(id))) {
Err(Error::DuplicateEffectDecl(*alias.name, old.entry.get().0, span))
Err(Error::DuplicateEffectDecl(
*alias.name,
old.entry.get().0,
span,
))
} else {
self.effect_aliases.push(alias);
Ok(id)
Expand All @@ -106,7 +118,11 @@ impl Effects {
self.effect_decls[id.0].recv = Some(recv);
}

pub fn define_alias_effects(&mut self, id: EffectAliasId, effs: Vec<(SrcNode<EffectDeclId>, Vec<TyId>)>) {
pub fn define_alias_effects(
&mut self,
id: EffectAliasId,
effs: Vec<(SrcNode<EffectDeclId>, Vec<TyId>)>,
) {
self.effect_aliases[id.0].effects = Some(effs);
}
}
65 changes: 40 additions & 25 deletions analysis/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ pub enum Error {
WrongNumberOfParams(Span, usize, Span, usize),
NoBranches(Span),
// (obligation, type, obligation_origin, generic_definition
TypeDoesNotFulfil(Option<(ClassId, Vec<TyId>, Vec<Option<EffectId>>)>, TyId, Span, Option<Span>, Span),
TypeDoesNotFulfil(
Option<(ClassId, Vec<TyId>, Vec<Option<EffectId>>)>,
TyId,
Span,
Option<Span>,
Span,
),
CycleWhenResolving(TyId, (ClassId, Vec<TyId>, Vec<Option<EffectId>>), Span),
NoSuchData(SrcNode<Ident>),
NoSuchCons(SrcNode<Ident>),
Expand Down Expand Up @@ -52,28 +58,36 @@ pub enum Error {
}

impl Error {
pub fn write<C: ariadne::Cache<SrcId>>(self, ctx: &Context, cache: C, main_src: SrcId, writer: impl Write) {
use ariadne::{Report, ReportKind, Label, Color, Fmt, Span, Config};
pub fn write<C: ariadne::Cache<SrcId>>(
self,
ctx: &Context,
cache: C,
main_src: SrcId,
writer: impl Write,
) {
use ariadne::{Color, Config, Fmt, Label, Report, ReportKind, Span};

let display = |id| ctx.tys.display(ctx, id);

let display_eff = |id| if let Some(eff) = id {
ctx.tys.display_eff(ctx, eff).to_string()
} else {
format!("!")
let display_eff = |id| {
if let Some(eff) = id {
ctx.tys.display_eff(ctx, eff).to_string()
} else {
format!("!")
}
};

let display_class = |class_id, gen_tys: &[_], gen_effs: &[_]| format!(
"{}{}",
*ctx.classes.get(class_id).name,
gen_tys
.iter()
.map(|ty| format!(" {}", display(*ty)))
.chain(gen_effs
let display_class = |class_id, gen_tys: &[_], gen_effs: &[_]| {
format!(
"{}{}",
*ctx.classes.get(class_id).name,
gen_tys
.iter()
.map(|eff| format!(" {}", display_eff(*eff))))
.collect::<String>(),
);
.map(|ty| format!(" {}", display(*ty)))
.chain(gen_effs.iter().map(|eff| format!(" {}", display_eff(*eff))))
.collect::<String>(),
)
};

let (msg, spans, notes) = match self {
Error::CannotCoerce(x, y, inner, info) => {
Expand Down Expand Up @@ -476,23 +490,24 @@ impl Error {
spans.first().map(|s| s.0.src()).unwrap_or(main_src),
spans.first().map(|s| s.0.start()).unwrap_or(0),
)
.with_code(3)
.with_message(msg);
.with_code(3)
.with_message(msg);

for (i, (span, msg, col)) in spans.into_iter().enumerate() {
report = report.with_label(Label::new(span)
.with_message(msg)
.with_order(i as i32)
.with_color(col));
report = report.with_label(
Label::new(span)
.with_message(msg)
.with_order(i as i32)
.with_color(col),
);
}

for note in notes {
report = report.with_note(note);
}

report
.with_config(Config::default()
.with_compact(false))
.with_config(Config::default().with_compact(false))
.finish()
.write(cache, writer)
.unwrap();
Expand Down
Loading