Add parsing for fields structs

This commit is contained in:
Jeff 2024-08-13 18:48:02 -04:00
parent a78d560a0d
commit b55a79d6bf
4 changed files with 118 additions and 37 deletions

View File

@ -491,7 +491,11 @@ pub enum StructDefinition {
}, },
Tuple { Tuple {
name: Node<Identifier>, name: Node<Identifier>,
fields: Vec<Node<Type>>, items: Vec<Node<Type>>,
},
Fields {
name: Node<Identifier>,
fields: Vec<(Node<Identifier>, Node<Type>)>,
}, },
} }
@ -499,7 +503,10 @@ impl Display for StructDefinition {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
StructDefinition::Unit { name } => write!(f, "struct {name}"), StructDefinition::Unit { name } => write!(f, "struct {name}"),
StructDefinition::Tuple { name, fields } => { StructDefinition::Tuple {
name,
items: fields,
} => {
write!(f, "struct {name} {{")?; write!(f, "struct {name} {{")?;
for (i, field) in fields.iter().enumerate() { for (i, field) in fields.iter().enumerate() {
@ -510,6 +517,19 @@ impl Display for StructDefinition {
write!(f, "{field}")?; write!(f, "{field}")?;
} }
write!(f, "}}")
}
StructDefinition::Fields { name, fields } => {
write!(f, "struct {name} {{")?;
for (i, (field_name, field_type)) in fields.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{field_name}: {field_type}")?;
}
write!(f, "}}") write!(f, "}}")
} }
} }

View File

@ -307,7 +307,7 @@ impl<'a> Analyzer<'a> {
if let Some(Type::Struct(struct_type)) = invokee_type { if let Some(Type::Struct(struct_type)) = invokee_type {
match struct_type { match struct_type {
StructType::Unit { name } => todo!(), StructType::Unit { .. } => todo!(),
StructType::Tuple { fields, .. } => { StructType::Tuple { fields, .. } => {
for (expected_type, argument) in fields.iter().zip(arguments.iter()) for (expected_type, argument) in fields.iter().zip(arguments.iter())
{ {
@ -328,7 +328,7 @@ impl<'a> Analyzer<'a> {
} }
} }
} }
StructType::Fields { name, fields } => todo!(), StructType::Fields { .. } => todo!(),
} }
} }
} }
@ -459,7 +459,10 @@ impl<'a> Analyzer<'a> {
name: name.inner.clone(), name: name.inner.clone(),
}), }),
), ),
StructDefinition::Tuple { name, fields } => ( StructDefinition::Tuple {
name,
items: fields,
} => (
name.inner.clone(), name.inner.clone(),
Type::Struct(StructType::Tuple { Type::Struct(StructType::Tuple {
name: name.inner.clone(), name: name.inner.clone(),
@ -469,6 +472,18 @@ impl<'a> Analyzer<'a> {
.collect(), .collect(),
}), }),
), ),
StructDefinition::Fields { name, fields } => (
name.inner.clone(),
Type::Struct(StructType::Fields {
name: name.inner.clone(),
fields: fields
.iter()
.map(|(identifier, r#type)| {
(identifier.inner.clone(), r#type.inner.clone())
})
.collect(),
}),
),
}; };
self.context.set_type(name, r#type, node.position); self.context.set_type(name, r#type, node.position);

View File

@ -580,7 +580,7 @@ impl<'src> Parser<'src> {
return Ok(Node::new( return Ok(Node::new(
Statement::StructDefinition(StructDefinition::Tuple { Statement::StructDefinition(StructDefinition::Tuple {
name, name,
fields: types, items: types,
}), }),
(left_position.0, right_position.1), (left_position.0, right_position.1),
)); ));
@ -595,12 +595,53 @@ impl<'src> Parser<'src> {
types.push(type_node); types.push(type_node);
} }
} else {
Ok(Node::new(
Statement::StructDefinition(StructDefinition::Unit { name }),
(left_position.0, name_end),
))
} }
if let Token::LeftCurlyBrace = self.current.0 {
self.next_token()?;
let mut fields = Vec::new();
loop {
if let (Token::RightCurlyBrace, right_position) = self.current {
self.next_token()?;
return Ok(Node::new(
Statement::StructDefinition(StructDefinition::Fields {
name,
fields,
}),
(left_position.0, right_position.1),
));
}
if let (Token::Comma, _) = self.current {
self.next_token()?;
continue;
}
let field_name = self.parse_identifier()?;
if let (Token::Colon, _) = self.current {
self.next_token()?;
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::Colon,
actual: self.current.0.to_owned(),
position: self.current.1,
});
}
let field_type = self.parse_type()?;
fields.push((field_name, field_type));
}
}
Ok(Node::new(
Statement::StructDefinition(StructDefinition::Unit { name }),
(left_position.0, name_end),
))
} }
(Token::While, left_position) => { (Token::While, left_position) => {
self.next_token()?; self.next_token()?;
@ -1042,6 +1083,34 @@ mod tests {
use super::*; use super::*;
#[test]
fn fields_struct() {
let input = "struct Foo { a: int, b: float }";
assert_eq!(
parse(input),
Ok(AbstractSyntaxTree {
nodes: [Node::new(
Statement::StructDefinition(StructDefinition::Fields {
name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![
(
Node::new(Identifier::new("a"), (13, 14)),
Node::new(Type::Integer, (16, 19))
),
(
Node::new(Identifier::new("b"), (21, 22)),
Node::new(Type::Float, (24, 29))
)
]
}),
(0, 31)
)]
.into()
})
);
}
#[test] #[test]
fn tuple_struct_instantiation() { fn tuple_struct_instantiation() {
let input = "struct Foo(int, float) Foo(1, 2.0)"; let input = "struct Foo(int, float) Foo(1, 2.0)";
@ -1053,7 +1122,7 @@ mod tests {
Node::new( Node::new(
Statement::StructDefinition(StructDefinition::Tuple { Statement::StructDefinition(StructDefinition::Tuple {
name: Node::new(Identifier::new("Foo"), (7, 10)), name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![ items: vec![
Node::new(Type::Integer, (11, 14)), Node::new(Type::Integer, (11, 14)),
Node::new(Type::Float, (16, 21)) Node::new(Type::Float, (16, 21))
] ]
@ -1090,7 +1159,7 @@ mod tests {
nodes: [Node::new( nodes: [Node::new(
Statement::StructDefinition(StructDefinition::Tuple { Statement::StructDefinition(StructDefinition::Tuple {
name: Node::new(Identifier::new("Foo"), (7, 10)), name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![ items: vec![
Node::new(Type::Integer, (11, 14)), Node::new(Type::Integer, (11, 14)),
Node::new(Type::Float, (16, 21)) Node::new(Type::Float, (16, 21))
] ]

View File

@ -599,30 +599,7 @@ impl Vm {
Ok(None) Ok(None)
} }
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(_) => Ok(None),
let (type_name, r#type) = match struct_definition {
StructDefinition::Unit { name } => (
name.inner.clone(),
Type::Struct(StructType::Unit {
name: name.inner.clone(),
}),
),
StructDefinition::Tuple { name, fields } => (
name.inner.clone(),
Type::Struct(StructType::Tuple {
name: name.inner.clone(),
fields: fields
.into_iter()
.map(|type_node| type_node.inner)
.collect(),
}),
),
};
self.context.set_type(type_name, r#type, node.position);
Ok(None)
}
Statement::StructInstantiation(struct_instantiation) => match struct_instantiation { Statement::StructInstantiation(struct_instantiation) => match struct_instantiation {
StructInstantiation::Tuple { name, fields } => { StructInstantiation::Tuple { name, fields } => {
Ok(Some(Value::r#struct(Struct::Tuple { Ok(Some(Value::r#struct(Struct::Tuple {