From 0c2d9f8b2f6a6c56df9740f9ccfd6f87238760bc Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Mon, 19 May 2025 13:52:42 -0500 Subject: [PATCH] Add primitive type uses and related. --- sketching/may_2025/name_one.dm | 6 -- sketching/may_2025/std_core.dm | 7 ++ src/ast/build.rs | 33 ++++++++- src/ast/mod.rs | 21 +++++- src/bin/dmc/name_analysis.rs | 2 + src/lib.rs | 2 +- src/name_analysis/gather.rs | 16 ++++- src/name_analysis/mod.rs | 25 +++---- src/name_analysis/resolve.rs | 15 +++- src/name_analysis/symbol.rs | 113 +++++++++++++----------------- src/name_analysis/symbol_table.rs | 82 +++++++++++++--------- src/parser/deimos.pest | 48 +++++++++++-- src/std_core/mod.rs | 3 - 13 files changed, 242 insertions(+), 131 deletions(-) create mode 100644 sketching/may_2025/std_core.dm diff --git a/sketching/may_2025/name_one.dm b/sketching/may_2025/name_one.dm index 8efbadf..bd3abf6 100644 --- a/sketching/may_2025/name_one.dm +++ b/sketching/may_2025/name_one.dm @@ -1,11 +1,5 @@ ns greeter; -class Array {} - -class String {} - -platform fn println(msg: Any) -> Void; - fn main(args: Array) { println(args); } diff --git a/sketching/may_2025/std_core.dm b/sketching/may_2025/std_core.dm new file mode 100644 index 0000000..45fd263 --- /dev/null +++ b/sketching/may_2025/std_core.dm @@ -0,0 +1,7 @@ +ns std::core; + +class Array {} + +class String {} + +platform fn println(msg: Any) -> Void; diff --git a/src/ast/build.rs b/src/ast/build.rs index 16ecafe..2f7d276 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -55,7 +55,9 @@ fn build_fqn(file_id: usize, fqn_pair: Pair) -> FullyQualifiedName { fn build_type_use(file_id: usize, type_use_pair: Pair) -> TypeUse { let inner_pair = type_use_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { - Rule::Void => TypeUse::Void, + Rule::PrimitiveType => { + TypeUse::Primitive(build_primitive_type(file_id, inner_pair)) + }, Rule::InterfaceOrClassTypeUse => { TypeUse::InterfaceOrClass(build_interface_or_class_type_use(file_id, inner_pair)) } @@ -65,6 +67,35 @@ fn build_type_use(file_id: usize, type_use_pair: Pair) -> TypeUse { } } +fn build_primitive_type( + file_id: usize, + primitive_type_pair: Pair, +) -> PrimitiveTypeUse { + let mut inner = primitive_type_pair.into_inner(); + match inner.next().unwrap().as_rule() { + Rule::Byte => PrimitiveTypeUse::Byte, + Rule::Short => PrimitiveTypeUse::Short, + Rule::Char => PrimitiveTypeUse::Char, + Rule::Int => PrimitiveTypeUse::Int, + Rule::Long => PrimitiveTypeUse::Long, + Rule::Double => PrimitiveTypeUse::Double, + Rule::Bool => PrimitiveTypeUse::Bool, + Rule::String => PrimitiveTypeUse::String, + Rule::Array => { + if let Some(generic_arguments_pair) = inner.next() { + PrimitiveTypeUse::Array( + Some(Box::new(build_generic_arguments(file_id, generic_arguments_pair))) + ) + } else { + PrimitiveTypeUse::Array(None) + } + } + Rule::Any => PrimitiveTypeUse::Any, + Rule::Void => PrimitiveTypeUse::Void, + _ => unreachable!(), + } +} + fn build_interface_or_class_type_use(file_id: usize, pair: Pair) -> InterfaceOrClassTypeUse { let mut borrow_count = 0; let mut is_mutable = false; diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 16cbd0b..84c7be1 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -93,7 +93,7 @@ impl Identifier { pub fn set_saved_symbol(&mut self, saved_symbol: SavedSymbol) { self.saved_symbol = Some(saved_symbol); } - + pub fn saved_symbol(&self) -> Option { self.saved_symbol.clone() } @@ -140,12 +140,27 @@ impl FullyQualifiedName { #[derive(Debug)] pub enum TypeUse { - Void, + Primitive(PrimitiveTypeUse), InterfaceOrClass(InterfaceOrClassTypeUse), Tuple(TupleTypeUse), Function(FunctionTypeUse), } +#[derive(Debug)] +pub enum PrimitiveTypeUse { + Byte, + Short, + Char, + Int, + Long, + Double, + Bool, + String, + Array(Option>), + Any, + Void, +} + #[derive(Debug)] pub struct InterfaceOrClassTypeUse { pub borrow_count: usize, @@ -270,7 +285,7 @@ pub struct ReturnType { impl ReturnType { pub fn void() -> Self { ReturnType { - declared_type: Box::new(TypeUse::Void), + declared_type: Box::new(TypeUse::Primitive(PrimitiveTypeUse::Void)), references: References::default(), } } diff --git a/src/bin/dmc/name_analysis.rs b/src/bin/dmc/name_analysis.rs index f7a4d61..849fafb 100644 --- a/src/bin/dmc/name_analysis.rs +++ b/src/bin/dmc/name_analysis.rs @@ -7,6 +7,7 @@ use deimos::name_analysis::symbol_table::SymbolTable; use deimos::parser::{DeimosParser, Rule}; use pest::Parser; use std::path::PathBuf; +use deimos::std_core::add_std_core_symbols; pub fn name_analysis(paths: &Vec) -> Result<(), Box> { let mut compilation_units = vec![]; @@ -29,6 +30,7 @@ pub fn name_analysis(paths: &Vec) -> Result<(), Box, ) { match type_use { - TypeUse::Void => {} + TypeUse::Primitive(primitive_type_use) => { + match primitive_type_use { + PrimitiveTypeUse::Array(generic_arguments_opt) => { + if let Some(generic_arguments) = generic_arguments_opt { + gather_generic_arguments( + generic_arguments, + symbol_table, + fqn_context, + diagnostics, + ); + } + } + _ => {} + } + } TypeUse::InterfaceOrClass(interface_or_class_type_use) => { gather_interface_or_class_type_use( interface_or_class_type_use, diff --git a/src/name_analysis/mod.rs b/src/name_analysis/mod.rs index a8dc2e8..ddfe3aa 100644 --- a/src/name_analysis/mod.rs +++ b/src/name_analysis/mod.rs @@ -43,7 +43,7 @@ mod tests { use pest::Parser; use std::collections::HashMap; - fn assert_no_diagnostics(sources: HashMap<&str, &str>) -> SymbolTable { + fn assert_no_diagnostics(sources: HashMap<&str, &str>, symbol_table: &mut SymbolTable) { let mut files = SimpleFiles::new(); let mut compilation_units = vec![]; @@ -61,10 +61,7 @@ mod tests { compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap())) } - let mut symbol_table = SymbolTable::new(); - add_std_core_symbols(&mut symbol_table).expect("Failed to add std_core_symbols"); - - let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table); + let diagnostics = analyze_names(&mut compilation_units, symbol_table); if !diagnostics.is_empty() { let writer = StandardStream::stderr(ColorChoice::Always); @@ -81,8 +78,6 @@ mod tests { for compilation_unit in &compilation_units { dbg!(compilation_unit); } - - symbol_table } #[test] @@ -95,7 +90,7 @@ mod tests { }"}, )]); - assert_no_diagnostics(sources); + assert_no_diagnostics(sources, &mut SymbolTable::new()); } #[test] @@ -117,7 +112,7 @@ mod tests { ), ]); - assert_no_diagnostics(sources); + assert_no_diagnostics(sources, &mut SymbolTable::new()); } #[test] @@ -125,12 +120,14 @@ mod tests { let sources: HashMap<&str, &str> = HashMap::from([( "main.dm", indoc! {" - fn main(args: Array) { - println(args) - } - "}, + fn main(args: Array) { + println(args) + } + "}, )]); - assert_no_diagnostics(sources); + let mut symbol_table = SymbolTable::new(); + add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); + assert_no_diagnostics(sources, &mut symbol_table); } } diff --git a/src/name_analysis/resolve.rs b/src/name_analysis/resolve.rs index 09c6a31..4373f6a 100644 --- a/src/name_analysis/resolve.rs +++ b/src/name_analysis/resolve.rs @@ -43,7 +43,20 @@ fn resolve_type_use( diagnostics: &mut Vec, ) { match type_use { - TypeUse::Void => {} + TypeUse::Primitive(primitive_type_use) => { + match primitive_type_use { + PrimitiveTypeUse::Array(generic_arguments_opt) => { + if let Some(generic_arguments) = generic_arguments_opt { + resolve_generic_arguments( + generic_arguments, + symbol_table, + diagnostics, + ); + } + } + _ => {} + } + } TypeUse::InterfaceOrClass(interface_or_class_type_use) => { resolve_interface_or_class_type_use( interface_or_class_type_use, diff --git a/src/name_analysis/symbol.rs b/src/name_analysis/symbol.rs index d741d26..a5bbd7e 100644 --- a/src/name_analysis/symbol.rs +++ b/src/name_analysis/symbol.rs @@ -1,6 +1,6 @@ use crate::ast::{Identifier, UseStatement}; use std::cell::RefCell; -use std::fmt::Display; +use std::fmt::{Debug, Display, Formatter}; use std::range::Range; use std::rc::Rc; @@ -80,23 +80,8 @@ impl Symbol { } } -impl Display for Symbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - use Symbol::*; - match self { - UseStatement(use_statement_symbol) => write!(f, "{}", use_statement_symbol.borrow()), - Module(module_symbol) => write!(f, "{}", module_symbol), - Type(class_symbol) => write!(f, "{}", class_symbol), - Function(function_symbol) => write!(f, "{}", function_symbol.borrow()), - Parameter(parameter_symbol) => write!(f, "{}", parameter_symbol), - Variable(variable_symbol) => write!(f, "{}", variable_symbol), - } - } -} - /* Use-statement */ -#[derive(Debug, Clone)] pub struct UseStatementSymbol { pub fqn: String, pub declared_name: String, @@ -137,19 +122,18 @@ impl SymbolInner for UseStatementSymbol { } } -impl Display for UseStatementSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "UseStatementSymbol(fqn = {}, declared_name = {})", - self.fqn, self.declared_name - ) +impl Debug for UseStatementSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("UseStatementSymbol") + .field("fqn", &self.fqn) + .field("declared_name", &self.declared_name) + .field("referenced_symbol", &self.referenced_symbol) + .finish() } } /* Module */ -#[derive(Debug)] pub struct ModuleSymbol { fqn: String, declared_name: String, @@ -183,19 +167,18 @@ impl SymbolInner for ModuleSymbol { } } -impl Display for ModuleSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "ModuleSymbol(name = {}, is_public = {})", - self.fqn, self.is_public - ) +impl Debug for ModuleSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ModuleSymbol") + .field("fqn", &self.fqn) + .field("declared_name", &self.declared_name) + .field("is_public", &self.is_public) + .finish() } } -/* Class */ +/* TypeSymbol */ -#[derive(Debug)] pub struct TypeSymbol { fqn: String, declared_name: String, @@ -237,19 +220,18 @@ impl SymbolInner for TypeSymbol { } } -impl Display for TypeSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "TypeSymbol(fqn = {}, declared_name = {})", - self.fqn, self.declared_name - ) +impl Debug for TypeSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TypeSymbol") + .field("fqn", &self.fqn) + .field("declared_name", &self.declared_name) + .field("is_public", &self.is_public) + .finish() } } /* Function */ -#[derive(Debug)] pub struct FunctionSymbol { fqn: String, declared_name: String, @@ -278,7 +260,7 @@ impl FunctionSymbol { return_type: None, } } - + pub fn with_parameters(self, parameters: Vec) -> Self { Self { fqn: self.fqn, @@ -286,11 +268,14 @@ impl FunctionSymbol { is_public: self.is_public, is_platform: self.is_platform, definition: self.definition, - parameters: parameters.into_iter().map(|parameter| Rc::new(parameter)).collect(), + parameters: parameters + .into_iter() + .map(|parameter| Rc::new(parameter)) + .collect(), return_type: self.return_type, } } - + pub fn with_return_type(self, return_type: TypeSymbol) -> Self { Self { fqn: self.fqn, @@ -326,19 +311,21 @@ impl SymbolInner for FunctionSymbol { } } -impl Display for FunctionSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "FunctionSymbol(fqn = {}, declared_name = {}, is_public = {})", - self.fqn, self.declared_name, self.is_public - ) +impl Debug for FunctionSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("FunctionSymbol") + .field("fqn", &self.fqn) + .field("declared_name", &self.declared_name) + .field("is_public", &self.is_public) + .field("is_platform", &self.is_platform) + .field("parameters", &self.parameters) + .field("return_type", &self.return_type) + .finish() } } /* Parameter */ -#[derive(Debug)] pub struct ParameterSymbol { declared_name: String, definition: Option, @@ -363,15 +350,16 @@ impl SymbolInner for ParameterSymbol { } } -impl Display for ParameterSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "ParameterSymbol({})", self.declared_name) +impl Debug for ParameterSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ParameterSymbol") + .field("declared_name", &self.declared_name) + .finish() } } /* Variable */ -#[derive(Debug)] pub struct VariableSymbol { declared_name: String, is_mutable: bool, @@ -398,12 +386,11 @@ impl SymbolInner for VariableSymbol { } } -impl Display for VariableSymbol { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "VariableSymbol(name = {}, is_mutable = {})", - self.declared_name, self.is_mutable - ) +impl Debug for VariableSymbol { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("VariableSymbol") + .field("declared_name", &self.declared_name) + .field("is_mutable", &self.is_mutable) + .finish() } } diff --git a/src/name_analysis/symbol_table.rs b/src/name_analysis/symbol_table.rs index 6e564d6..dc54513 100644 --- a/src/name_analysis/symbol_table.rs +++ b/src/name_analysis/symbol_table.rs @@ -1,10 +1,10 @@ -use std::cell::RefCell; use crate::name_analysis::symbol::{ FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, UseStatementSymbol, VariableSymbol, }; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Display; use std::rc::Rc; @@ -37,13 +37,34 @@ impl Scope { } fn get_any_symbol(&self, name: &str) -> Option { - self.variable_symbols.get(name) + self.variable_symbols + .get(name) .map(|s| Symbol::Variable(s.clone())) - .or_else(|| self.parameter_symbols.get(name).map(|s| Symbol::Parameter(s.clone()))) - .or_else(|| self.function_symbols.get(name).map(|s| Symbol::Function(s.clone()))) - .or_else(|| self.type_symbols.get(name).map(|ts| Symbol::Type(ts.clone()))) - .or_else(|| self.module_symbols.get(name).map(|ms| Symbol::Module(ms.clone()))) - .or_else(|| self.use_statement_symbols.get(name).map(|us| Symbol::UseStatement(us.clone()))) + .or_else(|| { + self.parameter_symbols + .get(name) + .map(|s| Symbol::Parameter(s.clone())) + }) + .or_else(|| { + self.function_symbols + .get(name) + .map(|s| Symbol::Function(s.clone())) + }) + .or_else(|| { + self.type_symbols + .get(name) + .map(|ts| Symbol::Type(ts.clone())) + }) + .or_else(|| { + self.module_symbols + .get(name) + .map(|ms| Symbol::Module(ms.clone())) + }) + .or_else(|| { + self.use_statement_symbols + .get(name) + .map(|us| Symbol::UseStatement(us.clone())) + }) } fn get_module_symbol_by_declared_name(&self, name: &str) -> Option> { @@ -162,10 +183,9 @@ impl SymbolTable { let declared_name = use_statement_symbol.declared_name().to_string(); let to_insert = Rc::new(RefCell::new(use_statement_symbol)); let to_return = to_insert.clone(); - current_scope.use_statement_symbols.insert( - declared_name, - to_insert, - ); + current_scope + .use_statement_symbols + .insert(declared_name, to_insert); Ok(to_return) } } @@ -216,10 +236,9 @@ impl SymbolTable { let declared_name = function_symbol.declared_name().to_string(); let to_insert = Rc::new(RefCell::new(function_symbol)); let to_return = to_insert.clone(); - current_scope.function_symbols.insert( - declared_name, - to_insert - ); + current_scope + .function_symbols + .insert(declared_name, to_insert); Ok(to_return) } } @@ -236,10 +255,9 @@ impl SymbolTable { } else { let to_insert = Rc::new(parameter_symbol); let to_return = to_insert.clone(); - current_scope.parameter_symbols.insert( - to_insert.declared_name().to_string(), - to_insert, - ); + current_scope + .parameter_symbols + .insert(to_insert.declared_name().to_string(), to_insert); Ok(to_return) } } @@ -295,24 +313,24 @@ impl Display for SymbolTable { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; for (i, scope) in self.scopes.iter().enumerate() { - writeln!(f, "Scope {} {}", i, scope.debug_name)?; - for (name, symbol) in &scope.use_statement_symbols { - writeln!(f, " {}({})", name, symbol.borrow())?; + writeln!(f, "----Scope {} {}----", i, scope.debug_name)?; + for symbol in scope.use_statement_symbols.values() { + writeln!(f, "{:#?}", symbol.borrow())?; } - for (name, symbol) in &scope.module_symbols { - writeln!(f, " {}({})", name, symbol)?; + for symbol in scope.module_symbols.values() { + writeln!(f, "{:#?}", symbol)?; } - for (name, symbol) in &scope.type_symbols { - writeln!(f, " {}({})", name, symbol)?; + for symbol in scope.type_symbols.values() { + writeln!(f, "{:#?}", symbol)?; } - for (name, symbol) in &scope.function_symbols { - writeln!(f, " {}({})", name, symbol.borrow())?; + for symbol in scope.function_symbols.values() { + writeln!(f, "{:#?}", symbol.borrow())?; } - for (name, symbol) in &scope.parameter_symbols { - writeln!(f, " {}({})", name, symbol)?; + for symbol in scope.parameter_symbols.values() { + writeln!(f, "{:#?}", symbol)?; } - for (name, symbol) in &scope.variable_symbols { - writeln!(f, " {}({})", name, symbol)?; + for symbol in scope.variable_symbols.values() { + writeln!(f, "{:#?}", symbol)?; } } Ok(()) diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 50aba7a..4661e3d 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -2,7 +2,7 @@ Ns = { "ns" } TypeKw = { "type" } Mod = { "mod" } -Int = { "int" } +IntKw = { "int" } ClassKw = { "class" } Platform = { "platform" } Pub = { "pub" } @@ -15,7 +15,6 @@ Ref = { "ref" } Def = { "def" } Where = { "where" } Infer = { "infer" } -Void = { "Void" } Delegate = { "delegate" } Let = { "let" } Fn = { "fn" } @@ -32,12 +31,25 @@ True = { "true" } False = { "false" } Use = { "use" } +// Keywords: primitive types +Byte = { "Byte" } +Short = { "Short" } +Char = { "Char" } +Int = { "Int" } +Long = { "Long" } +Double = { "Double" } +Bool = { "Bool" } +String = { "String" } +Array = { "Array" } +Any = { "Any" } +Void = { "Void" } + // Keywords as a rule (for preventing identifiers with keywords, etc.) Keyword = { Ns | TypeKw | Mod - | Int + | IntKw | ClassKw | Platform | Pub @@ -50,7 +62,6 @@ Keyword = { | Def | Where | Infer - | Void | Delegate | Let | Fn @@ -66,6 +77,17 @@ Keyword = { | True | False | Use + | Byte + | Short + | Char + | Int + | Long + | Double + | Bool + | String + | Array + | Any + | Void } // Symbols @@ -180,12 +202,26 @@ ParenthesesOptionalTypeUseList = { // Parameters = declaration TypeUse = { - Void + PrimitiveType | InterfaceOrClassTypeUse | TupleTypeUse | FunctionTypeUse } +PrimitiveType = { + Byte + | Short + | Char + | Int + | Long + | Double + | Bool + | String + | Array ~ GenericArguments? + | Any + | Void +} + InterfaceOrClassTypeUse = { Borrow* ~ Mut? @@ -335,7 +371,7 @@ Module = { Interface = { Pub? - ~ Int + ~ IntKw ~ Identifier ~ GenericParameters? ~ ImplementsList? diff --git a/src/std_core/mod.rs b/src/std_core/mod.rs index f6ccf1b..733e853 100644 --- a/src/std_core/mod.rs +++ b/src/std_core/mod.rs @@ -2,9 +2,6 @@ use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol, TypeSymbol}; use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { - symbol_table.insert_type_symbol(TypeSymbol::new("std::core:Array", "Array", true, None))?; - // todo: make this primitive - symbol_table.insert_type_symbol(TypeSymbol::new("std::core::String", "String", true, None))?; symbol_table.insert_function_symbol( FunctionSymbol::new("std::core::println", "println", true, true, None) .with_parameters(vec![ParameterSymbol::new("msg", None)]),