Skip to content

Commit

Permalink
Added ability to import and use global variables from other modules
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacShelton committed Oct 17, 2024
1 parent e247e33 commit 7db4074
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 121 deletions.
7 changes: 4 additions & 3 deletions src/ast/global_variable.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use super::Type;
use crate::{name::Name, source_files::Source};
use super::{Privacy, Type};
use crate::source_files::Source;

#[derive(Clone, Debug)]
pub struct GlobalVar {
pub name: Name,
pub name: String,
pub ast_type: Type,
pub source: Source,
pub is_foreign: bool,
pub is_thread_local: bool,
pub privacy: Privacy,
}
10 changes: 5 additions & 5 deletions src/parser/parse_global_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use super::{
Parser,
};
use crate::{
ast::GlobalVar,
ast::{GlobalVar, Privacy},
inflow::Inflow,
name::Name,
token::{Token, TokenKind},
};

Expand All @@ -20,13 +19,13 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {

let mut is_foreign = false;
let mut is_thread_local = false;
let mut namespace = None;
let mut privacy = Privacy::Private;

for annotation in annotations {
match annotation.kind {
AnnotationKind::Foreign => is_foreign = true,
AnnotationKind::ThreadLocal => is_thread_local = true,
AnnotationKind::Namespace(new_namespace) => namespace = Some(new_namespace),
AnnotationKind::Public => privacy = Privacy::Public,
_ => {
return Err(self.unexpected_annotation(&annotation, Some("for global variable")))
}
Expand All @@ -44,11 +43,12 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
let ast_type = self.parse_type(None::<&str>, Some("for type of global variable"))?;

Ok(GlobalVar {
name: Name::new(namespace, name),
name,
ast_type,
source,
is_foreign,
is_thread_local,
privacy,
})
}
}
15 changes: 14 additions & 1 deletion src/resolve/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum ResolveErrorKind {
AmbiguousType {
name: String,
},
AmbiguousGlobal {
name: String,
},
NotEnoughArgumentsToFunction {
name: String,
},
Expand Down Expand Up @@ -235,7 +238,14 @@ impl Display for ResolveErrorKind {
}

if !almost_matches.is_empty() {
write!(f, "\n Did you mean?")?;
match reason {
FindFunctionError::NotDefined => {
write!(f, "\n Did you mean?")?;
}
FindFunctionError::Ambiguous => {
write!(f, "\n Possibilities include:")?;
}
}

for almost_match in almost_matches {
write!(f, "\n {}", almost_match)?;
Expand All @@ -256,6 +266,9 @@ impl Display for ResolveErrorKind {
ResolveErrorKind::AmbiguousType { name } => {
write!(f, "Ambiguous type '{}'", name)?;
}
ResolveErrorKind::AmbiguousGlobal { name } => {
write!(f, "Ambiguous global variable '{}'", name)?;
}
ResolveErrorKind::NotEnoughArgumentsToFunction { name } => {
write!(f, "Not enough arguments for call to function '{}'", name)?;
}
Expand Down
3 changes: 1 addition & 2 deletions src/resolve/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use super::{
destination::resolve_expr_to_destination,
error::ResolveError,
function_search_ctx::FunctionSearchCtx,
global_search_ctx::GlobalSearchCtx,
variable_search_ctx::VariableSearchCtx,
Initialized, ResolveTypeCtx,
};
Expand Down Expand Up @@ -51,13 +50,13 @@ use std::collections::HashMap;
pub struct ResolveExprCtx<'a, 'b> {
pub resolved_ast: &'b mut resolved::Ast<'a>,
pub function_search_ctx: &'b FunctionSearchCtx,
pub global_search_ctx: &'b GlobalSearchCtx,
pub variable_search_ctx: VariableSearchCtx,
pub resolved_function_ref: resolved::FunctionRef,
pub helper_exprs: &'b IndexMap<ResolvedName, &'a ast::HelperExpr>,
pub settings: &'b Settings,
pub public_functions: &'b HashMap<FsNodeId, HashMap<String, Vec<resolved::FunctionRef>>>,
pub types_in_modules: &'b HashMap<FsNodeId, HashMap<String, resolved::TypeDecl>>,
pub globals_in_modules: &'b HashMap<FsNodeId, HashMap<String, resolved::GlobalVarDecl>>,
pub module_fs_node_id: FsNodeId,
pub physical_fs_node_id: FsNodeId,
}
Expand Down
84 changes: 42 additions & 42 deletions src/resolve/expr/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
expr::resolve_expr,
Initialized,
},
resolved::{self, Type, TypedExpr},
resolved::{self, GlobalVarDecl, Type, TypedExpr},
source_files::Source,
};

Expand Down Expand Up @@ -50,59 +50,53 @@ pub fn resolve_variable_expr(

let resolved_name = ResolvedName::new(ctx.module_fs_node_id, name);

if let Some((resolved_type, reference)) = ctx.global_search_ctx.find_global(&resolved_name) {
return Ok(resolve_global_variable(resolved_type, *reference, source));
if let Some(basename) = name.as_plain_str() {
if let Some(found) = ctx
.globals_in_modules
.get(&ctx.module_fs_node_id)
.and_then(|globals| globals.get(basename))
{
return Ok(resolve_global_variable(ctx, found, source));
}
}

if let Some(helper_expr) = ctx.helper_exprs.get(&resolved_name) {
return resolve_helper_expr(ctx, helper_expr, preferred_type, initialized, source);
}
if !name.namespace.is_empty() {
let Name {
namespace,
basename,
..
} = name;

if name.namespace.is_empty() {
let mut matches = ctx
.settings
.imported_namespaces
.iter()
.flat_map(|namespace| {
let resolved_name = ResolvedName::new(
ctx.module_fs_node_id,
&Name::new(Some(namespace.to_string()), name.basename.to_string()),
);

let global = ctx
.global_search_ctx
.find_global(&resolved_name)
.map(GlobalOrHelper::Global);

let helper_expr = ctx
.helper_exprs
.get(&resolved_name)
.copied()
.map(GlobalOrHelper::HelperExpr);

[global, helper_expr]
.namespace_to_dependency
.get(namespace.as_ref())
.into_iter()
.flatten()
.flat_map(|dep| ctx.settings.dependency_to_module.get(dep))
.flat_map(|fs_node_id| {
ctx.globals_in_modules
.get(fs_node_id)
.and_then(|globals| globals.get(basename.as_ref()))
})
.flatten();
.filter(|decl| decl.privacy.is_public());

if let Some(found) = matches.next() {
if matches.next().is_some() {
return Err(ResolveErrorKind::AmbiguousSymbol {
return Err(ResolveErrorKind::AmbiguousGlobal {
name: name.to_string(),
}
.at(source));
}

return match found {
GlobalOrHelper::Global((ty, reference)) => {
Ok(resolve_global_variable(ty, *reference, source))
}
GlobalOrHelper::HelperExpr(helper_expr) => {
resolve_helper_expr(ctx, helper_expr, preferred_type, initialized, source)
}
};
return Ok(resolve_global_variable(ctx, found, source));
}
}

if let Some(helper_expr) = ctx.helper_exprs.get(&resolved_name) {
return resolve_helper_expr(ctx, helper_expr, preferred_type, initialized, source);
}

Err(ResolveErrorKind::UndeclaredVariable {
name: name.to_string(),
}
Expand All @@ -115,16 +109,22 @@ enum GlobalOrHelper<'a> {
}

fn resolve_global_variable(
resolved_type: &Type,
reference: GlobalVarRef,
ctx: &ResolveExprCtx,
decl: &GlobalVarDecl,
source: Source,
) -> TypedExpr {
let global = ctx
.resolved_ast
.globals
.get(decl.global_ref)
.expect("valid global");

TypedExpr::new(
resolved_type.clone(),
global.resolved_type.clone(),
resolved::Expr::new(
resolved::ExprKind::GlobalVariable(Box::new(resolved::GlobalVariable {
reference,
resolved_type: resolved_type.clone(),
reference: decl.global_ref,
resolved_type: global.resolved_type.clone(),
})),
source,
),
Expand Down
52 changes: 0 additions & 52 deletions src/resolve/global_search_ctx.rs

This file was deleted.

Loading

0 comments on commit 7db4074

Please sign in to comment.