From 7be20b7c037e0f4f052715188352c9e3fdac0b26 Mon Sep 17 00:00:00 2001 From: IsaacShelton Date: Fri, 20 Sep 2024 18:28:51 -0500 Subject: [PATCH] Added simple namespace inference during function resolution --- .github/workflows/remoteBuild.yml | 4 +-- src/resolve/error.rs | 11 +++++-- src/resolve/expr/call.rs | 26 +++++---------- src/resolve/function_search_ctx.rs | 53 +++++++++++++++++++++++++++--- 4 files changed, 67 insertions(+), 27 deletions(-) diff --git a/.github/workflows/remoteBuild.yml b/.github/workflows/remoteBuild.yml index 1b0cdaa9..fd9eb758 100644 --- a/.github/workflows/remoteBuild.yml +++ b/.github/workflows/remoteBuild.yml @@ -83,8 +83,8 @@ jobs: run: | cargo build --release --target x86_64-pc-windows-gnu env: - CFLAGS: -static-libstdc++ - CXXFLAGS: -static-libstdc++ + CFLAGS: -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread + CXXFLAGS: -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread LLVM_SYS_181_PREFIX: C:\msys64\mingw64 zstd_DIR: C:\msys64\mingw64 zstd_LIBRARY: C:\msys64\mingw64\lib\libzstd.a diff --git a/src/resolve/error.rs b/src/resolve/error.rs index b3861949..843059e8 100644 --- a/src/resolve/error.rs +++ b/src/resolve/error.rs @@ -1,3 +1,4 @@ +use super::function_search_ctx::FindFunctionError; use crate::{ show::Show, source_files::{Source, SourceFiles}, @@ -30,6 +31,7 @@ pub enum ResolveErrorKind { }, FailedToFindFunction { name: String, + reason: FindFunctionError, }, UndeclaredVariable { name: String, @@ -197,9 +199,12 @@ impl Display for ResolveErrorKind { value )?; } - ResolveErrorKind::FailedToFindFunction { name } => { - write!(f, "Failed to find function '{}'", name)?; - } + ResolveErrorKind::FailedToFindFunction { name, reason } => match reason { + FindFunctionError::NotDefined => write!(f, "Failed to find function '{}'", name)?, + FindFunctionError::Ambiguous => { + write!(f, "Multiple possibilities for function '{}'", name)? + } + }, ResolveErrorKind::UndeclaredVariable { name } => { write!(f, "Undeclared variable '{}'", name)?; } diff --git a/src/resolve/expr/call.rs b/src/resolve/expr/call.rs index 4594eb74..7f67a324 100644 --- a/src/resolve/expr/call.rs +++ b/src/resolve/expr/call.rs @@ -1,7 +1,6 @@ use super::{resolve_expr, PreferredType, ResolveExprCtx}; use crate::{ ast::{self, ConformBehavior}, - name::ResolvedName, resolve::{ conform::{conform_expr, to_default::conform_expr_to_default, ConformMode}, error::{ResolveError, ResolveErrorKind}, @@ -23,24 +22,15 @@ pub fn resolve_call_expr( .at(source)); } - eprintln!("warning: function call name resolution not fully implemented yet"); - let resolved_name = if !call.function_name.namespace.is_empty() { - ResolvedName::Project( - format!( - "{}{}", - call.function_name.namespace, call.function_name.basename - ) - .into_boxed_str(), - ) - } else { - ResolvedName::Project(call.function_name.basename.clone().into_boxed_str()) - }; - - let Some(function_ref) = ctx.function_search_ctx.find_function(&resolved_name) else { - return Err(ResolveErrorKind::FailedToFindFunction { - name: call.function_name.to_string(), + let function_ref = match ctx.function_search_ctx.find_function(&call.function_name) { + Ok(function_ref) => function_ref, + Err(reason) => { + return Err(ResolveErrorKind::FailedToFindFunction { + name: call.function_name.to_string(), + reason, + } + .at(source)); } - .at(source)); }; let function = ctx.resolved_ast.functions.get(function_ref).unwrap(); diff --git a/src/resolve/function_search_ctx.rs b/src/resolve/function_search_ctx.rs index 92961aa9..1b3259ab 100644 --- a/src/resolve/function_search_ctx.rs +++ b/src/resolve/function_search_ctx.rs @@ -1,22 +1,67 @@ -use crate::{name::ResolvedName, resolved}; +use crate::{ + name::{Name, ResolvedName}, + resolved, +}; use std::collections::HashMap; #[derive(Clone, Debug)] pub struct FunctionSearchCtx { pub available: HashMap>, + pub imported_namespaces: Vec>, +} + +#[derive(Clone, Debug)] +pub enum FindFunctionError { + NotDefined, + Ambiguous, } impl FunctionSearchCtx { pub fn new() -> Self { Self { available: Default::default(), + // TODO: Make this value user-specified + imported_namespaces: vec!["io".to_string().into_boxed_str()], } } - pub fn find_function(&self, name: &ResolvedName) -> Option { - self.available - .get(name) + pub fn find_function(&self, name: &Name) -> Result { + eprintln!("warning: function call name resolution not fully implemented yet"); + + let resolved_name = if !name.namespace.is_empty() { + ResolvedName::Project(format!("{}{}", name.namespace, name.basename).into_boxed_str()) + } else { + ResolvedName::Project(name.basename.clone().into_boxed_str()) + }; + + if let Some(found) = self + .available + .get(&resolved_name) .and_then(|list| list.first()) .copied() + { + return Ok(found); + } + + if name.namespace.is_empty() { + let mut matches = self.imported_namespaces.iter().filter_map(|namespace| { + self.available + .get(&ResolvedName::Project( + format!("{}/{}", namespace, name.basename).into_boxed_str(), + )) + .and_then(|list| list.first()) + .copied() + }); + + if let Some(found) = matches.next() { + if matches.next().is_some() { + return Err(FindFunctionError::Ambiguous); + } else { + return Ok(found); + } + } + } + + Err(FindFunctionError::NotDefined) } }