From cc8e1b94fc004aba1ff34742e5c6b90ace331818 Mon Sep 17 00:00:00 2001 From: IsaacShelton Date: Wed, 18 Sep 2024 20:40:31 -0500 Subject: [PATCH] Started working on namespace resolution --- src/ast/datatype/kind/mod.rs | 11 +-- src/ast/expr/call.rs | 7 +- src/c/translation/types/composite.rs | 7 +- src/c/translation/types/enumeration.rs | 6 +- src/interpreter_env/mod.rs | 9 ++- src/lexer/identifier_state.rs | 5 +- src/lexer/mod.rs | 2 +- src/main.rs | 1 + src/parser/annotation.rs | 2 + src/parser/error.rs | 4 + src/parser/parse_annotation.rs | 13 +++- src/parser/parse_expr/post/member.rs | 9 ++- src/parser/parse_expr/primary/call.rs | 5 +- .../parse_expr/primary/enum_member_literal.rs | 2 +- src/parser/parse_expr/primary/mod.rs | 21 +++-- src/parser/parse_stmt/parse_declaration.rs | 2 +- src/parser/parse_type.rs | 67 ++++++++-------- src/parser/parse_util.rs | 24 +++++- src/resolve/expr/call.rs | 12 ++- src/resolve/function_search_ctx.rs | 21 +---- src/resolve/mod.rs | 77 ++++++++----------- src/resolve/type_search_ctx.rs | 36 ++++----- src/token.rs | 24 +++--- 23 files changed, 198 insertions(+), 169 deletions(-) diff --git a/src/ast/datatype/kind/mod.rs b/src/ast/datatype/kind/mod.rs index 8f431f3..032819f 100644 --- a/src/ast/datatype/kind/mod.rs +++ b/src/ast/datatype/kind/mod.rs @@ -5,7 +5,7 @@ use super::{ AnonymousEnum, AnonymousStruct, AnoymousUnion, CInteger, FixedArray, FloatSize, FunctionPointer, IntegerBits, IntegerSign, Type, }; -use crate::source_files::Source; +use crate::{name::Name, source_files::Source}; #[derive(Clone, Debug)] pub enum TypeKind { @@ -16,7 +16,7 @@ pub enum TypeKind { Pointer(Box), FixedArray(Box), Void, - Named(String), + Named(Name), AnonymousStruct(AnonymousStruct), AnonymousUnion(AnoymousUnion), AnonymousEnum(AnonymousEnum), @@ -30,9 +30,10 @@ impl TypeKind { pub fn allow_indirect_undefined(&self) -> bool { if let TypeKind::Named(name) = self { - if name.starts_with("struct<") - || name.starts_with("union<") - || name.starts_with("enum<") + let basename = &name.basename; + if basename.starts_with("struct<") + || basename.starts_with("union<") + || basename.starts_with("enum<") { return true; } diff --git a/src/ast/expr/call.rs b/src/ast/expr/call.rs index 348156a..0d7e672 100644 --- a/src/ast/expr/call.rs +++ b/src/ast/expr/call.rs @@ -1,9 +1,12 @@ use super::Expr; -use crate::ast::{CompileTimeArgument, Type}; +use crate::{ + ast::{CompileTimeArgument, Type}, + name::Name, +}; #[derive(Clone, Debug)] pub struct Call { - pub function_name: String, + pub function_name: Name, pub arguments: Vec, pub expected_to_return: Option, pub generics: Vec, diff --git a/src/c/translation/types/composite.rs b/src/c/translation/types/composite.rs index b25e8f7..5aaebfe 100644 --- a/src/c/translation/types/composite.rs +++ b/src/c/translation/types/composite.rs @@ -6,6 +6,7 @@ use crate::{ MemberDeclaration, MemberDeclarator, ParseError, }, diagnostics::Diagnostics, + name::Name, }; use indexmap::IndexMap; use std::collections::HashMap; @@ -30,8 +31,8 @@ pub fn make_composite( })?; return Ok(match &composite.kind { - CompositeKind::Struct => TypeKind::Named(format!("struct<{}>", name)), - CompositeKind::Union => TypeKind::Named(format!("union<{}>", name)), + CompositeKind::Struct => TypeKind::Named(Name::plain(format!("struct<{}>", name))), + CompositeKind::Union => TypeKind::Named(Name::plain(format!("union<{}>", name))), }); }; @@ -98,7 +99,7 @@ pub fn make_composite( source: composite.source, }); - Ok(TypeKind::Named(name)) + Ok(TypeKind::Named(Name::plain(name))) } else { let anonymous_struct = AnonymousStruct { fields, is_packed }; diff --git a/src/c/translation/types/enumeration.rs b/src/c/translation/types/enumeration.rs index 0e4c62e..ad568b5 100644 --- a/src/c/translation/types/enumeration.rs +++ b/src/c/translation/types/enumeration.rs @@ -5,6 +5,7 @@ use crate::{ translation::eval::evaluate_to_const_integer, }, index_map_ext::IndexMapExt, + name::Name, }; use indexmap::IndexMap; use num_bigint::BigInt; @@ -91,7 +92,10 @@ pub fn make_anonymous_enum( todo!("support enum type specifiers") } - Ok(TypeKind::Named(format!("enum<{}>", named.name))) + Ok(TypeKind::Named(Name::plain(format!( + "enum<{}>", + named.name + )))) } } } diff --git a/src/interpreter_env/mod.rs b/src/interpreter_env/mod.rs index 85d0ae8..9c1478f 100644 --- a/src/interpreter_env/mod.rs +++ b/src/interpreter_env/mod.rs @@ -8,6 +8,7 @@ use crate::{ Interpreter, InterpreterError, }, ir::{self, InterpreterSyscallKind}, + name::Name, resolved, source_files::Source, tag::Tag, @@ -56,7 +57,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { // Call to function we actually care about let call = ExprKind::Call(Box::new(Call { - function_name: "main".into(), + function_name: Name::plain("main"), arguments: vec![], expected_to_return: Some(void.clone()), generics: vec![], @@ -103,7 +104,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { fields: IndexMap::from_iter([( "kind".into(), Field { - ast_type: TypeKind::Named("ProjectKind".into()).at(source), + ast_type: TypeKind::Named(Name::plain("ProjectKind")).at(source), privacy: Privacy::Public, source, }, @@ -149,7 +150,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { Parameter::new("name".into(), ptr_char.clone()), Parameter::new( "project".into(), - TypeKind::Named("Project".into()).at(source), + TypeKind::Named(Name::plain("Project")).at(source), ), ], is_cstyle_vararg: false, @@ -164,7 +165,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { ExprKind::Variable("name".into()).at(source), ), ( - TypeKind::Named("ProjectKind".into()).at(source), + TypeKind::Named(Name::plain("ProjectKind")).at(source), ExprKind::Member( Box::new(ExprKind::Variable("project".into()).at(source)), "kind".into(), diff --git a/src/lexer/identifier_state.rs b/src/lexer/identifier_state.rs index 405433a..d09e096 100644 --- a/src/lexer/identifier_state.rs +++ b/src/lexer/identifier_state.rs @@ -1,6 +1,7 @@ use crate::{ + name::Name, source_files::Source, - token::{NamespacedIndentifier, Token, TokenKind}, + token::{Token, TokenKind}, }; pub struct IdentifierState { @@ -17,7 +18,7 @@ impl IdentifierState { let basename = identifier.split_off(last_slash + 1); let namespace = identifier; - return TokenKind::NamespacedIdentifier(NamespacedIndentifier { + return TokenKind::NamespacedIdentifier(Name { namespace, basename, }) diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index 232a61b..f1230a6 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -269,7 +269,7 @@ impl Lexer { } ',' => Has(TokenKind::Comma.at(source)), ':' if self.characters.eat('=') => Has(TokenKind::DeclareAssign.at(source)), - ':' if self.characters.eat(':') => Has(TokenKind::Namespace.at(source)), + ':' if self.characters.eat(':') => Has(TokenKind::StaticMember.at(source)), ':' => Has(TokenKind::Colon.at(source)), '#' => Has(TokenKind::Hash.at(source)), '\"' => { diff --git a/src/main.rs b/src/main.rs index 331bf5d..1e6cf81 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ mod llvm_backend; mod logic; mod look_ahead; mod lower; +mod name; mod parser; mod path; mod pragma_section; diff --git a/src/parser/annotation.rs b/src/parser/annotation.rs index 8f2157c..211d52e 100644 --- a/src/parser/annotation.rs +++ b/src/parser/annotation.rs @@ -19,6 +19,7 @@ pub enum AnnotationKind { ThreadLocal, Packed, AbideAbi, + Namespace(String), } impl AnnotationKind { @@ -34,6 +35,7 @@ impl Display for AnnotationKind { Self::ThreadLocal => "thread_local", Self::Packed => "packed", Self::AbideAbi => "abide_abi", + Self::Namespace(_) => "namespace", }) } } diff --git a/src/parser/error.rs b/src/parser/error.rs index 9228d1c..9f7725e 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -84,6 +84,7 @@ pub enum ParseErrorKind { word_for_nth: String, }, GenericsNotSupportedHere, + NamespaceNotAllowedHere, Other { message: String, }, @@ -207,6 +208,9 @@ impl Display for ParseErrorKind { ParseErrorKind::GenericsNotSupportedHere => { write!(f, "Generics not supported here")?; } + ParseErrorKind::NamespaceNotAllowedHere => { + write!(f, "Namespace not allowed here")?; + } ParseErrorKind::Other { message } | ParseErrorKind::Lexical { message } => { write!(f, "{}", message)?; } diff --git a/src/parser/parse_annotation.rs b/src/parser/parse_annotation.rs index 49eb944..6dc17c4 100644 --- a/src/parser/parse_annotation.rs +++ b/src/parser/parse_annotation.rs @@ -19,13 +19,15 @@ impl<'a, I: Inflow> Parser<'a, I> { let (annotation_name, source) = self.parse_identifier_keep_location(Some("for annotation name"))?; - self.parse_token(TokenKind::CloseBracket, Some("to close annotation body"))?; - - Ok(match annotation_name.as_str() { + let annotation = match annotation_name.as_str() { "foreign" => AnnotationKind::Foreign, "thread_local" => AnnotationKind::ThreadLocal, "packed" => AnnotationKind::Packed, "abide_abi" => AnnotationKind::AbideAbi, + "namespace" => { + let namespace = self.parse_identifier(Some("for namespace name"))?; + AnnotationKind::Namespace(namespace) + } _ => { return Err(ParseErrorKind::UnrecognizedAnnotation { name: annotation_name, @@ -33,6 +35,9 @@ impl<'a, I: Inflow> Parser<'a, I> { .at(source)) } } - .at(source)) + .at(source); + + self.parse_token(TokenKind::CloseBracket, Some("to close annotation body"))?; + Ok(annotation) } } diff --git a/src/parser/parse_expr/post/member.rs b/src/parser/parse_expr/post/member.rs index 5284447..2f5d6be 100644 --- a/src/parser/parse_expr/post/member.rs +++ b/src/parser/parse_expr/post/member.rs @@ -2,7 +2,7 @@ use super::Parser; use crate::{ ast::{Expr, ExprKind}, inflow::Inflow, - parser::error::ParseError, + parser::{error::ParseError, parse_util::into_plain_name}, token::{Token, TokenKind}, }; @@ -12,13 +12,16 @@ impl<'a, I: Inflow> Parser<'a, I> { // ^ let source = self.parse_token(TokenKind::Member, Some("for member expression"))?; - let member_name = self.parse_identifier(Some("for member name"))?; + let member_name = self.parse_name(Some("for member name"))?; if self.input.peek_is(TokenKind::OpenParen) || self.input.peek_is(TokenKind::OpenAngle) { let generics = self.parse_generics()?; self.parse_call_with(member_name, generics, vec![subject], source) } else { - Ok(ExprKind::Member(Box::new(subject), member_name).at(source)) + Ok( + ExprKind::Member(Box::new(subject), into_plain_name(member_name, source)?) + .at(source), + ) } } } diff --git a/src/parser/parse_expr/primary/call.rs b/src/parser/parse_expr/primary/call.rs index 1edf4bc..b0dd628 100644 --- a/src/parser/parse_expr/primary/call.rs +++ b/src/parser/parse_expr/primary/call.rs @@ -2,6 +2,7 @@ use super::Parser; use crate::{ ast::{Call, CompileTimeArgument, Expr, ExprKind}, inflow::Inflow, + name::Name, parser::error::ParseError, source_files::Source, token::{Token, TokenKind}, @@ -10,7 +11,7 @@ use crate::{ impl<'a, I: Inflow> Parser<'a, I> { pub fn parse_call( &mut self, - function_name: String, + function_name: Name, generics: Vec, source: Source, ) -> Result { @@ -22,7 +23,7 @@ impl<'a, I: Inflow> Parser<'a, I> { pub fn parse_call_with( &mut self, - function_name: String, + function_name: Name, generics: Vec, prefix_args: Vec, source: Source, diff --git a/src/parser/parse_expr/primary/enum_member_literal.rs b/src/parser/parse_expr/primary/enum_member_literal.rs index 4c46209..44851a0 100644 --- a/src/parser/parse_expr/primary/enum_member_literal.rs +++ b/src/parser/parse_expr/primary/enum_member_literal.rs @@ -16,7 +16,7 @@ impl<'a, I: Inflow> Parser<'a, I> { // EnumName::EnumVariant // ^ - self.parse_token(TokenKind::Namespace, Some("for enum member literal"))?; + self.parse_token(TokenKind::StaticMember, Some("for enum member literal"))?; let variant_source = self.source_here(); let variant_name = self diff --git a/src/parser/parse_expr/primary/mod.rs b/src/parser/parse_expr/primary/mod.rs index abec7c7..3ef3fed 100644 --- a/src/parser/parse_expr/primary/mod.rs +++ b/src/parser/parse_expr/primary/mod.rs @@ -11,7 +11,7 @@ use crate::{ UnaryOperator, While, }, inflow::Inflow, - parser::{array_last, error::ParseErrorKind}, + parser::{array_last, error::ParseErrorKind, parse_util::into_plain_name}, token::{StringLiteral, StringModifier, Token, TokenKind}, }; use std::ffi::CString; @@ -69,19 +69,20 @@ impl<'a, I: Inflow> Parser<'a, I> { TokenKind::StructKeyword | TokenKind::UnionKeyword | TokenKind::EnumKeyword => { self.parse_structure_literal() } - TokenKind::Identifier(_) => { + TokenKind::Identifier(_) | TokenKind::NamespacedIdentifier(_) => { // TODO: CLEANUP: This should be cleaned up once we have proper // namespaces and generic parsing that applies to all cases - let name = self.input.eat_identifier().unwrap(); + let name = self.parse_name(None::<&str>).unwrap(); let generics = self.parse_generics()?; match self.input.peek().kind { - TokenKind::Namespace => { + TokenKind::StaticMember => { if !generics.is_empty() { return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); } + let name = into_plain_name(name, source)?; self.parse_enum_member_literal(name, source) } TokenKind::OpenCurly => { @@ -101,7 +102,10 @@ impl<'a, I: Inflow> Parser<'a, I> { self.parse_type_from_parts(name, generics, source)?; self.parse_structure_literal_with(ast_type) } - _ => Ok(Expr::new(ExprKind::Variable(name), source)), + _ => Ok(Expr::new( + ExprKind::Variable(into_plain_name(name, source)?), + source, + )), } } } @@ -111,14 +115,17 @@ impl<'a, I: Inflow> Parser<'a, I> { return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); } - self.parse_declare_assign(name, source) + self.parse_declare_assign(into_plain_name(name, source)?, source) } _ => { if !generics.is_empty() { return Err(ParseErrorKind::GenericsNotSupportedHere.at(source)); } - Ok(Expr::new(ExprKind::Variable(name), source)) + Ok(Expr::new( + ExprKind::Variable(into_plain_name(name, source)?), + source, + )) } } } diff --git a/src/parser/parse_stmt/parse_declaration.rs b/src/parser/parse_stmt/parse_declaration.rs index 17f422b..4e91145 100644 --- a/src/parser/parse_stmt/parse_declaration.rs +++ b/src/parser/parse_stmt/parse_declaration.rs @@ -9,7 +9,7 @@ impl<'a, I: Inflow> Parser<'a, I> { pub fn parse_declaration(&mut self) -> Result { let (name, source) = self.parse_identifier_keep_location(Some("for variable name"))?; - let variable_type = self.parse_type(None::<&str>, Some("for variable type"))?; + let variable_type = self.parse_type(None::<&str>, Some("for variable"))?; let initial_value = self .input diff --git a/src/parser/parse_type.rs b/src/parser/parse_type.rs index 0d7f4ad..ff50fae 100644 --- a/src/parser/parse_type.rs +++ b/src/parser/parse_type.rs @@ -5,6 +5,7 @@ use super::{ use crate::{ ast::{CompileTimeArgument, Type, TypeKind}, inflow::Inflow, + name::Name, source_files::Source, token::{Token, TokenKind}, }; @@ -16,9 +17,9 @@ impl<'a, I: Inflow> Parser<'a, I> { for_reason: Option, ) -> Result { let source = self.input.peek().source; - let token = self.input.advance(); + let token = self.input.peek().clone(); - let TokenKind::Identifier(identifier) = token.kind else { + let Ok(name) = self.parse_name(None::<&str>) else { return Err(ParseError { kind: ParseErrorKind::ExpectedType { prefix: prefix.map(|prefix| prefix.to_string()), @@ -30,7 +31,7 @@ impl<'a, I: Inflow> Parser<'a, I> { }; let generics = self.parse_generics()?; - self.parse_type_from_parts(identifier, generics, source) + self.parse_type_from_parts(name, generics, source) } pub fn parse_generics(&mut self) -> Result, ParseError> { @@ -67,42 +68,42 @@ impl<'a, I: Inflow> Parser<'a, I> { pub fn parse_type_from_parts( &mut self, - identifier: String, + name: Name, generics: Vec, source: Source, ) -> Result { - let type_kind = match identifier.as_str() { - "bool" => Ok(TypeKind::Boolean), - "char" => Ok(TypeKind::char()), - "schar" => Ok(TypeKind::schar()), - "uchar" => Ok(TypeKind::uchar()), - "short" => Ok(TypeKind::short()), - "ushort" => Ok(TypeKind::ushort()), - "int" => Ok(TypeKind::int()), - "uint" => Ok(TypeKind::uint()), - "long" => Ok(TypeKind::long()), - "ulong" => Ok(TypeKind::ulong()), - "longlong" => Ok(TypeKind::longlong()), - "ulonglong" => Ok(TypeKind::ulonglong()), - "i8" => Ok(TypeKind::i8()), - "u8" => Ok(TypeKind::u8()), - "i16" => Ok(TypeKind::i16()), - "u16" => Ok(TypeKind::u16()), - "i32" => Ok(TypeKind::i32()), - "u32" => Ok(TypeKind::u32()), - "i64" => Ok(TypeKind::i64()), - "u64" => Ok(TypeKind::u64()), - "f32" | "float" => Ok(TypeKind::f32()), - "f64" | "double" => Ok(TypeKind::f64()), - "void" => Ok(TypeKind::Void), - "ptr" => { + let type_kind = match name.as_plain_str() { + Some("bool") => Ok(TypeKind::Boolean), + Some("char") => Ok(TypeKind::char()), + Some("schar") => Ok(TypeKind::schar()), + Some("uchar") => Ok(TypeKind::uchar()), + Some("short") => Ok(TypeKind::short()), + Some("ushort") => Ok(TypeKind::ushort()), + Some("int") => Ok(TypeKind::int()), + Some("uint") => Ok(TypeKind::uint()), + Some("long") => Ok(TypeKind::long()), + Some("ulong") => Ok(TypeKind::ulong()), + Some("longlong") => Ok(TypeKind::longlong()), + Some("ulonglong") => Ok(TypeKind::ulonglong()), + Some("i8") => Ok(TypeKind::i8()), + Some("u8") => Ok(TypeKind::u8()), + Some("i16") => Ok(TypeKind::i16()), + Some("u16") => Ok(TypeKind::u16()), + Some("i32") => Ok(TypeKind::i32()), + Some("u32") => Ok(TypeKind::u32()), + Some("i64") => Ok(TypeKind::i64()), + Some("u64") => Ok(TypeKind::u64()), + Some("f32" | "float") => Ok(TypeKind::f32()), + Some("f64" | "double") => Ok(TypeKind::f64()), + Some("void") => Ok(TypeKind::Void), + Some("ptr") => { if generics.len() == 1 { if let CompileTimeArgument::Type(inner) = generics.into_iter().next().unwrap() { Ok(TypeKind::Pointer(Box::new(inner))) } else { Err(ParseError { kind: ParseErrorKind::ExpectedTypeParameterToBeAType { - name: identifier, + name: name.to_string(), word_for_nth: "first".into(), }, source, @@ -111,7 +112,7 @@ impl<'a, I: Inflow> Parser<'a, I> { } else { Err(ParseError { kind: ParseErrorKind::IncorrectNumberOfTypeParametersFor { - name: identifier, + name: name.to_string(), expected: 1, got: generics.len(), }, @@ -119,7 +120,7 @@ impl<'a, I: Inflow> Parser<'a, I> { }) } } - "array" => { + Some("array") => { // TODO: Update fixed array type to use compile time arguments todo!("array<$N, $T> not updated yet to use compile time arguments"); @@ -128,7 +129,7 @@ impl<'a, I: Inflow> Parser<'a, I> { // count, // }))) } - identifier => Ok(TypeKind::Named(identifier.into())), + _ => Ok(TypeKind::Named(name)), }?; Ok(Type::new(type_kind, source)) diff --git a/src/parser/parse_util.rs b/src/parser/parse_util.rs index 101605c..8aa1814 100644 --- a/src/parser/parse_util.rs +++ b/src/parser/parse_util.rs @@ -1,6 +1,10 @@ -use super::{error::ParseError, Parser}; +use super::{ + error::{ParseError, ParseErrorKind}, + Parser, +}; use crate::{ inflow::Inflow, + name::Name, source_files::Source, token::{Token, TokenKind}, }; @@ -42,9 +46,27 @@ impl<'a, I: Inflow> Parser<'a, I> { } } + pub fn parse_name(&mut self, for_reason: Option) -> Result { + let token = self.input.advance(); + + match token.kind { + TokenKind::NamespacedIdentifier(name) => Ok(name), + TokenKind::Identifier(basename) => Ok(Name { + namespace: "".into(), + basename, + }), + _ => Err(ParseError::expected("identifier", for_reason, token)), + } + } + pub fn ignore_newlines(&mut self) { while self.input.peek().kind.is_newline() { self.input.advance(); } } } + +pub fn into_plain_name(name: Name, source: Source) -> Result { + name.into_plain() + .ok_or_else(|| ParseErrorKind::NamespaceNotAllowedHere.at(source)) +} diff --git a/src/resolve/expr/call.rs b/src/resolve/expr/call.rs index ffdf3d9..ff23acc 100644 --- a/src/resolve/expr/call.rs +++ b/src/resolve/expr/call.rs @@ -1,6 +1,7 @@ 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}, @@ -22,9 +23,14 @@ pub fn resolve_call_expr( .at(source)); } - let function_ref = ctx - .function_search_ctx - .find_function_or_error(&call.function_name, source)?; + let resolved_name = 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(), + } + .at(source)); + }; let function = ctx.resolved_ast.functions.get(function_ref).unwrap(); let return_type = function.return_type.clone(); diff --git a/src/resolve/function_search_ctx.rs b/src/resolve/function_search_ctx.rs index 2b97f7b..92961aa 100644 --- a/src/resolve/function_search_ctx.rs +++ b/src/resolve/function_search_ctx.rs @@ -1,10 +1,9 @@ -use super::error::{ResolveError, ResolveErrorKind}; -use crate::{resolved, source_files::Source}; +use crate::{name::ResolvedName, resolved}; use std::collections::HashMap; #[derive(Clone, Debug)] pub struct FunctionSearchCtx { - pub available: HashMap>, + pub available: HashMap>, } impl FunctionSearchCtx { @@ -14,21 +13,7 @@ impl FunctionSearchCtx { } } - pub fn find_function_or_error( - &self, - name: &str, - source: Source, - ) -> Result { - match self.find_function(name) { - Some(function) => Ok(function), - None => Err(ResolveErrorKind::FailedToFindFunction { - name: name.to_string(), - } - .at(source)), - } - } - - pub fn find_function(&self, name: &str) -> Option { + pub fn find_function(&self, name: &ResolvedName) -> Option { self.available .get(name) .and_then(|list| list.first()) diff --git a/src/resolve/mod.rs b/src/resolve/mod.rs index 582984f..9179490 100644 --- a/src/resolve/mod.rs +++ b/src/resolve/mod.rs @@ -22,6 +22,7 @@ use crate::{ ast::{self, AstWorkspace, Type}, cli::BuildOptions, index_map_ext::IndexMapExt, + name::ResolvedName, resolved::{self, Enum, TypedExpr, VariableStorage}, source_files::{Source, SourceFiles}, tag::Tag, @@ -103,7 +104,7 @@ pub fn resolve<'a>( } // Temporarily used stack to keep track of used type aliases - let mut used_aliases = HashSet::::new(); + let mut used_aliases = HashSet::::new(); // Pre-compute resolved enum types for (real_file_id, file) in ast_workspace.files.iter() { @@ -278,23 +279,12 @@ pub fn resolve<'a>( .function_search_ctxs .get_or_insert_with(file_id, || FunctionSearchCtx::new()); - // You can blame stable rust for having to do this. - // There is no way to "get_or_insert_mut" without pre-cloning the key. - let function_group = match function_search_context.available.get_mut(&function.name) { - Some(group) => group, - None => { - function_search_context - .available - .insert(function.name.clone(), Vec::new()); - - function_search_context - .available - .get_mut(&function.name) - .unwrap() - } - }; + let resolved_name = ResolvedName::Project(function.name.clone().into_boxed_str()); - function_group.push(function_ref); + function_search_context + .available + .entry(resolved_name) + .or_insert_with(|| vec![function_ref]); } } @@ -394,7 +384,7 @@ fn resolve_type_or_undeclared<'a>( type_search_ctx: &'a TypeSearchCtx<'_>, source_files: &SourceFiles, ast_type: &'a ast::Type, - used_aliases_stack: &mut HashSet, + used_aliases_stack: &mut HashSet, ) -> Result { match resolve_type(type_search_ctx, source_files, ast_type, used_aliases_stack) { Ok(inner) => Ok(inner), @@ -409,7 +399,7 @@ fn resolve_type<'a>( type_search_ctx: &'a TypeSearchCtx<'_>, source_files: &SourceFiles, ast_type: &'a ast::Type, - used_aliases_stack: &mut HashSet, + used_aliases_stack: &mut HashSet, ) -> Result { match &ast_type.kind { ast::TypeKind::Boolean => Ok(resolved::TypeKind::Boolean), @@ -427,31 +417,32 @@ fn resolve_type<'a>( } ast::TypeKind::Void => Ok(resolved::TypeKind::Void), ast::TypeKind::Named(name) => { - let search = type_search_ctx - .find_type_or_error(name, ast_type.source) - .cloned(); - - match search { - Ok(found) => Ok(found), - Err(err) => { - if let Some(definition) = type_search_ctx.find_alias(name) { - if used_aliases_stack.insert(name.clone()) { - let inner = resolve_type( - type_search_ctx, - source_files, - &definition.value, - used_aliases_stack, - ); - used_aliases_stack.remove(name.as_str()); - inner.map(|ty| ty.kind) - } else { - Err(ResolveErrorKind::RecursiveTypeAlias { name: name.clone() } - .at(definition.source)) - } - } else { - Err(err) + eprintln!("warning: resolved_type currently always resolves name to project basename"); + let resolved_name = ResolvedName::Project(name.basename.clone().into_boxed_str()); + + if let Some(found) = type_search_ctx.find_type(&resolved_name) { + Ok(found.clone()) + } else if let Some(definition) = type_search_ctx.find_alias(&resolved_name) { + if used_aliases_stack.insert(resolved_name.clone()) { + let inner = resolve_type( + type_search_ctx, + source_files, + &definition.value, + used_aliases_stack, + ); + used_aliases_stack.remove(&resolved_name); + inner.map(|ty| ty.kind) + } else { + Err(ResolveErrorKind::RecursiveTypeAlias { + name: name.to_string(), } + .at(definition.source)) + } + } else { + Err(ResolveErrorKind::UndeclaredType { + name: name.to_string(), } + .at(ast_type.source)) } } ast::TypeKind::Floating(size) => Ok(resolved::TypeKind::Floating(*size)), @@ -578,7 +569,7 @@ fn resolve_enum_backing_type( type_search_ctx: &TypeSearchCtx, source_files: &SourceFiles, backing_type: Option>, - used_aliases: &mut HashSet, + used_aliases: &mut HashSet, source: Source, ) -> Result { if let Some(backing_type) = backing_type.as_ref().map(Borrow::borrow) { diff --git a/src/resolve/type_search_ctx.rs b/src/resolve/type_search_ctx.rs index 5001af5..a647ec4 100644 --- a/src/resolve/type_search_ctx.rs +++ b/src/resolve/type_search_ctx.rs @@ -1,40 +1,26 @@ use super::error::{ResolveError, ResolveErrorKind}; -use crate::{ast, resolved, source_files::Source}; +use crate::{ast, name::ResolvedName, resolved, source_files::Source}; use indexmap::IndexMap; #[derive(Clone, Debug, Default)] pub struct TypeSearchCtx<'a> { - types: IndexMap, - type_aliases: IndexMap, + types: IndexMap, + type_aliases: IndexMap, } impl<'a> TypeSearchCtx<'a> { - pub fn new(aliases: IndexMap) -> Self { + pub fn new(aliases: IndexMap) -> Self { Self { types: Default::default(), type_aliases: aliases, } } - pub fn find_type_or_error( - &self, - name: &str, - source: Source, - ) -> Result<&resolved::TypeKind, ResolveError> { - match self.find_type(name) { - Some(info) => Ok(info), - None => Err(ResolveErrorKind::UndeclaredType { - name: name.to_string(), - } - .at(source)), - } - } - - pub fn find_type(&self, name: &str) -> Option<&resolved::TypeKind> { + pub fn find_type(&self, name: &ResolvedName) -> Option<&resolved::TypeKind> { self.types.get(name) } - pub fn find_alias(&self, name: &str) -> Option<&ast::TypeAlias> { + pub fn find_alias(&self, name: &ResolvedName) -> Option<&ast::TypeAlias> { self.type_aliases.get(name).copied() } @@ -44,7 +30,10 @@ impl<'a> TypeSearchCtx<'a> { value: resolved::TypeKind, source: Source, ) -> Result<(), ResolveError> { - if self.types.insert(name.to_string(), value).is_some() { + eprintln!("warning: TypeSearchCtx::put_type always puts at root"); + let resolved_name = ResolvedName::Project(name.to_string().into_boxed_str()); + + if self.types.insert(resolved_name, value).is_some() { return Err(ResolveErrorKind::MultipleDefinitionsOfTypeNamed { name: name.to_string(), } @@ -60,7 +49,10 @@ impl<'a> TypeSearchCtx<'a> { value: &'a ast::TypeAlias, source: Source, ) -> Result<(), ResolveError> { - if self.type_aliases.insert(name.to_string(), value).is_some() { + eprintln!("warning: TypeSearchCtx::put_type_alias always puts at root"); + let resolved_name = ResolvedName::Project(name.to_string().into_boxed_str()); + + if self.type_aliases.insert(resolved_name, value).is_some() { return Err(ResolveErrorKind::MultipleDefinitionsOfTypeNamed { name: name.to_string(), } diff --git a/src/token.rs b/src/token.rs index 11a9447..9c3e7ff 100644 --- a/src/token.rs +++ b/src/token.rs @@ -1,4 +1,4 @@ -use crate::{inflow::InflowEnd, source_files::Source}; +use crate::{inflow::InflowEnd, name::Name, source_files::Source}; use derivative::Derivative; use derive_more::{Deref, IsVariant, Unwrap}; use num_bigint::BigInt; @@ -46,19 +46,13 @@ pub struct StringLiteral { pub modifier: StringModifier, } -#[derive(Clone, Debug, PartialEq)] -pub struct NamespacedIndentifier { - pub namespace: String, - pub basename: String, -} - #[derive(Clone, Debug, PartialEq, IsVariant, Unwrap)] pub enum TokenKind { EndOfFile, Error(String), Newline, Identifier(String), - NamespacedIdentifier(NamespacedIndentifier), + NamespacedIdentifier(Name), OpenCurly, CloseCurly, OpenParen, @@ -130,7 +124,7 @@ pub enum TokenKind { LogicalRightShift, Increment, Decrement, - Namespace, + StaticMember, Extend, FatArrow, } @@ -141,8 +135,12 @@ impl Display for TokenKind { TokenKind::EndOfFile => f.write_str("end-of-file"), TokenKind::Error(message) => write!(f, "'lex error - {}'", message), TokenKind::Newline => f.write_str("'newline'"), - TokenKind::Identifier(_) => f.write_str("'identifier'"), - TokenKind::NamespacedIdentifier(_) => f.write_str("'namespaced identifier'"), + TokenKind::Identifier(name) => write!(f, "(identifier) '{}'", name), + TokenKind::NamespacedIdentifier(name) => write!( + f, + "(namespaced identifier) '{}{}'", + name.namespace, name.basename, + ), TokenKind::OpenCurly => f.write_str("'{'"), TokenKind::CloseCurly => f.write_str("'}'"), TokenKind::OpenParen => f.write_str("'('"), @@ -214,7 +212,7 @@ impl Display for TokenKind { TokenKind::LogicalRightShift => f.write_str("'>>>'"), TokenKind::Increment => f.write_str("'++'"), TokenKind::Decrement => f.write_str("'--'"), - TokenKind::Namespace => f.write_str("'::'"), + TokenKind::StaticMember => f.write_str("'::'"), TokenKind::Extend => f.write_str("'..'"), TokenKind::FatArrow => f.write_str("'=>'"), } @@ -301,7 +299,7 @@ impl TokenKind { | TokenKind::Ellipsis | TokenKind::AddressOf | TokenKind::Dereference - | TokenKind::Namespace + | TokenKind::StaticMember | TokenKind::Extend | TokenKind::FatArrow => 0, }