diff --git a/compiler/cl-typeck/examples/typeck.rs b/compiler/cl-typeck/examples/typeck.rs index be3cd01..5629f78 100644 --- a/compiler/cl-typeck/examples/typeck.rs +++ b/compiler/cl-typeck/examples/typeck.rs @@ -24,6 +24,7 @@ const STDLIB: &str = include_str!("../../../stdlib/lib.cl"); const C_MAIN: &str = ""; const C_RESV: &str = "\x1b[35m"; const C_CODE: &str = "\x1b[36m"; +const C_BYID: &str = "\x1b[95m"; const C_LISTING: &str = "\x1b[38;5;117m"; /// A home for immutable intermediate ASTs @@ -58,6 +59,7 @@ fn main_menu(prj: &mut Project) -> Result<(), RlError> { "e" | "exit" => return Ok(Response::Break), "l" | "list" => list_types(prj), "q" | "query" => query_type_expression(prj)?, + "i" | "id" => get_by_id(prj)?, "r" | "resolve" => resolve_all(prj)?, "d" | "desugar" => live_desugar()?, "h" | "help" => { @@ -66,6 +68,7 @@ fn main_menu(prj: &mut Project) -> Result<(), RlError> { code (c): Enter code to type-check list (l): List all known types query (q): Query the type system + id (i): Get a type by its type ID resolve (r): Perform type resolution desugar (d): WIP: Test the experimental desugaring passes 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> { prj.resolve_imports()?; for id in prj.pool.keys() { diff --git a/compiler/cl-typeck/src/handle.rs b/compiler/cl-typeck/src/handle.rs index f0705d9..c4b6fe3 100644 --- a/compiler/cl-typeck/src/handle.rs +++ b/compiler/cl-typeck/src/handle.rs @@ -1,4 +1,4 @@ -use crate::{definition::Def, project::Project}; +use crate::{definition::Def, path::Path, project::Project}; use cl_structures::index_map::*; // define the index types @@ -46,6 +46,15 @@ impl<'p, 'c> Handle<'p, 'c> { self.prj.pool.get(self.id) } + pub fn navigate(self, path: Path) -> (Option, Option) { + 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. pub fn project(self) -> &'p Project<'c> { self.prj