catlog/tt/
context.rs

1//! Contexts store the type and values of in-scope variables during elaboration.
2use crate::tt::{prelude::*, val::*};
3
4/// Each variable in context is associated with a label and a type.
5///
6/// Multiple variables with the same name can show up in context; in this case
7/// the most recent one is selected, as follows the standard scope conventions.
8pub struct VarInContext {
9    /// The name of the variable.
10    pub name: VarName,
11    /// The label for the variable.
12    pub label: LabelSegment,
13    /// The type of the variable.
14    pub ty: Option<TyV>,
15}
16
17impl VarInContext {
18    /// Constructor for VarInContext.
19    pub fn new(name: VarName, label: LabelSegment, ty: Option<TyV>) -> Self {
20        Self { name, label, ty }
21    }
22}
23
24/// The variable context during elaboration
25pub struct Context {
26    /// Stores the value of each of the variables in context
27    pub env: Env,
28    /// Stores the names and types of each of the variables in context.
29    ///
30    /// We allow the type to be "none" as a hack for the `self` variable before we
31    /// know the type of the `self` variable.
32    pub scope: Vec<VarInContext>,
33}
34
35/// A checkpoint that we can return the context to.
36pub struct ContextCheckpoint {
37    env: Env,
38    scope: usize,
39}
40
41// Clippy wants this for some reason
42impl Default for Context {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl Context {
49    /// Create an empty context.
50    pub fn new() -> Self {
51        Self {
52            env: Env::Nil,
53            scope: Vec::new(),
54        }
55    }
56
57    /// Create a checkpoint from the current state of the context.
58    pub fn checkpoint(&self) -> ContextCheckpoint {
59        ContextCheckpoint {
60            env: self.env.clone(),
61            scope: self.scope.len(),
62        }
63    }
64
65    /// Reset the context to a previously-saved checkpoint.
66    pub fn reset_to(&mut self, c: ContextCheckpoint) {
67        self.env = c.env;
68        self.scope.truncate(c.scope);
69    }
70
71    /// Add a new variable to scope (note: does not add it to the environment)
72    pub fn push_scope(&mut self, name: VarName, label: LabelSegment, ty: Option<TyV>) {
73        self.scope.push(VarInContext::new(name, label, ty))
74    }
75
76    /// Lookup a variable by name
77    pub fn lookup(&self, name: VarName) -> Option<(BwdIdx, LabelSegment, Option<TyV>)> {
78        self.scope
79            .iter()
80            .rev()
81            .enumerate()
82            .find(|(_, v)| v.name == name)
83            .map(|(i, v)| (i.into(), v.label, v.ty.clone()))
84    }
85}