diff --git a/src/codegen.rs b/src/codegen.rs index 5e379d7..21ea683 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -921,6 +921,9 @@ impl Codegen { } } } + AstNode::NamespacedLookup { .. } => { + self.codegen_node(*item, local_inferences, output) + } _ => { panic!("unsupported namespace lookup") } diff --git a/src/typechecker.rs b/src/typechecker.rs index f67f4a1..c3feee7 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -139,11 +139,6 @@ pub struct Scope { allow_unsafe: bool, } -#[derive(Debug)] -pub struct Module { - scope: Scope, -} - impl Scope { pub fn new() -> Scope { Scope { @@ -185,6 +180,14 @@ impl Scope { None } + fn find_module(&self, module: ModuleId) -> Option<&Module> { + todo!() + } +} + +#[derive(Debug)] +pub struct Module { + scope: Scope, } pub struct Typechecker { @@ -2384,15 +2387,34 @@ impl Typechecker { } } + #[instrument(skip(self))] + pub fn typecheck_namespaced_lookup_in_module( + &mut self, + namespace: NodeId, + item: NodeId, + local_inferences: &mut Vec, + module: ModuleId, + ) -> TypeId { + let module = self.compiler.get_module(module); + if let Some(module_id) = self.find_module_in_module(namespace, module) { + self.typecheck_namespaced_item_lookup(namespace, module_id, item, local_inferences) + } else if let Some(type_id) = self.find_type_in_module(namespace, module) { + self.typecheck_namespaced_type_lookup(namespace, type_id, item, local_inferences) + } else { + self.error("could not find namespace", namespace); + VOID_TYPE_ID + } + } + // enter the module's scope then recurse and call typecheck_namespaced_lookup? fn typecheck_namespaced_item_lookup( &mut self, namespace: NodeId, - module: ModuleId, + module_id: ModuleId, item: NodeId, local_inferences: &mut Vec, ) -> TypeId { - let module = self.compiler.get_module(module); + let module = self.compiler.get_module(module_id); let node = self.compiler.get_node(item).clone(); match &node { AstNode::Call { head, args } => { @@ -2405,6 +2427,7 @@ impl Typechecker { ); let fun_id = module.scope.find_fun(name); if let Some(fun_id) = fun_id { + debug!(?fun_id, "found {name}", name = std::str::from_utf8(name).unwrap()); self.typecheck_call_with_fun_id(*head, fun_id, args, None, local_inferences) } else { debug!(?node); @@ -2412,6 +2435,9 @@ impl Typechecker { VOID_TYPE_ID } } + AstNode::NamespacedLookup { namespace, item } => { + self.typecheck_namespaced_lookup_in_module(*namespace, *item, local_inferences, module_id) + } _ => { debug!(?node); self.error("could not find item in namespace", namespace); @@ -3129,6 +3155,7 @@ impl Typechecker { if file_name == unsafe { std::ffi::OsStr::from_encoded_bytes_unchecked(name) } { + debug!(?module_id, "found module"); return Some(*module_id); } } @@ -3139,6 +3166,33 @@ impl Typechecker { None } + #[instrument(skip(self))] + pub fn find_module_in_module(&self, namespace: NodeId, module: &Module) -> Option { + let name = self.compiler.get_source(namespace); + debug!( + "searching for module \"{name}\"", + name = std::str::from_utf8(name).unwrap() + ); + let scope = &module.scope; + for (path, module_id) in scope.modules.iter() { + trace!(?path, ?module_id); + // definitely incorrect, but we currently only have one path segment + // this needs to somehow be able to resolve the path against all the segments of the path + for path in path.ancestors() { + if let Some(file_name) = path.file_stem() { + if file_name + == unsafe { std::ffi::OsStr::from_encoded_bytes_unchecked(name) } + { + debug!(?module_id, "found module"); + return Some(*module_id); + } + } + } + } + + None + } + pub fn find_type_in_scope(&self, type_name: NodeId) -> Option { let name = self.compiler.get_source(type_name); for scope in self.scope.iter().rev() { @@ -3151,6 +3205,10 @@ impl Typechecker { None } + pub fn find_type_in_module(&self, type_name: NodeId, module: &Module) -> Option { + todo!() + } + pub fn find_type_in_scope_by_name(&self, name: &[u8]) -> Option { for scope in self.scope.iter().rev() { if let Some(type_id) = scope.types.get(name) {