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 {
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 {
match self {
StructDefinition::Unit { name } => write!(f, "struct {name}"),
StructDefinition::Tuple { name, fields } => {
StructDefinition::Tuple {
name,
items: fields,
} => {
write!(f, "struct {name} {{")?;
for (i, field) in fields.iter().enumerate() {
@ -510,6 +517,19 @@ impl Display for StructDefinition {
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, "}}")
}
}

View File

@ -307,7 +307,7 @@ impl<'a> Analyzer<'a> {
if let Some(Type::Struct(struct_type)) = invokee_type {
match struct_type {
StructType::Unit { name } => todo!(),
StructType::Unit { .. } => todo!(),
StructType::Tuple { fields, .. } => {
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(),
}),
),
StructDefinition::Tuple { name, fields } => (
StructDefinition::Tuple {
name,
items: fields,
} => (
name.inner.clone(),
Type::Struct(StructType::Tuple {
name: name.inner.clone(),
@ -469,6 +472,18 @@ impl<'a> Analyzer<'a> {
.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);

View File

@ -580,7 +580,7 @@ impl<'src> Parser<'src> {
return Ok(Node::new(
Statement::StructDefinition(StructDefinition::Tuple {
name,
fields: types,
items: types,
}),
(left_position.0, right_position.1),
));
@ -595,12 +595,53 @@ impl<'src> Parser<'src> {
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) => {
self.next_token()?;
@ -1042,6 +1083,34 @@ mod tests {
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]
fn tuple_struct_instantiation() {
let input = "struct Foo(int, float) Foo(1, 2.0)";
@ -1053,7 +1122,7 @@ mod tests {
Node::new(
Statement::StructDefinition(StructDefinition::Tuple {
name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![
items: vec![
Node::new(Type::Integer, (11, 14)),
Node::new(Type::Float, (16, 21))
]
@ -1090,7 +1159,7 @@ mod tests {
nodes: [Node::new(
Statement::StructDefinition(StructDefinition::Tuple {
name: Node::new(Identifier::new("Foo"), (7, 10)),
fields: vec![
items: vec![
Node::new(Type::Integer, (11, 14)),
Node::new(Type::Float, (16, 21))
]

View File

@ -599,30 +599,7 @@ impl Vm {
Ok(None)
}
Statement::StructDefinition(struct_definition) => {
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::StructDefinition(_) => Ok(None),
Statement::StructInstantiation(struct_instantiation) => match struct_instantiation {
StructInstantiation::Tuple { name, fields } => {
Ok(Some(Value::r#struct(Struct::Tuple {