1
0

Implement struct definition and type

This commit is contained in:
Jeff 2024-03-19 17:49:24 -04:00
parent c7b189a83f
commit 16d443d8a6
7 changed files with 133 additions and 3 deletions

View File

@ -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,
};

View File

@ -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)
}
}
}
}

View File

@ -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<Type>)>,
}
impl StructureDefinition {
pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition<Type>)>) -> Self {
Self { name, fields }
}
}
impl AbstractTree for StructureDefinition {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
Ok(())
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let struct_type = Type::Structure {
name: self.name.clone(),
fields: self.fields,
};
context.set_type(self.name, struct_type)?;
Ok(Action::None)
}
}

View File

@ -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<Type>)>,
},
}

View File

@ -23,6 +23,10 @@ pub enum ValueNode {
),
Range(Range<i64>),
String(String),
Structure {
name: Identifier,
fields: Vec<(Identifier, Type)>,
},
Function {
parameters: Vec<(Identifier, WithPosition<Type>)>,
return_type: WithPosition<Type>,
@ -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!(),
}
}
}

View File

@ -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(),

View File

@ -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!(