From 2c5a70df1a6bb4452b277341ad6618ac31485d65 Mon Sep 17 00:00:00 2001 From: IsaacShelton Date: Sun, 22 Sep 2024 13:00:20 -0500 Subject: [PATCH] Added initial ability for structs to be namespaced, as well as cleaned up some namespacing code --- src/ast/function/mod.rs | 5 ++--- src/ast/structure/mod.rs | 4 ++-- src/c/translation/function.rs | 4 ++-- src/c/translation/types/composite.rs | 4 ++-- src/interpreter_env/mod.rs | 29 +++++++++++----------------- src/lexer/identifier_state.rs | 4 ++++ src/lower/mod.rs | 1 - src/name.rs | 23 +++++++++++++++++++++- src/parser/parse_function.rs | 4 ++-- src/parser/parse_structure.rs | 7 +++++-- src/pragma_section/parse.rs | 4 ++-- src/pragma_section/run.rs | 2 +- src/resolve/core_structure_info.rs | 3 ++- src/resolve/expr/struct_literal.rs | 2 +- src/resolve/mod.rs | 29 ++++++++++++++-------------- src/resolve/type_search_ctx.rs | 12 ++++++++---- src/resolved/mod.rs | 6 +++--- src/target/type_layout.rs | 4 +--- src/workspace/mod.rs | 2 +- 19 files changed, 86 insertions(+), 63 deletions(-) diff --git a/src/ast/function/mod.rs b/src/ast/function/mod.rs index 8dd94ca4..3c552c5b 100644 --- a/src/ast/function/mod.rs +++ b/src/ast/function/mod.rs @@ -1,12 +1,12 @@ mod parameters; use super::{Stmt, Type}; -use crate::{source_files::Source, tag::Tag}; +use crate::{name::Name, source_files::Source, tag::Tag}; pub use parameters::{Parameter, Parameters}; #[derive(Clone, Debug)] pub struct Function { - pub name: String, + pub name: Name, pub parameters: Parameters, pub return_type: Type, pub stmts: Vec, @@ -14,5 +14,4 @@ pub struct Function { pub source: Source, pub abide_abi: bool, pub tag: Option, - pub namespace: Option, } diff --git a/src/ast/structure/mod.rs b/src/ast/structure/mod.rs index f6c84f44..ec90b7c9 100644 --- a/src/ast/structure/mod.rs +++ b/src/ast/structure/mod.rs @@ -1,10 +1,10 @@ use super::Type; -use crate::source_files::Source; +use crate::{name::Name, source_files::Source}; use indexmap::IndexMap; #[derive(Clone, Debug)] pub struct Structure { - pub name: String, + pub name: Name, pub fields: IndexMap, pub is_packed: bool, pub source: Source, diff --git a/src/c/translation/function.rs b/src/c/translation/function.rs index da5113d7..072b09ff 100644 --- a/src/c/translation/function.rs +++ b/src/c/translation/function.rs @@ -6,6 +6,7 @@ use crate::{ ParameterDeclarationCore, ParameterTypeList, ParseError, }, diagnostics::Diagnostics, + name::Name, }; use std::collections::HashMap; @@ -72,7 +73,7 @@ pub fn declare_function( }; ast_file.functions.push(Function { - name, + name: Name::plain(name), parameters, return_type, stmts: vec![], @@ -80,7 +81,6 @@ pub fn declare_function( source, abide_abi: true, tag: None, - namespace: None, }); Ok(()) diff --git a/src/c/translation/types/composite.rs b/src/c/translation/types/composite.rs index 5aaebfea..aaf3b04b 100644 --- a/src/c/translation/types/composite.rs +++ b/src/c/translation/types/composite.rs @@ -90,7 +90,7 @@ pub fn make_composite( let is_packed = false; if let Some(name) = &composite.name { - let name = format!("struct<{}>", name); + let name = Name::plain(format!("struct<{}>", name)); ast_file.structures.push(Structure { name: name.clone(), @@ -99,7 +99,7 @@ pub fn make_composite( source: composite.source, }); - Ok(TypeKind::Named(Name::plain(name))) + Ok(TypeKind::Named(name)) } else { let anonymous_struct = AnonymousStruct { fields, is_packed }; diff --git a/src/interpreter_env/mod.rs b/src/interpreter_env/mod.rs index bc16e361..08fed70f 100644 --- a/src/interpreter_env/mod.rs +++ b/src/interpreter_env/mod.rs @@ -15,12 +15,12 @@ use crate::{ }; use indexmap::IndexMap; -fn thin_void_function(name: impl ToString, syscall_kind: InterpreterSyscallKind) -> Function { +fn thin_void_function(name: impl Into, syscall_kind: InterpreterSyscallKind) -> Function { let source = Source::internal(); let void = TypeKind::Void.at(Source::internal()); Function { - name: name.to_string(), + name: Name::plain(name), parameters: Parameters { required: vec![], is_cstyle_vararg: false, @@ -39,33 +39,29 @@ fn thin_void_function(name: impl ToString, syscall_kind: InterpreterSyscallKind) is_foreign: false, source, tag: None, - namespace: None, } } fn thin_cstring_function( - name: impl ToString, - param_name: impl ToString, + name: impl Into, + param_name: impl Into, syscall_kind: InterpreterSyscallKind, ) -> Function { let source = Source::internal(); let void = TypeKind::Void.at(Source::internal()); let ptr_char = TypeKind::Pointer(Box::new(TypeKind::char().at(source))).at(source); - + let param_name = param_name.into(); Function { - name: name.to_string(), + name: Name::plain(name.into()), parameters: Parameters { - required: vec![Parameter::new(param_name.to_string(), ptr_char.clone())], + required: vec![Parameter::new(param_name.clone(), ptr_char.clone())], is_cstyle_vararg: false, }, return_type: void.clone(), stmts: vec![StmtKind::Expr( ExprKind::InterpreterSyscall(Box::new(InterpreterSyscall { kind: syscall_kind, - args: vec![( - ptr_char.clone(), - ExprKind::Variable(param_name.to_string()).at(source), - )], + args: vec![(ptr_char.clone(), ExprKind::Variable(param_name).at(source))], result_type: void.clone(), })) .at(source), @@ -75,7 +71,6 @@ fn thin_cstring_function( is_foreign: false, source, tag: None, - namespace: None, } } @@ -94,7 +89,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { .at(Source::internal()); file.functions.push(Function { - name: "".into(), + name: Name::plain(""), parameters: Parameters::default(), return_type: void.clone(), stmts: vec![StmtKind::Return(Some(call)).at(Source::internal())], @@ -102,7 +97,6 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { source, abide_abi: false, tag: Some(Tag::InterpreterEntryPoint), - namespace: None, }); file.enums.insert( @@ -130,7 +124,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { ); file.structures.push(Structure { - name: "Project".into(), + name: Name::plain("Project"), fields: IndexMap::from_iter([( "kind".into(), Field { @@ -185,7 +179,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { )); file.functions.push(Function { - name: "project".into(), + name: Name::plain("project"), parameters: Parameters { required: vec![ Parameter::new("name".into(), ptr_char.clone()), @@ -223,7 +217,6 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) { is_foreign: false, source, tag: None, - namespace: None, }); } diff --git a/src/lexer/identifier_state.rs b/src/lexer/identifier_state.rs index d09e096c..7044e0ae 100644 --- a/src/lexer/identifier_state.rs +++ b/src/lexer/identifier_state.rs @@ -16,6 +16,10 @@ impl IdentifierState { if let Some(last_slash) = self.last_slash { let basename = identifier.split_off(last_slash + 1); + + // Remove trailing slash + identifier.pop(); + let namespace = identifier; return TokenKind::NamespacedIdentifier(Name { diff --git a/src/lower/mod.rs b/src/lower/mod.rs index f8b6cd2c..5692a713 100644 --- a/src/lower/mod.rs +++ b/src/lower/mod.rs @@ -189,7 +189,6 @@ fn lower_function( } } - eprintln!("warning: name mangling does not take all cases into account yet"); let mangled_name = if function.name.plain() == "main" { "main".into() } else if function.is_foreign { diff --git a/src/name.rs b/src/name.rs index b97e9f26..8e01bda9 100644 --- a/src/name.rs +++ b/src/name.rs @@ -7,6 +7,15 @@ pub struct Name { } impl Name { + pub fn new(namespace: Option>, basename: impl Into) -> Self { + Self { + namespace: namespace + .map(|namespace| namespace.into()) + .unwrap_or_default(), + basename: basename.into(), + } + } + pub fn plain(basename: impl Into) -> Self { Self { namespace: "".into(), @@ -29,11 +38,19 @@ impl Name { None } } + + pub fn fullname(&self) -> String { + if self.namespace.is_empty() { + self.basename.clone() + } else { + format!("{}/{}", self.namespace, self.basename) + } + } } impl Display for Name { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}{}", self.namespace, self.basename) + write!(f, "{}", self.fullname()) } } @@ -44,6 +61,10 @@ pub enum ResolvedName { } impl ResolvedName { + pub fn new(name: &Name) -> Self { + Self::Project(name.fullname().into_boxed_str()) + } + pub fn plain(&self) -> &str { match self { ResolvedName::Remote(name) => &**name, diff --git a/src/parser/parse_function.rs b/src/parser/parse_function.rs index 89163671..17f79ba2 100644 --- a/src/parser/parse_function.rs +++ b/src/parser/parse_function.rs @@ -6,6 +6,7 @@ use super::{ use crate::{ ast::{Function, Parameters, TypeKind}, inflow::Inflow, + name::Name, token::{Token, TokenKind}, }; @@ -57,7 +58,7 @@ impl<'a, I: Inflow> Parser<'a, I> { .unwrap_or_default(); Ok(Function { - name, + name: Name::new(namespace, name), parameters, return_type, stmts, @@ -65,7 +66,6 @@ impl<'a, I: Inflow> Parser<'a, I> { source, abide_abi, tag: None, - namespace, }) } } diff --git a/src/parser/parse_structure.rs b/src/parser/parse_structure.rs index d3e4258b..264b0bba 100644 --- a/src/parser/parse_structure.rs +++ b/src/parser/parse_structure.rs @@ -6,6 +6,7 @@ use super::{ use crate::{ ast::{Field, Structure}, inflow::Inflow, + name::Name, token::{Token, TokenKind}, }; use indexmap::IndexMap; @@ -22,11 +23,13 @@ impl<'a, I: Inflow> Parser<'a, I> { self.ignore_newlines(); let mut is_packed = false; + let mut namespace = None; for annotation in annotations { match annotation.kind { AnnotationKind::Packed => is_packed = true, - _ => return Err(self.unexpected_annotation(&annotation, Some("for structure"))), + AnnotationKind::Namespace(new_namespace) => namespace = Some(new_namespace), + _ => return Err(self.unexpected_annotation(&annotation, Some("for struct"))), } } @@ -61,7 +64,7 @@ impl<'a, I: Inflow> Parser<'a, I> { self.parse_token(TokenKind::CloseParen, Some("to end struct fields"))?; Ok(Structure { - name, + name: Name::new(namespace, name), fields, is_packed, source, diff --git a/src/pragma_section/parse.rs b/src/pragma_section/parse.rs index 8449395e..17222895 100644 --- a/src/pragma_section/parse.rs +++ b/src/pragma_section/parse.rs @@ -3,6 +3,7 @@ use crate::{ ast::{AstFile, Expr, ExprKind, Function, Parameters, Stmt, StmtKind, TypeKind}, diagnostics::ErrorDiagnostic, inflow::Inflow, + name::Name, parser::{self, error::ParseError, Input}, show::{into_show, Show}, source_files::Source, @@ -79,7 +80,7 @@ impl PragmaSection { } ast_file.functions.push(Function { - name: "main".into(), + name: Name::plain("main"), parameters: Parameters { required: vec![], is_cstyle_vararg: false, @@ -90,7 +91,6 @@ impl PragmaSection { source, abide_abi: false, tag: None, - namespace: None, }); } else { return Err(Box::new(ParseError::expected( diff --git a/src/pragma_section/run.rs b/src/pragma_section/run.rs index 783609e5..a5f49a92 100644 --- a/src/pragma_section/run.rs +++ b/src/pragma_section/run.rs @@ -70,7 +70,7 @@ impl PragmaSection { else { return Err(into_show( ParseErrorKind::Other { - message: "No Adept version was specifed for module!".into(), + message: "No Adept version was specifed for module! Use `pragma => adept(\"3.0\")` at the top of the module file".into(), } .at(self.pragma_source), )); diff --git a/src/resolve/core_structure_info.rs b/src/resolve/core_structure_info.rs index 389de94f..c486d7a4 100644 --- a/src/resolve/core_structure_info.rs +++ b/src/resolve/core_structure_info.rs @@ -1,5 +1,6 @@ use super::error::{ResolveError, ResolveErrorKind}; use crate::{ + name::ResolvedName, resolved::{self, StructureRef}, source_files::Source, }; @@ -7,7 +8,7 @@ use crate::{ pub fn get_core_structure_info( resolved_type: &resolved::Type, source: Source, -) -> Result<(&str, StructureRef), ResolveError> { +) -> Result<(&ResolvedName, StructureRef), ResolveError> { match &resolved_type.kind { resolved::TypeKind::Structure(name, structure_ref) => Ok((name, *structure_ref)), _ => Err(ResolveErrorKind::CannotCreateStructLiteralForNonStructure { diff --git a/src/resolve/expr/struct_literal.rs b/src/resolve/expr/struct_literal.rs index f09d0a8a..cfd4c961 100644 --- a/src/resolve/expr/struct_literal.rs +++ b/src/resolve/expr/struct_literal.rs @@ -47,7 +47,7 @@ pub fn resolve_struct_literal_expr( let (struct_name, structure_ref) = get_core_structure_info(&resolved_type, source)?; let structure_type = - resolved::TypeKind::Structure(struct_name.to_string(), structure_ref).at(source); + resolved::TypeKind::Structure(struct_name.clone(), structure_ref).at(source); let mut next_index = 0; let mut resolved_fields = IndexMap::new(); diff --git a/src/resolve/mod.rs b/src/resolve/mod.rs index f5279ef5..fcc0c05e 100644 --- a/src/resolve/mod.rs +++ b/src/resolve/mod.rs @@ -22,7 +22,7 @@ use crate::{ ast::{self, AstWorkspace, Type}, cli::BuildOptions, index_map_ext::IndexMapExt, - name::ResolvedName, + name::{Name, ResolvedName}, resolved::{self, Enum, TypedExpr, VariableStorage}, source_files::{Source, SourceFiles}, tag::Tag, @@ -135,7 +135,7 @@ pub fn resolve<'a>( ); type_search_ctx.put_type( - enum_name.clone(), + &Name::plain(enum_name.clone()), resolved::TypeKind::Enum(enum_name.clone()), enum_definition.source, )?; @@ -169,16 +169,18 @@ pub fn resolve<'a>( ); } + let resolved_name = ResolvedName::new(&structure.name); + let structure_key = resolved_ast.structures.insert(resolved::Structure { - name: structure.name.clone(), + name: resolved_name.clone(), fields, is_packed: structure.is_packed, source: structure.source, }); type_search_ctx.put_type( - structure.name.clone(), - resolved::TypeKind::Structure(structure.name.clone(), structure_key), + &structure.name, + resolved::TypeKind::Structure(resolved_name, structure_key), structure.source, )?; } @@ -200,7 +202,11 @@ pub fn resolve<'a>( &mut used_aliases, )?; - type_search_ctx.put_type(alias_name.clone(), resolved_type.kind, alias.source)?; + type_search_ctx.put_type( + &Name::plain(alias_name.clone()), + resolved_type.kind, + alias.source, + )?; } } @@ -245,11 +251,7 @@ pub fn resolve<'a>( let type_search_ctx = ctx.type_search_ctxs.get_mut(&file_id).unwrap(); for (function_i, function) in file.functions.iter().enumerate() { - let name = if let Some(namespace) = function.namespace.as_ref() { - ResolvedName::Project(format!("{}/{}", namespace, function.name).into_boxed_str()) - } else { - ResolvedName::Project(function.name.clone().into_boxed_str()) - }; + let name = ResolvedName::new(&function.name); let function_ref = resolved_ast.functions.insert(resolved::Function { name: name.clone(), @@ -270,7 +272,7 @@ pub fn resolve<'a>( source: function.source, abide_abi: function.abide_abi, tag: function.tag.or_else(|| { - if options.coerce_main_signature && function.name == "main" { + if options.coerce_main_signature && function.name.basename == "main" { Some(Tag::Main) } else { None @@ -438,8 +440,7 @@ fn resolve_type<'a>( } ast::TypeKind::Void => Ok(resolved::TypeKind::Void), ast::TypeKind::Named(name) => { - eprintln!("warning: resolved_type currently always resolves name to project basename"); - let resolved_name = ResolvedName::Project(name.basename.clone().into_boxed_str()); + let resolved_name = ResolvedName::new(name); if let Some(found) = type_search_ctx.find_type(&resolved_name) { Ok(found.clone()) diff --git a/src/resolve/type_search_ctx.rs b/src/resolve/type_search_ctx.rs index a647ec40..9f5fb1be 100644 --- a/src/resolve/type_search_ctx.rs +++ b/src/resolve/type_search_ctx.rs @@ -1,5 +1,10 @@ use super::error::{ResolveError, ResolveErrorKind}; -use crate::{ast, name::ResolvedName, resolved, source_files::Source}; +use crate::{ + ast, + name::{Name, ResolvedName}, + resolved, + source_files::Source, +}; use indexmap::IndexMap; #[derive(Clone, Debug, Default)] @@ -26,12 +31,11 @@ impl<'a> TypeSearchCtx<'a> { pub fn put_type( &mut self, - name: impl ToString, + name: &Name, value: resolved::TypeKind, source: Source, ) -> Result<(), ResolveError> { - eprintln!("warning: TypeSearchCtx::put_type always puts at root"); - let resolved_name = ResolvedName::Project(name.to_string().into_boxed_str()); + let resolved_name = ResolvedName::new(name); if self.types.insert(resolved_name, value).is_some() { return Err(ResolveErrorKind::MultipleDefinitionsOfTypeNamed { diff --git a/src/resolved/mod.rs b/src/resolved/mod.rs index 083d8183..1ff589cc 100644 --- a/src/resolved/mod.rs +++ b/src/resolved/mod.rs @@ -102,7 +102,7 @@ impl PartialEq for Parameter { #[derive(Clone, Debug)] pub struct Structure { - pub name: String, + pub name: ResolvedName, pub fields: IndexMap, pub is_packed: bool, pub source: Source, @@ -154,7 +154,7 @@ pub enum TypeKind { FloatLiteral(f64), Floating(FloatSize), Pointer(Box), - Structure(String, StructureRef), + Structure(ResolvedName, StructureRef), Void, AnonymousStruct(), AnonymousUnion(), @@ -323,7 +323,7 @@ impl Display for TypeKind { write!(f, "ptr<{}>", inner.kind)?; } TypeKind::Void => f.write_str("void")?, - TypeKind::Structure(name, _) => f.write_str(name)?, + TypeKind::Structure(name, _) => write!(f, "{}", name)?, TypeKind::AnonymousStruct() => f.write_str("(anonymous struct)")?, TypeKind::AnonymousUnion() => f.write_str("(anonymous union)")?, TypeKind::AnonymousEnum(..) => f.write_str("(anonymous enum)")?, diff --git a/src/target/type_layout.rs b/src/target/type_layout.rs index 2bb3fb13..5318116c 100644 --- a/src/target/type_layout.rs +++ b/src/target/type_layout.rs @@ -108,10 +108,8 @@ impl<'a> TypeLayoutCache<'a> { .get(*structure_ref) .expect("referenced structure to exist"); - let name = &resolved_structure.name; - let info = RecordInfo::from_structure(structure); - self.get_impl_record_layout(&info, Some(name)) + self.get_impl_record_layout(&info, Some(resolved_structure.name.plain())) } ir::Type::AnonymousComposite(type_composite) => { let info = RecordInfo::from_composite(type_composite); diff --git a/src/workspace/mod.rs b/src/workspace/mod.rs index 4e5dbdaa..893c5b12 100644 --- a/src/workspace/mod.rs +++ b/src/workspace/mod.rs @@ -205,7 +205,7 @@ pub fn compile_workspace(compiler: &mut Compiler, project_folder: &Path) { } let Some(_adept_version) = compiler.version.get() else { - eprintln!("error: No Adept version was specified!, Use `pragma => adept(c\"3.0\")` at the top of your module file"); + eprintln!("error: No Adept version was specified! Use `pragma => adept(\"3.0\")` at the top of the module file"); exit(1); };