From 16d443d8a6bc4b8421023495a12a745cfcfdb51d Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 19 Mar 2024 17:49:24 -0400 Subject: [PATCH] Implement struct definition and type --- src/abstract_tree/mod.rs | 2 + src/abstract_tree/statement.rs | 15 ++++++- src/abstract_tree/structure_definition.rs | 39 ++++++++++++++++++ src/abstract_tree/type.rs | 4 +- src/abstract_tree/value_node.rs | 25 ++++++++++++ src/lexer.rs | 1 + src/parser.rs | 50 +++++++++++++++++++++++ 7 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 src/abstract_tree/structure_definition.rs diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index ec99013..8967932 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -10,6 +10,7 @@ pub mod r#loop; pub mod map_index; pub mod math; pub mod statement; +pub mod structure_definition; pub mod r#type; pub mod value_node; pub mod r#while; @@ -31,6 +32,7 @@ pub use self::{ r#type::Type, r#while::While, statement::Statement, + structure_definition::StructureDefinition, value_node::ValueNode, }; diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index af8afd6..b42695e 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -3,7 +3,10 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While}; +use super::{ + AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type, + While, +}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Statement { @@ -13,6 +16,7 @@ pub enum Statement { Expression(Expression), IfElse(IfElse), Loop(Loop), + StructureDefinition(StructureDefinition), While(While), } @@ -26,6 +30,9 @@ impl AbstractTree for Statement { Statement::IfElse(if_else) => if_else.expected_type(_context), Statement::Loop(r#loop) => r#loop.expected_type(_context), Statement::While(r#while) => r#while.expected_type(_context), + Statement::StructureDefinition(structure_definition) => { + structure_definition.expected_type(_context) + } } } @@ -38,6 +45,9 @@ impl AbstractTree for Statement { Statement::IfElse(if_else) => if_else.validate(_context), Statement::Loop(r#loop) => r#loop.validate(_context), Statement::While(r#while) => r#while.validate(_context), + Statement::StructureDefinition(structure_definition) => { + structure_definition.validate(_context) + } } } @@ -50,6 +60,9 @@ impl AbstractTree for Statement { Statement::IfElse(if_else) => if_else.run(_context), Statement::Loop(r#loop) => r#loop.run(_context), Statement::While(r#while) => r#while.run(_context), + Statement::StructureDefinition(structure_definition) => { + structure_definition.run(_context) + } } } } diff --git a/src/abstract_tree/structure_definition.rs b/src/abstract_tree/structure_definition.rs new file mode 100644 index 0000000..a192c88 --- /dev/null +++ b/src/abstract_tree/structure_definition.rs @@ -0,0 +1,39 @@ +use crate::{ + context::Context, + error::{RuntimeError, ValidationError}, +}; + +use super::{AbstractTree, Action, Identifier, Type, WithPosition}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct StructureDefinition { + name: Identifier, + fields: Vec<(Identifier, WithPosition)>, +} + +impl StructureDefinition { + pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition)>) -> Self { + Self { name, fields } + } +} + +impl AbstractTree for StructureDefinition { + fn expected_type(&self, _context: &Context) -> Result { + Ok(Type::None) + } + + fn validate(&self, _context: &Context) -> Result<(), ValidationError> { + Ok(()) + } + + fn run(self, context: &Context) -> Result { + let struct_type = Type::Structure { + name: self.name.clone(), + fields: self.fields, + }; + + context.set_type(self.name, struct_type)?; + + Ok(Action::None) + } +} diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs index 793eb6c..d3f480c 100644 --- a/src/abstract_tree/type.rs +++ b/src/abstract_tree/type.rs @@ -6,7 +6,7 @@ use crate::{ error::{RuntimeError, TypeConflict, ValidationError}, }; -use super::{AbstractTree, Action}; +use super::{AbstractTree, Action, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Type { @@ -27,7 +27,7 @@ pub enum Type { String, Structure { name: Identifier, - fields: Vec<(Identifier, Type)>, + fields: Vec<(Identifier, WithPosition)>, }, } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 9e5b3b3..766e957 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -23,6 +23,10 @@ pub enum ValueNode { ), Range(Range), String(String), + Structure { + name: Identifier, + fields: Vec<(Identifier, Type)>, + }, Function { parameters: Vec<(Identifier, WithPosition)>, return_type: WithPosition, @@ -59,6 +63,7 @@ impl AbstractTree for ValueNode { .collect(), return_type: Box::new(return_type.node.clone()), }, + ValueNode::Structure { name, fields } => todo!(), }; Ok(r#type) @@ -160,6 +165,7 @@ impl AbstractTree for ValueNode { return_type, body, } => Value::function(parameters, return_type, body), + ValueNode::Structure { name, fields } => todo!(), }; Ok(Action::Return(value)) @@ -228,6 +234,25 @@ impl Ord for ValueNode { } } (Function { .. }, _) => Ordering::Greater, + ( + Structure { + name: left_name, + fields: left_fields, + }, + Structure { + name: right_name, + fields: right_fields, + }, + ) => todo!(), + ( + Structure { name, fields }, + Function { + parameters, + return_type, + body, + }, + ) => todo!(), + (Structure { name, fields }, _) => todo!(), } } } diff --git a/src/lexer.rs b/src/lexer.rs index 2e2e770..bd3f196 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -224,6 +224,7 @@ pub fn lexer<'src>() -> impl Parser< just("map").padded(), just("none").padded(), just("range").padded(), + just("struct").padded(), just("str").padded(), just("loop").padded(), just("while").padded(), diff --git a/src/parser.rs b/src/parser.rs index e49b82c..e3b7e6b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -417,7 +417,27 @@ pub fn parser<'src>() -> impl Parser< .with_position(state.span()) }); + let structure_field = identifier.clone().then(type_specification.clone()); + + let structure_definition = just(Token::Keyword("struct")) + .ignore_then(identifier.clone()) + .then( + structure_field + .separated_by(just(Token::Control(Control::Comma))) + .allow_trailing() + .collect() + .delimited_by( + just(Token::Control(Control::CurlyOpen)), + just(Token::Control(Control::CurlyClose)), + ), + ) + .map_with(|(name, fields), state| { + Statement::StructureDefinition(StructureDefinition::new(name, fields)) + .with_position(state.span()) + }); + choice(( + structure_definition, if_else, assignment, expression_statement, @@ -438,6 +458,36 @@ mod tests { use super::*; + #[test] + fn structure_definition() { + assert_eq!( + parse( + &lex(" + struct Foo { + bar : int, + baz : str, + } + ") + .unwrap() + ) + .unwrap()[0] + .node, + Statement::StructureDefinition(StructureDefinition::new( + Identifier::new("Foo"), + vec![ + ( + Identifier::new("bar"), + Type::Integer.with_position((64, 67)) + ), + ( + Identifier::new("baz"), + Type::String.with_position((99, 102)) + ), + ] + )) + ) + } + #[test] fn map_index() { assert_eq!(