1
1
mirror of https://github.com/tweag/nickel.git synced 2024-09-20 16:08:14 +03:00

Attach meta data to linearized terms

This commit is contained in:
Yannik Sander 2021-10-29 15:08:52 +02:00 committed by Yannik Sander
parent 4cd865fe7a
commit 3646ede403
2 changed files with 28 additions and 44 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use nickel::{
identifier::Ident,
position::TermPos,
term::Term,
term::{MetaValue, Term},
typecheck::{
linearization::{
Building, Completed, Environment, Linearization, LinearizationItem, Linearizer,
@ -67,6 +67,7 @@ impl BuildingExt for Linearization<Building<BuildingResource>> {
pub struct AnalysisHost {
env: Environment,
scope: Vec<ScopeId>,
meta: Option<MetaValue>,
}
impl AnalysisHost {
@ -74,6 +75,7 @@ impl AnalysisHost {
AnalysisHost {
env: Environment::new(),
scope: Vec::new(),
meta: None,
}
}
}
@ -101,6 +103,7 @@ impl Linearizer<BuildingResource, (UnifTable, HashMap<usize, Ident>)> for Analys
pos,
scope: self.scope.clone(),
kind: TermKind::Declaration(ident.to_string(), Vec::new()),
meta: self.meta.take(),
});
}
Term::Var(ident) => {
@ -113,6 +116,7 @@ impl Linearizer<BuildingResource, (UnifTable, HashMap<usize, Ident>)> for Analys
// id = parent: full let binding including the body
// id = parent + 1: actual delcaration scope, i.e. _ = < definition >
kind: TermKind::Usage(parent.map(|id| id + 1)),
meta: self.meta.take(),
});
if let Some(parent) = parent {
lin.add_usage(parent, id);
@ -124,14 +128,29 @@ impl Linearizer<BuildingResource, (UnifTable, HashMap<usize, Ident>)> for Analys
ty,
kind: TermKind::Record(attrs.clone()),
scope: self.scope.clone(),
meta: self.meta.take(),
}),
Term::MetaValue(meta) => {
// Notice 1: No push to lin
// Notice 2: we discard the encoded value as anything we
// would do with the value will be handled in the following
// call to [Self::add_term]
let meta = MetaValue {
value: None,
..meta.to_owned()
};
self.meta.insert(meta);
}
_ => lin.push(LinearizationItem {
id,
pos,
ty,
scope: self.scope.clone(),
kind: TermKind::Structure,
meta: self.meta.take(),
}),
}
}
@ -175,12 +194,14 @@ impl Linearizer<BuildingResource, (UnifTable, HashMap<usize, Ident>)> for Analys
ty,
kind,
scope,
meta,
}| LinearizationItem {
ty: to_type(&table, &reported_names, &mut NameReg::new(), ty),
id,
pos,
kind,
scope,
meta,
},
)
.collect();
@ -201,6 +222,9 @@ impl Linearizer<BuildingResource, (UnifTable, HashMap<usize, Ident>)> for Analys
AnalysisHost {
scope,
env: self.env.clone(),
/// when opening a new scope `meta` is assumed to be `None` as meta data
/// is immediately followed by a term without opening a scope
meta: None,
}
}
}

View File

@ -26,8 +26,8 @@ use std::{collections::HashMap, marker::PhantomData};
use super::TypeWrapper;
use crate::environment::Environment as GenericEnvironment;
use crate::term::RecordAttrs;
use crate::types::Types;
use crate::types::{AbsType, Types};
use crate::term::{MetaValue, RecordAttrs};
use crate::{identifier::Ident, position::TermPos, term::Term};
/// Holds the state of a linearization, either in progress or finalized
@ -103,6 +103,7 @@ pub struct LinearizationItem<S: ResolutionState> {
pub ty: S,
pub kind: TermKind,
pub scope: Vec<ScopeId>,
pub meta: Option<MetaValue>,
}
/// Abstact term kinds.
@ -187,53 +188,12 @@ pub enum ScopeId {
impl ScopeIdElem for ScopeId {}
#[derive(Default)]
pub struct BuildingResource {
pub linearization: Vec<LinearizationItem<Unresolved>>,
pub scope: HashMap<Vec<ScopeId>, Vec<usize>>,
}
impl Into<Completed> for Linearization<Completed> {
fn into(self) -> Completed {
self.state
}
}
impl Linearization<Building<BuildingResource>> {
pub fn push(&mut self, item: LinearizationItem<Unresolved>) {
self.state
.resource
.scope
.remove(&item.scope)
.map(|mut s| {
s.push(item.id);
s
})
.or_else(|| Some(vec![item.id]))
.into_iter()
.for_each(|l| {
self.state.resource.scope.insert(item.scope.clone(), l);
});
self.state.resource.linearization.push(item);
}
pub fn add_usage(&mut self, decl: usize, usage: usize) {
match self
.state
.resource
.linearization
.get_mut(decl)
.expect("Coundt find parent")
.kind
{
TermKind::Structure => unreachable!(),
TermKind::Usage(_) => unreachable!(),
TermKind::Record(_) => unreachable!(),
TermKind::Declaration(_, ref mut usages) => usages.push(usage),
};
}
}
impl Completed {
pub fn get_item(&self, id: usize) -> Option<&LinearizationItem<Resolved>> {
self.id_mapping