[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),
|
Complete(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ImportMap {
|
||||||
|
by_name: HashMap<String, ImportRecord>,
|
||||||
|
by_id: HashMap<ModuleId, ImportRecord>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Semantics {
|
pub struct Semantics {
|
||||||
mid: ModuleId,
|
mid: ModuleId,
|
||||||
file: Rc<str>,
|
file: Rc<str>,
|
||||||
|
|
@ -671,7 +677,7 @@ pub struct Semantics {
|
||||||
syntax_tree: Rc<SyntaxTree>,
|
syntax_tree: Rc<SyntaxTree>,
|
||||||
lines: Rc<Lines>,
|
lines: Rc<Lines>,
|
||||||
|
|
||||||
import_map: OnceCell<HashMap<String, ImportRecord>>,
|
import_map: OnceCell<ImportMap>,
|
||||||
|
|
||||||
// Instead of physical parents, this is the set of *logical* parents.
|
// Instead of physical parents, this is the set of *logical* parents.
|
||||||
// This is what is used for binding.
|
// This is what is used for binding.
|
||||||
|
|
@ -726,9 +732,26 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_imports(&self, imports: HashMap<String, ImportRecord>) {
|
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");
|
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> {
|
pub fn source(&self) -> Rc<str> {
|
||||||
self.source.clone()
|
self.source.clone()
|
||||||
}
|
}
|
||||||
|
|
@ -1268,18 +1291,9 @@ impl Semantics {
|
||||||
|
|
||||||
pub fn class_of(&self, mid: ModuleId, t: TreeRef) -> ClassRef {
|
pub fn class_of(&self, mid: ModuleId, t: TreeRef) -> ClassRef {
|
||||||
if mid != self.mid {
|
if mid != self.mid {
|
||||||
let weak_semantics = self
|
let Some(other_semantics) = self.import_by_id(mid) else {
|
||||||
.import_map
|
self.internal_compiler_error(Some(t), "Have a class we can't resolve");
|
||||||
.get()
|
};
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.find(|(_, v)| v.module_id == mid)
|
|
||||||
.unwrap()
|
|
||||||
.1
|
|
||||||
.semantics
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let other_semantics = weak_semantics.upgrade().unwrap();
|
|
||||||
return other_semantics.class_of(mid, t);
|
return other_semantics.class_of(mid, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2215,7 +2229,15 @@ impl Semantics {
|
||||||
if declaration.module == self.mid {
|
if declaration.module == self.mid {
|
||||||
self.type_of(*t)
|
self.type_of(*t)
|
||||||
} else {
|
} 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
|
// The details of a class are computed lazily, but this is enough of
|
||||||
// a belly-button.
|
// a belly-button.
|
||||||
let name = tree.nth_token(1)?;
|
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()))
|
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....
|
// 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 {
|
let Some(import_map) = self.import_map.get() else {
|
||||||
self.internal_compiler_error(None, "import map not initialized");
|
self.internal_compiler_error(None, "import map not initialized");
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = string_constant_to_string(tok.as_str(&self.source));
|
match import_map.by_name.get(&name) {
|
||||||
match import_map.get(&name) {
|
|
||||||
Some(import) => Some(Type::Module(name.into(), import.clone())),
|
Some(import) => Some(Type::Module(name.into(), import.clone())),
|
||||||
None => {
|
None => {
|
||||||
let error =
|
let error =
|
||||||
|
|
@ -2669,7 +2711,7 @@ impl Semantics {
|
||||||
match self.import_map.get() {
|
match self.import_map.get() {
|
||||||
Some(m) => {
|
Some(m) => {
|
||||||
eprintln!("Import map:");
|
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!(" {k} => {} ({:?})", b.name, b.module_id);
|
||||||
}
|
}
|
||||||
eprintln!();
|
eprintln!();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,5 @@ fun test() -> string {
|
||||||
foo.hello() + " world"
|
foo.hello() + " world"
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ignore working on declaration rebuild
|
|
||||||
// TODO: Obviously run the code duh
|
// TODO: Obviously run the code duh
|
||||||
// @no-errors
|
// @no-errors
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue