diff options
| author | nic-gaffney <gaffney_nic@protonmail.com> | 2023-09-13 02:29:56 -0500 |
|---|---|---|
| committer | nic-gaffney <gaffney_nic@protonmail.com> | 2023-09-13 02:29:56 -0500 |
| commit | b81d5efb177d40e712becf84063ea3c36ae083e1 (patch) | |
| tree | c2b1c9b6d04133bda5a2a461bf2a7b72c91415da | |
| parent | a224e3bed1fb765b484e9d28a6242c91d9ffad4d (diff) | |
| download | sloth-b81d5efb177d40e712becf84063ea3c36ae083e1.tar.gz | |
clippy my beloved (also structs)
| -rw-r--r-- | sloth/src/analysis/setup.rs | 36 | ||||
| -rw-r--r-- | sloth/src/codegen/mod.rs | 1 | ||||
| -rw-r--r-- | sloth/src/lexer.rs | 5 | ||||
| -rw-r--r-- | sloth/src/parser/ast.rs | 12 | ||||
| -rw-r--r-- | sloth/src/parser/stmt.rs | 33 | ||||
| -rw-r--r-- | sloth/src/symtable.rs | 5 |
6 files changed, 90 insertions, 2 deletions
diff --git a/sloth/src/analysis/setup.rs b/sloth/src/analysis/setup.rs index faf10f1..69e7efb 100644 --- a/sloth/src/analysis/setup.rs +++ b/sloth/src/analysis/setup.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use super::AnalysisError; use crate::parser::ast::{ AstNode, BinaryOp, Expr, ExprKind, Function, FunctionInput, FunctionKind, Literal, Stmt, @@ -39,6 +41,14 @@ impl Populator { )?; table.insert(identifier.to_owned(), symbol); } + StmtKind::DefineStruct { + identifier, + properties, + } => { + let symbol = + self.build_struct_symbol(node.line(), &table, properties.clone())?; + table.insert(identifier.to_owned(), symbol); + } StmtKind::DefineValue { identifier, typ, .. } => { @@ -124,6 +134,24 @@ impl Populator { })) } + fn build_struct_symbol( + &mut self, + line: u32, + table: &SymbolTable, + properties: HashMap<String, TypeIdentifier>, + ) -> Result<Symbol, AnalysisError> { + let properties = properties + .iter() + .map(|it| (it.0.clone(), table.get_type(&it.1).unwrap())) + .collect::<HashMap<String, Type>>(); + + Ok(Symbol::Value(ValueSymbol { + typ: Type::Struct { properties }, + id: self.reserve_id(), + mutable: true, + })) + } + fn build_function_symbol( &mut self, line: u32, @@ -194,6 +222,10 @@ pub(super) fn propagate_types_stmt(node: &mut Stmt) -> Result<(), AnalysisError> StmtKind::DefineValue { value, .. } => { propagate_types(value)?; } + StmtKind::DefineStruct { + identifier, + properties, + } => (), StmtKind::AssignVariable { value, .. } => { propagate_types(value)?; } @@ -257,6 +289,10 @@ pub(super) fn propagate_types(node: &mut Expr) -> Result<(), AnalysisError> { } match op { + BinaryOp::PathRes => lhs + .typ + .clone() + .ok_or(AnalysisError::Unknown(node.line, "Error Propagating Type"))?, BinaryOp::Add | BinaryOp::Con | BinaryOp::Sub diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs index ca7598c..91bc078 100644 --- a/sloth/src/codegen/mod.rs +++ b/sloth/src/codegen/mod.rs @@ -325,6 +325,7 @@ impl<'ctx> Codegen<'ctx> { Type::Integer => self.context.i32_type().fn_type(&inputs_typ, false), Type::Float => self.context.f32_type().fn_type(&inputs_typ, false), Type::Boolean => self.context.bool_type().fn_type(&inputs_typ, false), + // Type::Pointer => self.context.ptr_type().fn_type(&inputs_typ, false), Type::Array { ref typ, .. } => { let i32_type = self.context.i32_type().as_basic_type_enum(); diff --git a/sloth/src/lexer.rs b/sloth/src/lexer.rs index 5033c99..7b71377 100644 --- a/sloth/src/lexer.rs +++ b/sloth/src/lexer.rs @@ -102,6 +102,7 @@ pub enum TokenType { Loop, Break, Continue, + Struct, As, @@ -173,6 +174,7 @@ impl Display for TokenType { TokenType::Arrow => "->", TokenType::FatArrow => "=>", TokenType::Const => "const", + TokenType::Struct => "struct", TokenType::Val => "val", TokenType::Var => "var", TokenType::Fn => "fn", @@ -593,7 +595,7 @@ mod tests { #[test] fn lex_keywords() { - let source = "val var fn if else while for in loop break continue as true false"; + let source = "val var fn if else while for in loop break continue as true false struct"; let tokens = Lexer::new(source).map(|it| it.tt).collect_vec(); assert_eq!(&tokens, &[ @@ -611,6 +613,7 @@ mod tests { TokenType::As, Literal::Boolean(true).into(), Literal::Boolean(false).into(), + TokenType::Struct, ]); } diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs index a82a6df..e93dcdb 100644 --- a/sloth/src/parser/ast.rs +++ b/sloth/src/parser/ast.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fmt::Display; use crate::lexer::{self, TokenType}; @@ -167,6 +168,10 @@ impl Stmt { let mut children = Vec::new(); match &self.kind { + StmtKind::DefineStruct { + identifier, + properties, + } => (), StmtKind::Block(inner) => { children.extend(inner.iter().map(Self::as_node)); } @@ -243,6 +248,10 @@ pub enum StmtKind { identifier: String, value: Expr, }, + DefineStruct { + identifier: String, + properties: HashMap<String, TypeIdentifier>, + }, /// A function definition. Output is None when the function returns nothing /// meaning void, otherwise it is the name of the type the function /// returns. @@ -360,6 +369,7 @@ pub enum BinaryOp { LogicalOr, Range, + PathRes, } impl TryFrom<TokenType> for BinaryOp { @@ -385,6 +395,7 @@ impl TryFrom<TokenType> for BinaryOp { TokenType::PipePipe => Self::LogicalOr, TokenType::DotDot => Self::Range, + TokenType::Dot => Self::PathRes, _ => return Err(ParsingError::InvalidOp), }; @@ -414,6 +425,7 @@ impl Display for BinaryOp { BinaryOp::LogicalOr => "||", BinaryOp::Range => "..", + BinaryOp::PathRes => ".", }; write!(f, "{value}") diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs index 54534c4..9496d88 100644 --- a/sloth/src/parser/stmt.rs +++ b/sloth/src/parser/stmt.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use super::ast::{Function, FunctionInput, FunctionKind, Stmt, StmtKind}; use super::{AstParser, ParsingError}; use crate::lexer::TokenType; @@ -17,6 +19,7 @@ impl<'a> AstParser<'a> { TokenType::For => self.for_stmt(), TokenType::Var => self.define_variable(), TokenType::Val => self.define_value(), + TokenType::Struct => self.define_struct(), TokenType::Fn => self.define_function(false), TokenType::Return => self.return_stmt(), @@ -150,6 +153,36 @@ impl<'a> AstParser<'a> { )) } + fn define_struct(&mut self) -> Result<Stmt, ParsingError> { + let mut properties = HashMap::new(); + + self.consume(TokenType::Struct, "Expected struct")?; + + let identifier = self.consume_identifier()?; + + while self.peek().tt != TokenType::ClosingBracket { + self.consume(TokenType::Val, "Expected val in struct!")?; + + let ident = self.consume_identifier()?; + let typ = self.consume_type()?; + + properties.insert(ident, typ).ok_or(0); + } + self.consume(TokenType::ClosingBracket, "Expected '}' at end of struct"); + + let kind = StmtKind::DefineStruct { + identifier, + properties, + }; + + Ok(Stmt::new( + self.reserve_id(), + self.line, + kind, + self.top.clone(), + )) + } + fn define_value(&mut self) -> Result<Stmt, ParsingError> { // Consume the val token self.consume(TokenType::Val, "Expected val")?; diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs index 06c0026..bdf6194 100644 --- a/sloth/src/symtable.rs +++ b/sloth/src/symtable.rs @@ -146,7 +146,7 @@ pub struct ValueSymbol { pub mutable: bool, } -#[derive(Clone, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Debug, PartialEq)] pub enum Type { Void, Integer, @@ -160,6 +160,9 @@ pub enum Type { inputs: Vec<Type>, output: Box<Type>, }, + Struct { + properties: HashMap<String, Type>, + }, Array { typ: Box<Type>, }, |
