Add parsing for fields structs
This commit is contained in:
parent
a78d560a0d
commit
b55a79d6bf
@ -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, "}}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,13 +595,54 @@ impl<'src> Parser<'src> {
|
|||||||
|
|
||||||
types.push(type_node);
|
types.push(type_node);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
} 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(
|
Ok(Node::new(
|
||||||
Statement::StructDefinition(StructDefinition::Unit { name }),
|
Statement::StructDefinition(StructDefinition::Unit { name }),
|
||||||
(left_position.0, name_end),
|
(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))
|
||||||
]
|
]
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user