cl-typeck: Crate-spanning refactor

TODO: remove all unreferenced files
TODO: Finish resolving statically known types of values
TODO: Type inference
This commit is contained in:
2024-07-24 18:22:42 -05:00
parent b7ad285a11
commit e19127facc
17 changed files with 1270 additions and 989 deletions

View File

@@ -1,15 +1,14 @@
use cl_typeck::{
entry::Entry, import::import, populate::Populator, table::Table,
type_expression::TypeExpression,
};
use cl_ast::{
ast_visitor::{Fold, Visit},
desugar::*,
};
use cl_lexer::Lexer;
use cl_parser::{inliner::ModuleInliner, Parser};
use cl_typeck::{
handle::Handle,
name_collector::NameCollector,
project::Project,
type_resolver::resolve,
};
use repline::{error::Error as RlError, prebaked::*};
use std::{error::Error, path};
@@ -31,7 +30,7 @@ const C_LISTING: &str = "\x1b[38;5;117m";
static mut TREES: TreeManager = TreeManager::new();
fn main() -> Result<(), Box<dyn Error>> {
let mut prj = Project::default();
let mut prj = Table::default();
let mut parser = Parser::new(Lexer::new(STDLIB));
let code = match parser.file() {
@@ -42,13 +41,14 @@ fn main() -> Result<(), Box<dyn Error>> {
}
};
let code = inline_modules(code, concat!(env!("PWD"), "/stdlib"));
NameCollector::new(&mut prj).visit_file(unsafe { TREES.push(code) });
Populator::new(&mut prj).visit_file(unsafe { TREES.push(code) });
// NameCollector::new(&mut prj).visit_file(unsafe { TREES.push(code) });
main_menu(&mut prj)?;
Ok(())
}
fn main_menu(prj: &mut Project) -> Result<(), RlError> {
fn main_menu(prj: &mut Table) -> Result<(), RlError> {
banner();
read_and(C_MAIN, "mu>", "? >", |line| {
match line.trim() {
@@ -80,7 +80,7 @@ fn main_menu(prj: &mut Project) -> Result<(), RlError> {
})
}
fn enter_code(prj: &mut Project) -> Result<(), RlError> {
fn enter_code(prj: &mut Table) -> Result<(), RlError> {
read_and(C_CODE, "cl>", "? >", |line| {
if line.trim().is_empty() {
return Ok(Response::Break);
@@ -89,8 +89,7 @@ fn enter_code(prj: &mut Project) -> Result<(), RlError> {
let code = inline_modules(code, "");
let code = WhileElseDesugar.fold_file(code);
// Safety: this is totally unsafe
NameCollector::new(prj).visit_file(unsafe { TREES.push(code) });
Populator::new(prj).visit_file(unsafe { TREES.push(code) });
Ok(Response::Accept)
})
}
@@ -113,22 +112,22 @@ fn live_desugar() -> Result<(), RlError> {
})
}
fn query_type_expression(prj: &mut Project) -> Result<(), RlError> {
fn query_type_expression(prj: &mut Table) -> Result<(), RlError> {
read_and(C_RESV, "ty>", "? >", |line| {
if line.trim().is_empty() {
return Ok(Response::Break);
}
// parse it as a path, and convert the path into a borrowed path
let ty = Parser::new(Lexer::new(line)).ty()?.kind;
let id = prj.evaluate(&ty, prj.root)?.handle_unchecked(prj);
pretty_handle(id)?;
let id = ty.evaluate(prj, prj.root())?;
pretty_handle(id.to_entry(prj))?;
Ok(Response::Accept)
})
}
fn get_by_id(prj: &mut Project) -> Result<(), RlError> {
fn get_by_id(prj: &mut Table) -> Result<(), RlError> {
use cl_structures::index_map::MapIndex;
use cl_typeck::handle::DefID;
use cl_typeck::handle::Handle;
read_and(C_BYID, "id>", "? >", |line| {
if line.trim().is_empty() {
return Ok(Response::Break);
@@ -141,9 +140,7 @@ fn get_by_id(prj: &mut Project) -> Result<(), RlError> {
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);
};
let handle = Handle::from_usize(def_id).to_entry(prj);
print!(" > {{{C_LISTING}{handle}\x1b[0m}}");
if !path.parts.is_empty() {
@@ -151,65 +148,114 @@ fn get_by_id(prj: &mut Project) -> Result<(), RlError> {
}
println!();
let (ty, value) = handle.navigate((&path).into());
if let (None, None) = (ty, value) {
let Some(handle) = handle.nav(&path.parts) else {
Err("No results.")?
}
if let Some(t) = ty {
println!("Result: {}", t.id());
pretty_handle(t)?;
}
if let Some(v) = value {
println!("Result in value namespace: {}", v.id());
pretty_handle(v)?;
}
};
pretty_handle(handle)?;
Ok(Response::Accept)
})
}
fn resolve_all(prj: &mut Project) -> Result<(), Box<dyn Error>> {
prj.resolve_imports()?;
for id in prj.pool.keys() {
resolve(prj, id)?;
fn resolve_all(prj: &mut Table) -> Result<(), Box<dyn Error>> {
println!("Resolving imports:");
for (id, error) in import(prj) {
eprintln!("{error} in {} ({id})", id.to_entry(prj))
}
println!("Types resolved successfully!");
// todo!("Resolve imports");
// prj.resolve_imports()?;
// for id in prj.pool.keys() {
// resolve(prj, id)?;
// }
// println!("Types resolved successfully!");
Ok(())
}
fn list_types(prj: &mut Project) {
println!(" name | type");
for (idx, key) in prj.pool.keys().enumerate() {
let handle = key.handle_unchecked(prj);
let vis = handle.vis().unwrap_or_default();
fn list_types(prj: &mut Table) {
for handle in prj.debug_handle_iter() {
let id = handle.id();
let kind = handle.kind().unwrap();
let name = handle.name().unwrap_or("".into());
println!("{idx:3}: {name:16}| {vis}{handle}");
println!("{id:3}: {name:16}| {kind} {handle}");
}
}
fn pretty_handle(handle: Handle) -> Result<(), std::io::Error> {
fn pretty_handle(h: Entry) -> Result<(), std::io::Error> {
use std::io::Write;
let mut stdout = std::io::stdout().lock();
let Some(vis) = handle.vis() else {
return writeln!(stdout, "Invalid handle: {handle}");
let mut out = std::io::stdout().lock();
let Some(kind) = h.kind() else {
return writeln!(out, "Invalid handle: {h}");
};
writeln!(stdout, "{C_LISTING}{}\x1b[0m: {vis}{handle}", handle.id())?;
if let Some(parent) = handle.parent() {
writeln!(stdout, "{C_LISTING}Parent\x1b[0m: {parent}")?;
write!(out, "{C_LISTING}{kind}")?;
if let Some(name) = h.name() {
write!(out, " {name}")?;
}
if let Some(types) = handle.types() {
writeln!(stdout, "{C_LISTING}Types:\x1b[0m")?;
for (name, def) in types {
writeln!(stdout, "- {C_LISTING}{name}\x1b[0m: {}", handle.with(*def))?
writeln!(out, "\x1b[0m: {h}")?;
if let Some(parent) = h.parent() {
writeln!(out, "- {C_LISTING}Parent\x1b[0m: {parent}")?;
}
if let Some(span) = h.span() {
writeln!(
out,
"- {C_LISTING}Span:\x1b[0m ({}, {})",
span.head, span.tail
)?;
}
match h.meta() {
Some(meta) if !meta.is_empty() => {
writeln!(out, "- {C_LISTING}Meta:\x1b[0m")?;
for meta in meta {
writeln!(out, " - {meta}")?;
}
}
_ => {}
}
if let Some(children) = h.children() {
writeln!(out, "- {C_LISTING}Children:\x1b[0m")?;
for (name, child) in children {
writeln!(
out,
" - {C_LISTING}{name}\x1b[0m ({child}): {}",
h.with_id(*child)
)?
}
}
if let Some(values) = handle.values() {
writeln!(stdout, "{C_LISTING}Values:\x1b[0m")?;
for (name, def) in values {
writeln!(stdout, "- {C_LISTING}{name}\x1b[0m: {}", handle.with(*def))?
if let Some(imports) = h.imports() {
writeln!(out, "- {C_LISTING}Imports:\x1b[0m")?;
for (name, child) in imports {
writeln!(
out,
" - {C_LISTING}{name}\x1b[0m ({child}): {}",
h.with_id(*child)
)?
}
}
write!(stdout, "\x1b[0m")
// let Some(vis) = handle.vis() else {
// return writeln!(stdout, "Invalid handle: {handle}");
// };
// writeln!(stdout, "{C_LISTING}{}\x1b[0m: {vis}{handle}", handle.id())?;
// if let Some(parent) = handle.parent() {
// }
// if let Some(types) = handle.types() {
// writeln!(stdout, "{C_LISTING}Types:\x1b[0m")?;
// for (name, def) in types {
// }
// }
// if let Some(values) = handle.values() {
// writeln!(stdout, "{C_LISTING}Values:\x1b[0m")?;
// for (name, def) in values {
// writeln!(stdout, "- {C_LISTING}{name}\x1b[0m: {}", handle.with(*def))?
// }
// }
// write!(stdout, "\x1b[0m")
Ok(())
}
fn inline_modules(code: cl_ast::File, path: impl AsRef<path::Path>) -> cl_ast::File {