[fine] Many more import-related shuffles

This commit is contained in:
John Doty 2024-02-15 06:12:18 -08:00
parent 994268abb6
commit a3ae4339cf
8 changed files with 159 additions and 67 deletions

View file

@ -104,6 +104,13 @@ impl std::ops::Deref for ClassRef {
}
}
#[derive(Clone, Debug)]
pub struct ImportRecord {
pub name: String,
pub module_id: u64,
pub semantics: Weak<Semantics>,
}
#[derive(Clone)]
pub enum Type {
// Signals a type error. If you receive this then you know that an error
@ -156,7 +163,7 @@ pub enum Type {
Alternate(Box<[Type]>),
// A module of some kind. What module?
Module(Rc<str>),
Module(ImportRecord),
}
impl Type {
@ -251,7 +258,7 @@ impl fmt::Display for Type {
}
Ok(())
}
Module(name) => write!(f, "module {}", name),
Module(name) => write!(f, "module {}", name.name),
}
}
}
@ -583,7 +590,11 @@ fn set_logical_parents(
// Process escapes and convert a string constant in source to a runtime String value.
pub fn string_constant_to_string(s: &str) -> String {
let mut result = String::new();
let mut input = s.chars();
if s.len() <= 2 {
return result;
}
let mut input = s[1..s.len() - 1].chars();
while let Some(ch) = input.next() {
if ch == '\\' {
if let Some(ch) = input.next() {
@ -615,7 +626,7 @@ pub struct Semantics {
syntax_tree: Rc<SyntaxTree>,
lines: Rc<Lines>,
import_map: OnceCell<HashMap<String, Weak<Semantics>>>,
import_map: OnceCell<HashMap<String, ImportRecord>>,
// Instead of physical parents, this is the set of *logical* parents.
// This is what is used for binding.
@ -661,7 +672,7 @@ impl Semantics {
semantics
}
pub fn set_imports(&self, imports: HashMap<String, Weak<Semantics>>) {
pub fn set_imports(&self, imports: HashMap<String, ImportRecord>) {
self.import_map.set(imports).expect("imports already set");
}
@ -678,7 +689,22 @@ impl Semantics {
}
pub fn imports(&self) -> Vec<String> {
vec![]
self.syntax_tree
.root()
.map(|file| {
self.syntax_tree[file]
.children_of_kind(&self.syntax_tree, TreeKind::Import)
.filter_map(|import| {
let tok = self.syntax_tree[import].nth_token(1)?;
if tok.kind != TokenKind::String {
None
} else {
Some(string_constant_to_string(tok.as_str(&self.source)))
}
})
.collect()
})
.unwrap_or(Vec::new())
}
pub fn snapshot_errors(&self) -> Vec<Error> {
@ -2213,7 +2239,20 @@ impl Semantics {
if tok.kind != TokenKind::String {
return Some(Type::Error); // Already reported as syntax error
}
Some(Type::Module(tok.as_str(&self.source).into()))
// do we bind it here? it's not normalized....
let Some(import_map) = self.import_map.get() else {
self.internal_compiler_error(None, "import map not initialized");
};
let name = tok.as_str(&self.source);
match import_map.get(name) {
Some(import) => Some(Type::Module(import.clone())),
None => {
self.report_error_tree(tree, format!("unable to resolve module import {name}"));
Some(Type::Error)
}
}
}
// TODO: Really want to TEST THIS also uh can we generate bytecode for functions and call it??
@ -2488,7 +2527,7 @@ pub fn check(s: &Semantics) {
TreeKind::WhileStatement => check_while_statement(s, tree),
TreeKind::Import => {
// TODO: Check Import Statement
let _ = s.type_of(t);
}
}
}