Add parsing for fields structs
This commit is contained in:
parent
a78d560a0d
commit
b55a79d6bf
@ -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, "}}")
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
]
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user