cl-typeck: Add path-resolution relative to an ID

Great for interactive debugging
This commit is contained in:
John 2024-07-21 05:57:15 -05:00
parent 9d7ab77999
commit 6bf34fdff6
2 changed files with 55 additions and 1 deletions

View File

@ -24,6 +24,7 @@ const STDLIB: &str = include_str!("../../../stdlib/lib.cl");
const C_MAIN: &str = ""; const C_MAIN: &str = "";
const C_RESV: &str = "\x1b[35m"; const C_RESV: &str = "\x1b[35m";
const C_CODE: &str = "\x1b[36m"; const C_CODE: &str = "\x1b[36m";
const C_BYID: &str = "\x1b[95m";
const C_LISTING: &str = "\x1b[38;5;117m"; const C_LISTING: &str = "\x1b[38;5;117m";
/// A home for immutable intermediate ASTs /// A home for immutable intermediate ASTs
@ -58,6 +59,7 @@ fn main_menu(prj: &mut Project) -> Result<(), RlError> {
"e" | "exit" => return Ok(Response::Break), "e" | "exit" => return Ok(Response::Break),
"l" | "list" => list_types(prj), "l" | "list" => list_types(prj),
"q" | "query" => query_type_expression(prj)?, "q" | "query" => query_type_expression(prj)?,
"i" | "id" => get_by_id(prj)?,
"r" | "resolve" => resolve_all(prj)?, "r" | "resolve" => resolve_all(prj)?,
"d" | "desugar" => live_desugar()?, "d" | "desugar" => live_desugar()?,
"h" | "help" => { "h" | "help" => {
@ -66,6 +68,7 @@ fn main_menu(prj: &mut Project) -> Result<(), RlError> {
code (c): Enter code to type-check code (c): Enter code to type-check
list (l): List all known types list (l): List all known types
query (q): Query the type system query (q): Query the type system
id (i): Get a type by its type ID
resolve (r): Perform type resolution resolve (r): Perform type resolution
desugar (d): WIP: Test the experimental desugaring passes desugar (d): WIP: Test the experimental desugaring passes
help (h): Print this list help (h): Print this list
@ -125,6 +128,48 @@ fn query_type_expression(prj: &mut Project) -> Result<(), RlError> {
}) })
} }
fn get_by_id(prj: &mut Project) -> Result<(), RlError> {
use cl_structures::index_map::MapIndex;
use cl_typeck::handle::DefID;
read_and(C_BYID, "id>", "? >", |line| {
if line.trim().is_empty() {
return Ok(Response::Break);
}
let mut parser = Parser::new(Lexer::new(line));
let def_id = match parser.literal()? {
cl_ast::Literal::Int(int) => int as _,
other => Err(format!("Expected integer, got {other}"))?,
};
let mut path = parser.path().unwrap_or_default();
path.absolute = false;
let Some(handle) = DefID::from_usize(def_id).handle(prj) else {
return Ok(Response::Deny);
};
print!(" > {{{C_LISTING}{handle}\x1b[0m}}");
if !path.parts.is_empty() {
print!("::{path}")
}
println!();
let (ty, value) = handle.navigate((&path).into());
if let (None, None) = (ty, value) {
Err("No results.")?
}
if let Some(t) = ty {
println!("Result in type namespace: {}", t.id());
pretty_handle(t)?;
}
if let Some(v) = value {
println!("Result in value namespace: {}", v.id());
pretty_handle(v)?;
}
Ok(Response::Accept)
})
}
fn resolve_all(prj: &mut Project) -> Result<(), Box<dyn Error>> { fn resolve_all(prj: &mut Project) -> Result<(), Box<dyn Error>> {
prj.resolve_imports()?; prj.resolve_imports()?;
for id in prj.pool.keys() { for id in prj.pool.keys() {

View File

@ -1,4 +1,4 @@
use crate::{definition::Def, project::Project}; use crate::{definition::Def, path::Path, project::Project};
use cl_structures::index_map::*; use cl_structures::index_map::*;
// define the index types // define the index types
@ -46,6 +46,15 @@ impl<'p, 'c> Handle<'p, 'c> {
self.prj.pool.get(self.id) self.prj.pool.get(self.id)
} }
pub fn navigate(self, path: Path) -> (Option<Self>, Option<Self>) {
match self.prj.get(path, self.id) {
Some((Some(ty), Some(vl), _)) => (Some(self.with(ty)), Some(self.with(vl))),
Some((_, Some(vl), _)) => (None, Some(self.with(vl))),
Some((Some(ty), _, _)) => (Some(self.with(ty)), None),
_ => (None, None),
}
}
/// Gets the [Project] this handle points to. /// Gets the [Project] this handle points to.
pub fn project(self) -> &'p Project<'c> { pub fn project(self) -> &'p Project<'c> {
self.prj self.prj