aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornic-gaffney <gaffney_nic@protonmail.com>2023-09-13 02:29:56 -0500
committernic-gaffney <gaffney_nic@protonmail.com>2023-09-13 02:29:56 -0500
commitb81d5efb177d40e712becf84063ea3c36ae083e1 (patch)
treec2b1c9b6d04133bda5a2a461bf2a7b72c91415da
parenta224e3bed1fb765b484e9d28a6242c91d9ffad4d (diff)
downloadsloth-b81d5efb177d40e712becf84063ea3c36ae083e1.tar.gz
clippy my beloved (also structs)
-rw-r--r--sloth/src/analysis/setup.rs36
-rw-r--r--sloth/src/codegen/mod.rs1
-rw-r--r--sloth/src/lexer.rs5
-rw-r--r--sloth/src/parser/ast.rs12
-rw-r--r--sloth/src/parser/stmt.rs33
-rw-r--r--sloth/src/symtable.rs5
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>,
},