Implement enums
This commit is contained in:
parent
9f98617f6a
commit
087d926c3d
@ -43,13 +43,13 @@ impl AbstractTree for EnumDefinition {
|
||||
Ok(Type::None)
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||
context.set_enum_definition(self.name.clone(), self.clone())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||
context.set_enum_definition(self.name.clone(), self)?;
|
||||
|
||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
||||
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 {
|
||||
@ -16,7 +16,7 @@ pub enum Type {
|
||||
Enum {
|
||||
name: Identifier,
|
||||
type_arguments: Option<Vec<Type>>,
|
||||
variants: Vec<(Identifier, Option<Type>)>,
|
||||
variants: Vec<(Identifier, Option<WithPosition<Type>>)>,
|
||||
},
|
||||
Float,
|
||||
Function {
|
||||
|
@ -42,12 +42,7 @@ impl AbstractTree for ValueNode {
|
||||
let r#type = match self {
|
||||
ValueNode::Boolean(_) => Type::Boolean,
|
||||
|
||||
ValueNode::EnumInstance {
|
||||
name,
|
||||
variant: _,
|
||||
type_arguments,
|
||||
expression: _,
|
||||
} => {
|
||||
ValueNode::EnumInstance { name, .. } => {
|
||||
if let Some(r#type) = context.get_type(name)? {
|
||||
r#type
|
||||
} else {
|
||||
@ -130,13 +125,34 @@ impl AbstractTree for ValueNode {
|
||||
}
|
||||
|
||||
if let ValueNode::EnumInstance {
|
||||
name,
|
||||
variant,
|
||||
type_arguments,
|
||||
expression,
|
||||
variant,
|
||||
..
|
||||
} = self
|
||||
{
|
||||
let r#type = self.expected_type(context)?;
|
||||
|
||||
if let Type::Enum { variants, .. } = r#type {
|
||||
let expected_type_option = variants.iter().find_map(|(identifier, type_option)| {
|
||||
if identifier == variant {
|
||||
type_option.clone()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(expected_type) = expected_type_option {
|
||||
let actual_type = expression.node.expected_type(context)?;
|
||||
|
||||
expected_type.node.check(&actual_type).map_err(|conflict| {
|
||||
ValidationError::TypeCheck {
|
||||
conflict,
|
||||
actual_position: expression.position,
|
||||
expected_position: expected_type.position,
|
||||
}
|
||||
})?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -88,26 +88,16 @@ impl Context {
|
||||
.map(|identifier| Type::Parameter(identifier.clone()))
|
||||
.collect()
|
||||
});
|
||||
let variants = enum_definition
|
||||
.variants()
|
||||
.into_iter()
|
||||
.map(|(identifier, type_option)| {
|
||||
(
|
||||
identifier.clone(),
|
||||
type_option.clone().map(|r#type| r#type.node),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Type::Enum {
|
||||
name: enum_definition.name().clone(),
|
||||
type_arguments,
|
||||
variants,
|
||||
variants: enum_definition.variants().clone(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(Some(r#type.clone()));
|
||||
return Ok(Some(r#type));
|
||||
}
|
||||
|
||||
for module in BUILT_IN_MODULES {
|
||||
|
@ -522,7 +522,7 @@ mod tests {
|
||||
parse(
|
||||
&lex("
|
||||
enum FooBar {
|
||||
Foo,
|
||||
Foo(int),
|
||||
Bar,
|
||||
}
|
||||
")
|
||||
@ -534,7 +534,10 @@ mod tests {
|
||||
Identifier::new("FooBar"),
|
||||
None,
|
||||
vec![
|
||||
(Identifier::new("Foo"), None),
|
||||
(
|
||||
Identifier::new("Foo"),
|
||||
Some(Type::Integer.with_position((55, 58)))
|
||||
),
|
||||
(Identifier::new("Bar"), None)
|
||||
]
|
||||
))
|
||||
|
@ -24,10 +24,10 @@ fn simple_enum_type_check() {
|
||||
actual: Type::String,
|
||||
expected: Type::Integer,
|
||||
},
|
||||
actual_position: (0, 0).into(),
|
||||
expected_position: (0, 0).into()
|
||||
actual_position: (123, 127).into(),
|
||||
expected_position: (47, 50).into()
|
||||
},
|
||||
position: (0, 0).into()
|
||||
position: (105, 141).into()
|
||||
}])
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user