[fine] Lookup semantics by mid
This isn't actually correct, I really need a global view to make this right.
This commit is contained in:
parent
2c03989da3
commit
4c061fbd28
2 changed files with 59 additions and 18 deletions
|
|
@ -664,6 +664,12 @@ enum Incremental<T> {
|
|||
Complete(T),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ImportMap {
|
||||
by_name: HashMap<String, ImportRecord>,
|
||||
by_id: HashMap<ModuleId, ImportRecord>,
|
||||
}
|
||||
|
||||
pub struct Semantics {
|
||||
mid: ModuleId,
|
||||
file: Rc<str>,
|
||||
|
|
@ -671,7 +677,7 @@ pub struct Semantics {
|
|||
syntax_tree: Rc<SyntaxTree>,
|
||||
lines: Rc<Lines>,
|
||||
|
||||
import_map: OnceCell<HashMap<String, ImportRecord>>,
|
||||
import_map: OnceCell<ImportMap>,
|
||||
|
||||
// Instead of physical parents, this is the set of *logical* parents.
|
||||
// This is what is used for binding.
|
||||
|
|
@ -726,9 +732,26 @@ impl Semantics {
|
|||
}
|
||||
|
||||
pub fn set_imports(&self, imports: HashMap<String, ImportRecord>) {
|
||||
let mut by_id = HashMap::new();
|
||||
for (_, v) in imports.iter() {
|
||||
by_id.insert(v.module_id, v.clone());
|
||||
}
|
||||
let imports = ImportMap {
|
||||
by_name: imports,
|
||||
by_id,
|
||||
};
|
||||
|
||||
self.import_map.set(imports).expect("imports already set");
|
||||
}
|
||||
|
||||
pub fn import_by_id(&self, mid: ModuleId) -> Option<Rc<Semantics>> {
|
||||
// TODO: ACTUALLY THIS IS WRONG, WE NEED THE GLOBAL MAP HERE, NOT THE LOCAL ONE.
|
||||
let import_map = self.import_map.get()?;
|
||||
let record = import_map.by_id.get(&mid)?;
|
||||
|
||||
record.semantics.upgrade()
|
||||
}
|
||||
|
||||
pub fn source(&self) -> Rc<str> {
|
||||
self.source.clone()
|
||||
}
|
||||
|
|
@ -1268,18 +1291,9 @@ impl Semantics {
|
|||
|
||||
pub fn class_of(&self, mid: ModuleId, t: TreeRef) -> ClassRef {
|
||||
if mid != self.mid {
|
||||
let weak_semantics = self
|
||||
.import_map
|
||||
.get()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|(_, v)| v.module_id == mid)
|
||||
.unwrap()
|
||||
.1
|
||||
.semantics
|
||||
.clone();
|
||||
|
||||
let other_semantics = weak_semantics.upgrade().unwrap();
|
||||
let Some(other_semantics) = self.import_by_id(mid) else {
|
||||
self.internal_compiler_error(Some(t), "Have a class we can't resolve");
|
||||
};
|
||||
return other_semantics.class_of(mid, t);
|
||||
}
|
||||
|
||||
|
|
@ -2215,7 +2229,15 @@ impl Semantics {
|
|||
if declaration.module == self.mid {
|
||||
self.type_of(*t)
|
||||
} else {
|
||||
self.internal_compiler_error(Some(*t), "Not implemented: deref this module");
|
||||
let Some(other_semantics) = self.import_by_id(declaration.module) else {
|
||||
let message = format!(
|
||||
"Cannot find a module matching this decl's mid: {:?}",
|
||||
declaration.module
|
||||
);
|
||||
self.internal_compiler_error(Some(*t), &message);
|
||||
};
|
||||
|
||||
other_semantics.type_of(*t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2364,6 +2386,26 @@ impl Semantics {
|
|||
// The details of a class are computed lazily, but this is enough of
|
||||
// a belly-button.
|
||||
let name = tree.nth_token(1)?;
|
||||
|
||||
// NOTE: There's a kind of a weird design decision here, which is to
|
||||
// return an instance type instead of a class type. This is
|
||||
// because it turns out to be what you want most of the time:
|
||||
// variables should be object type, arguments should be object
|
||||
// type, etc.
|
||||
//
|
||||
// There are only two places where you have to deal with this
|
||||
// being weird: first, in the new object expression, and
|
||||
// second, in static member access.
|
||||
//
|
||||
// For new object expression it turns out to not matter much,
|
||||
// you just have to be aware that the type identifier is an
|
||||
// object type.
|
||||
//
|
||||
// For the static member access, that one is just plain weird.
|
||||
// But it's easier to handle converting object type -> class
|
||||
// type there (in type_of_identifier) rather than flipping the
|
||||
// default here and dealing with converting class type ->
|
||||
// object type literally everywhere else.
|
||||
Some(Type::Object(self.mid, t, name.as_str(&self.source).into()))
|
||||
}
|
||||
|
||||
|
|
@ -2499,12 +2541,12 @@ impl Semantics {
|
|||
}
|
||||
|
||||
// do we bind it here? it's not normalized....
|
||||
let name = string_constant_to_string(tok.as_str(&self.source));
|
||||
let Some(import_map) = self.import_map.get() else {
|
||||
self.internal_compiler_error(None, "import map not initialized");
|
||||
};
|
||||
|
||||
let name = string_constant_to_string(tok.as_str(&self.source));
|
||||
match import_map.get(&name) {
|
||||
match import_map.by_name.get(&name) {
|
||||
Some(import) => Some(Type::Module(name.into(), import.clone())),
|
||||
None => {
|
||||
let error =
|
||||
|
|
@ -2669,7 +2711,7 @@ impl Semantics {
|
|||
match self.import_map.get() {
|
||||
Some(m) => {
|
||||
eprintln!("Import map:");
|
||||
for (k, b) in m.iter() {
|
||||
for (k, b) in m.by_name.iter() {
|
||||
eprintln!(" {k} => {} ({:?})", b.name, b.module_id);
|
||||
}
|
||||
eprintln!();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,5 @@ fun test() -> string {
|
|||
foo.hello() + " world"
|
||||
}
|
||||
|
||||
// @ignore working on declaration rebuild
|
||||
// TODO: Obviously run the code duh
|
||||
// @no-errors
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue