Implement struct definition and type
This commit is contained in:
parent
c7b189a83f
commit
16d443d8a6
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
src/abstract_tree/structure_definition.rs
Normal file
39
src/abstract_tree/structure_definition.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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>)>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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!(
|
||||
|
Loading…
Reference in New Issue
Block a user