Skip to content

Commit

Permalink
Add context completion
Browse files Browse the repository at this point in the history
  • Loading branch information
jneem committed Sep 11, 2023
1 parent 0c01499 commit 73b9f10
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 145 deletions.
97 changes: 67 additions & 30 deletions core/src/term/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,12 @@ impl Traverse<RichTerm> for RuntimeContract {
Ok(RuntimeContract { contract, ..self })
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
self.contract.traverse_ref(f)
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
self.contract.traverse_ref(f, state)
}
}

Expand Down Expand Up @@ -455,8 +459,12 @@ impl Traverse<RichTerm> for LabeledType {
.map(|typ| LabeledType { typ, label })
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
self.typ.traverse_ref(f)
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
self.typ.traverse_ref(f, state)
}
}

Expand Down Expand Up @@ -568,11 +576,15 @@ impl Traverse<RichTerm> for TypeAnnotation {
Ok(TypeAnnotation { typ, contracts })
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
self.contracts
.iter()
.find_map(|c| c.traverse_ref(f))
.or_else(|| self.typ.as_ref().and_then(|t| t.traverse_ref(f)))
.find_map(|c| c.traverse_ref(f, state))
.or_else(|| self.typ.as_ref().and_then(|t| t.traverse_ref(f, state)))
}
}

Expand Down Expand Up @@ -1539,16 +1551,19 @@ impl RichTerm {
}

/// Flow control for tree traverals.
pub enum TraverseControl<U> {
/// Normal control flow: continue recursing into the children.
pub enum TraverseControl<S, U> {
Continue,
/// Normal control flow: continue recursing into the children.
///
/// Pass the state &S to all children.
ContinueWithState(S),
/// Skip this branch of the tree.
SkipBranch,
/// Finish traversing immediately (and return a value).
Return(U),
}

impl<U> From<Option<U>> for TraverseControl<U> {
impl<S, U> From<Option<U>> for TraverseControl<S, U> {
fn from(value: Option<U>) -> Self {
match value {
Some(u) => TraverseControl::Return(u),
Expand All @@ -1571,7 +1586,11 @@ pub trait Traverse<T>: Sized {
///
/// Through its return value, `f` can short-circuit one branch of the traversal or
/// the entire traversal.
fn traverse_ref<U>(&self, f: &mut dyn FnMut(&T) -> TraverseControl<U>) -> Option<U>;
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&T, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U>;
}

impl Traverse<RichTerm> for RichTerm {
Expand Down Expand Up @@ -1758,16 +1777,22 @@ impl Traverse<RichTerm> for RichTerm {
}
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
match f(self) {
TraverseControl::Continue => {}
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
let child_state = match f(self, state) {
TraverseControl::Continue => None,
TraverseControl::ContinueWithState(s) => Some(s),
TraverseControl::SkipBranch => {
return None;
}
TraverseControl::Return(ret) => {
return Some(ret);
}
};
let state = child_state.as_ref().unwrap_or(state);

match &*self.term {
Term::Null
Expand All @@ -1784,37 +1809,45 @@ impl Traverse<RichTerm> for RichTerm {
| Term::RuntimeError(_) => None,
Term::StrChunks(chunks) => chunks.iter().find_map(|ch| {
if let StrChunk::Expr(term, _) = ch {
term.traverse_ref(f)
term.traverse_ref(f, state)
} else {
None
}
}),
Term::Fun(_, t)
| Term::FunPattern(_, _, t)
| Term::Op1(_, t)
| Term::Sealed(_, t, _) => t.traverse_ref(f),
| Term::Sealed(_, t, _) => t.traverse_ref(f, state),
Term::Let(_, t1, t2, _)
| Term::LetPattern(_, _, t1, t2)
| Term::App(t1, t2)
| Term::Op2(_, t1, t2) => t1.traverse_ref(f).or_else(|| t2.traverse_ref(f)),
Term::Record(data) => data.fields.values().find_map(|field| field.traverse_ref(f)),
| Term::Op2(_, t1, t2) => t1
.traverse_ref(f, state)
.or_else(|| t2.traverse_ref(f, state)),
Term::Record(data) => data
.fields
.values()
.find_map(|field| field.traverse_ref(f, state)),
Term::RecRecord(data, dyn_data, _) => data
.fields
.values()
.find_map(|field| field.traverse_ref(f))
.find_map(|field| field.traverse_ref(f, state))
.or_else(|| {
dyn_data.iter().find_map(|(id, field)| {
id.traverse_ref(f).or_else(|| field.traverse_ref(f))
id.traverse_ref(f, state)
.or_else(|| field.traverse_ref(f, state))
})
}),
Term::Match { cases, default } => cases
.iter()
.find_map(|(_id, t)| t.traverse_ref(f))
.or_else(|| default.as_ref().and_then(|t| t.traverse_ref(f))),
Term::Array(ts, _) => ts.iter().find_map(|t| t.traverse_ref(f)),
Term::OpN(_, ts) => ts.iter().find_map(|t| t.traverse_ref(f)),
Term::Annotated(annot, t) => t.traverse_ref(f).or_else(|| annot.traverse_ref(f)),
Term::Type(ty) => ty.traverse_ref(f),
.find_map(|(_id, t)| t.traverse_ref(f, state))
.or_else(|| default.as_ref().and_then(|t| t.traverse_ref(f, state))),
Term::Array(ts, _) => ts.iter().find_map(|t| t.traverse_ref(f, state)),
Term::OpN(_, ts) => ts.iter().find_map(|t| t.traverse_ref(f, state)),
Term::Annotated(annot, t) => t
.traverse_ref(f, state)
.or_else(|| annot.traverse_ref(f, state)),
Term::Type(ty) => ty.traverse_ref(f, state),
}
}
}
Expand All @@ -1833,12 +1866,16 @@ impl Traverse<Type> for RichTerm {
self.traverse(&f_on_term, state, order)
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&Type) -> TraverseControl<U>) -> Option<U> {
let mut f_on_term = |rt: &RichTerm| match &*rt.term {
Term::Type(ty) => ty.traverse_ref(f).into(),
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&Type, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
let mut f_on_term = |rt: &RichTerm, state: &S| match &*rt.term {
Term::Type(ty) => ty.traverse_ref(f, state).into(),
_ => TraverseControl::Continue,
};
self.traverse_ref(&mut f_on_term)
self.traverse_ref(&mut f_on_term, state)
}
}

Expand Down
12 changes: 8 additions & 4 deletions core/src/term/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,19 @@ impl Traverse<RichTerm> for Field {
})
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
self.metadata
.annotation
.traverse_ref(f)
.or_else(|| self.value.as_ref().and_then(|v| v.traverse_ref(f)))
.traverse_ref(f, state)
.or_else(|| self.value.as_ref().and_then(|v| v.traverse_ref(f, state)))
.or_else(|| {
self.pending_contracts
.iter()
.find_map(|c| c.traverse_ref(f))
.find_map(|c| c.traverse_ref(f, state))
})
}
}
Expand Down
58 changes: 39 additions & 19 deletions core/src/typ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,11 +625,16 @@ impl Traverse<Type> for RecordRows {
Ok(RecordRows(inner))
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&Type) -> TraverseControl<U>) -> Option<U> {
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&Type, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
match &self.0 {
RecordRowsF::Extend { row, tail } => {
row.typ.traverse_ref(f).or_else(|| tail.traverse_ref(f))
}
RecordRowsF::Extend { row, tail } => row
.typ
.traverse_ref(f, state)
.or_else(|| tail.traverse_ref(f, state)),
_ => None,
}
}
Expand Down Expand Up @@ -1056,10 +1061,13 @@ impl Type {

/// Searches for a `TypeF::Flat`. If one is found, returns the term it contains.
pub fn find_flat(&self) -> Option<RichTerm> {
self.traverse_ref(&mut |ty: &Type| match &ty.typ {
TypeF::Flat(f) => TraverseControl::Return(f.clone()),
_ => TraverseControl::Continue,
})
self.traverse_ref(
&mut |ty: &Type, _: &()| match &ty.typ {
TypeF::Flat(f) => TraverseControl::Return(f.clone()),
_ => TraverseControl::Continue,
},
&(),
)
}
}

Expand Down Expand Up @@ -1099,16 +1107,22 @@ impl Traverse<Type> for Type {
}
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&Type) -> TraverseControl<U>) -> Option<U> {
match f(self) {
TraverseControl::Continue => {}
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&Type, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
let child_state = match f(self, state) {
TraverseControl::Continue => None,
TraverseControl::ContinueWithState(s) => Some(s),
TraverseControl::SkipBranch => {
return None;
}
TraverseControl::Return(ret) => {
return Some(ret);
}
};
let state = child_state.as_ref().unwrap_or(state);

match &self.typ {
TypeF::Dyn
Expand All @@ -1119,12 +1133,14 @@ impl Traverse<Type> for Type {
| TypeF::Var(_)
| TypeF::Enum(_)
| TypeF::Wildcard(_) => None,
TypeF::Flat(rt) => rt.traverse_ref(f),
TypeF::Arrow(t1, t2) => t1.traverse_ref(f).or_else(|| t2.traverse_ref(f)),
TypeF::Flat(rt) => rt.traverse_ref(f, state),
TypeF::Arrow(t1, t2) => t1
.traverse_ref(f, state)
.or_else(|| t2.traverse_ref(f, state)),
TypeF::Forall { body: t, .. }
| TypeF::Dict { type_fields: t, .. }
| TypeF::Array(t) => t.traverse_ref(f),
TypeF::Record(rrows) => rrows.traverse_ref(f),
| TypeF::Array(t) => t.traverse_ref(f, state),
TypeF::Record(rrows) => rrows.traverse_ref(f, state),
}
}
}
Expand All @@ -1144,18 +1160,22 @@ impl Traverse<RichTerm> for Type {
self.traverse(&f_on_type, state, order)
}

fn traverse_ref<U>(&self, f: &mut dyn FnMut(&RichTerm) -> TraverseControl<U>) -> Option<U> {
let mut f_on_type = |ty: &Type| match &ty.typ {
fn traverse_ref<S, U>(
&self,
f: &mut dyn FnMut(&RichTerm, &S) -> TraverseControl<S, U>,
state: &S,
) -> Option<U> {
let mut f_on_type = |ty: &Type, s: &S| match &ty.typ {
TypeF::Flat(t) => {
if let Some(ret) = t.traverse_ref(f) {
if let Some(ret) = t.traverse_ref(f, s) {
TraverseControl::Return(ret)
} else {
TraverseControl::SkipBranch
}
}
_ => TraverseControl::Continue,
};
self.traverse_ref(&mut f_on_type)
self.traverse_ref(&mut f_on_type, state)
}
}

Expand Down
3 changes: 2 additions & 1 deletion lsp/nls/src/field_walker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ impl FieldDefs {
/// are the fields defined on either record.
///
/// `env` is an environment used only for the initial resolutions; see [`Self::resolve_path`]
fn resolve_term(rt: &RichTerm, env: &Environment, server: &Server) -> FieldDefs {
pub fn resolve_term(rt: &RichTerm, env: &Environment, server: &Server) -> FieldDefs {
let term_fields = match rt.term.as_ref() {
Term::Record(data) | Term::RecRecord(data, ..) => {
let fields = data
Expand Down Expand Up @@ -329,6 +329,7 @@ impl FieldDefs {
let defs = FieldDefs::resolve_annot(annot, env, server);
defs.fold(FieldDefs::resolve_term(term, env, server), Combine::combine)
}
Term::Type(typ) => FieldDefs::resolve_type(typ, env, server),
_ => Default::default(),
};

Expand Down
Loading

0 comments on commit 73b9f10

Please sign in to comment.