Skip to content

Commit d81670f

Browse files
committed
Started working on namespace support for helper expressions and global variables
1 parent 3b75a89 commit d81670f

File tree

14 files changed

+78
-66
lines changed

14 files changed

+78
-66
lines changed

Diff for: src/ast/expr/kind.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use super::{
33
Integer, InterpreterSyscall, ShortCircuitingBinaryOperation, StructureLiteral, UnaryOperation,
44
While,
55
};
6-
use crate::source_files::Source;
6+
use crate::{name::Name, source_files::Source};
77
use std::ffi::CString;
88

99
#[derive(Clone, Debug)]
1010
pub enum ExprKind {
11-
Variable(String),
11+
Variable(Name),
1212
Boolean(bool),
1313
Integer(Integer),
1414
Float(f64),

Diff for: src/ast/global_variable.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use super::Type;
2-
use crate::source_files::Source;
2+
use crate::{name::Name, source_files::Source};
33

44
#[derive(Clone, Debug)]
55
pub struct GlobalVar {
6-
pub name: String,
6+
pub name: Name,
77
pub ast_type: Type,
88
pub source: Source,
99
pub is_foreign: bool,

Diff for: src/interpreter_env/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ fn thin_cstring_function(
6161
stmts: vec![StmtKind::Expr(
6262
ExprKind::InterpreterSyscall(Box::new(InterpreterSyscall {
6363
kind: syscall_kind,
64-
args: vec![(ptr_char.clone(), ExprKind::Variable(param_name).at(source))],
64+
args: vec![(
65+
ptr_char.clone(),
66+
ExprKind::Variable(Name::plain(param_name)).at(source),
67+
)],
6568
result_type: void.clone(),
6669
}))
6770
.at(source),
@@ -197,12 +200,12 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
197200
args: vec![
198201
(
199202
ptr_char.clone(),
200-
ExprKind::Variable("name".into()).at(source),
203+
ExprKind::Variable(Name::plain("name")).at(source),
201204
),
202205
(
203206
TypeKind::Named(Name::plain("ProjectKind")).at(source),
204207
ExprKind::Member(
205-
Box::new(ExprKind::Variable("project".into()).at(source)),
208+
Box::new(ExprKind::Variable(Name::plain("project")).at(source)),
206209
"kind".into(),
207210
)
208211
.at(source),

Diff for: src/lexer/identifier_state.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ impl IdentifierState {
2222

2323
let namespace = identifier;
2424

25-
return TokenKind::NamespacedIdentifier(Name {
26-
namespace,
27-
basename,
28-
})
29-
.at(self.start_source);
25+
return TokenKind::NamespacedIdentifier(Name::new(Some(namespace), basename))
26+
.at(self.start_source);
3027
}
3128

3229
match identifier.as_str() {

Diff for: src/name.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,31 @@ use std::fmt::Display;
22

33
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
44
pub struct Name {
5-
pub namespace: String,
6-
pub basename: String,
5+
pub namespace: Box<str>,
6+
pub basename: Box<str>,
77
}
88

99
impl Name {
1010
pub fn new(namespace: Option<impl Into<String>>, basename: impl Into<String>) -> Self {
1111
Self {
1212
namespace: namespace
1313
.map(|namespace| namespace.into())
14-
.unwrap_or_default(),
15-
basename: basename.into(),
14+
.unwrap_or_default()
15+
.into_boxed_str(),
16+
basename: basename.into().into_boxed_str(),
1617
}
1718
}
1819

1920
pub fn plain(basename: impl Into<String>) -> Self {
2021
Self {
2122
namespace: "".into(),
22-
basename: basename.into(),
23+
basename: basename.into().into_boxed_str(),
2324
}
2425
}
2526

2627
pub fn into_plain(self) -> Option<String> {
2728
if self.namespace.is_empty() {
28-
Some(self.basename)
29+
Some(self.basename.to_string())
2930
} else {
3031
None
3132
}
@@ -41,7 +42,7 @@ impl Name {
4142

4243
pub fn fullname(&self) -> String {
4344
if self.namespace.is_empty() {
44-
self.basename.clone()
45+
self.basename.clone().to_string()
4546
} else {
4647
format!("{}/{}", self.namespace, self.basename)
4748
}

Diff for: src/parser/parse_expr/primary/mod.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
108108
self.parse_type_from_parts(name, generics, source)?;
109109
self.parse_structure_literal_with(ast_type)
110110
}
111-
_ => Ok(Expr::new(
112-
ExprKind::Variable(into_plain_name(name, source)?),
113-
source,
114-
)),
111+
_ => Ok(Expr::new(ExprKind::Variable(name), source)),
115112
}
116113
}
117114
}
@@ -128,10 +125,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
128125
return Err(ParseErrorKind::GenericsNotSupportedHere.at(source));
129126
}
130127

131-
Ok(Expr::new(
132-
ExprKind::Variable(into_plain_name(name, source)?),
133-
source,
134-
))
128+
Ok(Expr::new(ExprKind::Variable(name), source))
135129
}
136130
}
137131
}

Diff for: src/parser/parse_expr/primary/structure_literal.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::Parser;
22
use crate::{
33
ast::{Expr, ExprKind, FieldInitializer, FillBehavior, Language, StructureLiteral, Type},
44
inflow::Inflow,
5+
name::Name,
56
parser::error::ParseError,
67
token::{Token, TokenKind},
78
};
@@ -38,7 +39,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
3839
self.ignore_newlines();
3940

4041
let field_value = if dupe {
41-
ExprKind::Variable(field_name.clone()).at(source)
42+
ExprKind::Variable(Name::plain(field_name.clone())).at(source)
4243
} else {
4344
self.parse_token(TokenKind::Colon, Some("after field name in struct literal"))?;
4445
self.ignore_newlines();

Diff for: src/parser/parse_global_variable.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use super::{
66
use crate::{
77
ast::GlobalVar,
88
inflow::Inflow,
9+
name::Name,
910
token::{Token, TokenKind},
1011
};
1112

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

2021
let mut is_foreign = false;
2122
let mut is_thread_local = false;
23+
let mut namespace = None;
2224

2325
for annotation in annotations {
2426
match annotation.kind {
2527
AnnotationKind::Foreign => is_foreign = true,
2628
AnnotationKind::ThreadLocal => is_thread_local = true,
29+
AnnotationKind::Namespace(new_namespace) => namespace = Some(new_namespace),
2730
_ => {
2831
return Err(self.unexpected_annotation(&annotation, Some("for global variable")))
2932
}
@@ -41,7 +44,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
4144
let ast_type = self.parse_type(None::<&str>, Some("for type of global variable"))?;
4245

4346
Ok(GlobalVar {
44-
name,
47+
name: Name::new(namespace, name),
4548
ast_type,
4649
source,
4750
is_foreign,

Diff for: src/parser/parse_helper_expr.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use super::{annotation::Annotation, error::ParseError, Parser};
1+
use super::{
2+
annotation::{Annotation, AnnotationKind},
3+
error::ParseError,
4+
Parser,
5+
};
26
use crate::{
37
ast::{HelperExpr, Named},
48
inflow::Inflow,
@@ -14,6 +18,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
1418
let source = self.source_here();
1519
self.input.advance();
1620

21+
let mut namespace = None;
1722
let name = self.parse_identifier(Some("for define name after 'define' keyword"))?;
1823
self.ignore_newlines();
1924

@@ -22,14 +27,15 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
2227
#[allow(clippy::never_loop, clippy::match_single_binding)]
2328
for annotation in annotations {
2429
match annotation.kind {
30+
AnnotationKind::Namespace(new_namespace) => namespace = Some(new_namespace),
2531
_ => return Err(self.unexpected_annotation(&annotation, Some("for define"))),
2632
}
2733
}
2834

2935
let value = self.parse_expr()?;
3036

3137
Ok(Named::<HelperExpr> {
32-
name: Name::plain(name),
38+
name: Name::new(namespace, name),
3339
value: HelperExpr {
3440
value,
3541
source,

Diff for: src/parser/parse_util.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
5151

5252
match token.kind {
5353
TokenKind::NamespacedIdentifier(name) => Ok(name),
54-
TokenKind::Identifier(basename) => Ok(Name {
55-
namespace: "".into(),
56-
basename,
57-
}),
54+
TokenKind::Identifier(basename) => Ok(Name::plain(basename)),
5855
_ => Err(ParseError::expected("identifier", for_reason, token)),
5956
}
6057
}

Diff for: src/resolve/expr/variable.rs

+28-20
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ use crate::{
1212

1313
pub fn resolve_variable_expr(
1414
ctx: &mut ResolveExprCtx<'_, '_>,
15-
name: &str,
15+
name: &Name,
1616
preferred_type: Option<PreferredType>,
1717
initialized: Initialized,
1818
source: Source,
1919
) -> Result<TypedExpr, ResolveError> {
20-
if let Some(variable) = ctx.variable_search_ctx.find_variable(name) {
20+
if let Some(variable) = name
21+
.as_plain_str()
22+
.and_then(|name| ctx.variable_search_ctx.find_variable(name))
23+
{
2124
let function = ctx
2225
.resolved_ast
2326
.functions
@@ -30,7 +33,7 @@ pub fn resolve_variable_expr(
3033
.expect("found variable to exist")
3134
.is_initialized();
3235

33-
Ok(TypedExpr::new_maybe_initialized(
36+
return Ok(TypedExpr::new_maybe_initialized(
3437
variable.resolved_type.clone(),
3538
resolved::Expr::new(
3639
resolved::ExprKind::Variable(Box::new(resolved::Variable {
@@ -40,9 +43,13 @@ pub fn resolve_variable_expr(
4043
source,
4144
),
4245
is_initialized,
43-
))
44-
} else if let Some((resolved_type, reference)) = ctx.global_search_ctx.find_global(name) {
45-
Ok(TypedExpr::new(
46+
));
47+
}
48+
49+
let resolved_name = ResolvedName::new(name);
50+
51+
if let Some((resolved_type, reference)) = ctx.global_search_ctx.find_global(&resolved_name) {
52+
return Ok(TypedExpr::new(
4653
resolved_type.clone(),
4754
resolved::Expr::new(
4855
resolved::ExprKind::GlobalVariable(Box::new(resolved::GlobalVariable {
@@ -51,31 +58,32 @@ pub fn resolve_variable_expr(
5158
})),
5259
source,
5360
),
54-
))
55-
} else if let Some(define) = ctx
56-
.helper_exprs
57-
// TODO: CLEANUP: PERFORMANCE: Once we have proper support for
58-
// namespaced helper expressions, this should be cleaned up
59-
.get(&ResolvedName::new(&Name::new(None::<&str>, name)))
60-
{
61+
));
62+
}
63+
64+
if let Some(define) = ctx.helper_exprs.get(&resolved_name) {
6165
let TypedExpr {
6266
resolved_type,
6367
expr,
6468
is_initialized,
6569
} = resolve_expr(ctx, &define.value, preferred_type, initialized)?;
6670

67-
Ok(TypedExpr::new_maybe_initialized(
71+
return Ok(TypedExpr::new_maybe_initialized(
6872
resolved_type,
6973
resolved::Expr::new(
7074
resolved::ExprKind::ResolvedNamedExpression(name.to_string(), Box::new(expr)),
7175
source,
7276
),
7377
is_initialized,
74-
))
75-
} else {
76-
Err(ResolveErrorKind::UndeclaredVariable {
77-
name: name.to_string(),
78-
}
79-
.at(source))
78+
));
79+
}
80+
81+
// TODO: Check if any global variables from imported namespaces match
82+
// TODO: Check if any helper exprs from imported namespaces match
83+
// TODO: They should probably be checked at the same time
84+
85+
Err(ResolveErrorKind::UndeclaredVariable {
86+
name: name.to_string(),
8087
}
88+
.at(source))
8189
}

Diff for: src/resolve/global_search_ctx.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use super::error::{ResolveError, ResolveErrorKind};
22
use crate::{
3+
name::ResolvedName,
34
resolved::{self, GlobalVarRef},
45
source_files::Source,
56
};
67
use std::collections::HashMap;
78

89
#[derive(Clone, Debug)]
910
pub struct GlobalSearchCtx {
10-
globals: HashMap<String, (resolved::Type, GlobalVarRef)>,
11+
globals: HashMap<ResolvedName, (resolved::Type, GlobalVarRef)>,
1112
}
1213

1314
impl GlobalSearchCtx {
@@ -19,7 +20,7 @@ impl GlobalSearchCtx {
1920

2021
pub fn find_global_or_error(
2122
&self,
22-
name: &str,
23+
name: &ResolvedName,
2324
source: Source,
2425
) -> Result<(&resolved::Type, &GlobalVarRef), ResolveError> {
2526
match self.find_global(name) {
@@ -31,7 +32,7 @@ impl GlobalSearchCtx {
3132
}
3233
}
3334

34-
pub fn find_global(&self, name: &str) -> Option<(&resolved::Type, &GlobalVarRef)> {
35+
pub fn find_global(&self, name: &ResolvedName) -> Option<(&resolved::Type, &GlobalVarRef)> {
3536
if let Some((resolved_type, key)) = self.globals.get(name) {
3637
return Some((resolved_type, key));
3738
}
@@ -40,11 +41,10 @@ impl GlobalSearchCtx {
4041

4142
pub fn put(
4243
&mut self,
43-
name: impl ToString,
44+
name: ResolvedName,
4445
resolved_type: resolved::Type,
4546
reference: GlobalVarRef,
4647
) {
47-
self.globals
48-
.insert(name.to_string(), (resolved_type, reference));
48+
self.globals.insert(name, (resolved_type, reference));
4949
}
5050
}

0 commit comments

Comments
 (0)