1
0

Implement enums

This commit is contained in:
Jeff 2024-03-18 16:52:09 -04:00
parent 9f98617f6a
commit 087d926c3d
6 changed files with 41 additions and 32 deletions

View File

@ -43,13 +43,13 @@ impl AbstractTree for EnumDefinition {
Ok(Type::None) 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(()) Ok(())
} }
fn run(self, context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
context.set_enum_definition(self.name.clone(), self)?;
Ok(Action::None) Ok(Action::None)
} }
} }

View File

@ -6,7 +6,7 @@ use crate::{
error::{RuntimeError, TypeConflict, ValidationError}, error::{RuntimeError, TypeConflict, ValidationError},
}; };
use super::{AbstractTree, Action}; use super::{AbstractTree, Action, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Type { pub enum Type {
@ -16,7 +16,7 @@ pub enum Type {
Enum { Enum {
name: Identifier, name: Identifier,
type_arguments: Option<Vec<Type>>, type_arguments: Option<Vec<Type>>,
variants: Vec<(Identifier, Option<Type>)>, variants: Vec<(Identifier, Option<WithPosition<Type>>)>,
}, },
Float, Float,
Function { Function {

View File

@ -42,12 +42,7 @@ impl AbstractTree for ValueNode {
let r#type = match self { let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean, ValueNode::Boolean(_) => Type::Boolean,
ValueNode::EnumInstance { ValueNode::EnumInstance { name, .. } => {
name,
variant: _,
type_arguments,
expression: _,
} => {
if let Some(r#type) = context.get_type(name)? { if let Some(r#type) = context.get_type(name)? {
r#type r#type
} else { } else {
@ -130,13 +125,34 @@ impl AbstractTree for ValueNode {
} }
if let ValueNode::EnumInstance { if let ValueNode::EnumInstance {
name,
variant,
type_arguments,
expression, expression,
variant,
..
} = self } = self
{ {
let r#type = self.expected_type(context)?; 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(()) Ok(())

View File

@ -88,26 +88,16 @@ impl Context {
.map(|identifier| Type::Parameter(identifier.clone())) .map(|identifier| Type::Parameter(identifier.clone()))
.collect() .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 { Type::Enum {
name: enum_definition.name().clone(), name: enum_definition.name().clone(),
type_arguments, 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 { for module in BUILT_IN_MODULES {

View File

@ -522,7 +522,7 @@ mod tests {
parse( parse(
&lex(" &lex("
enum FooBar { enum FooBar {
Foo, Foo(int),
Bar, Bar,
} }
") ")
@ -534,7 +534,10 @@ mod tests {
Identifier::new("FooBar"), Identifier::new("FooBar"),
None, None,
vec![ vec![
(Identifier::new("Foo"), None), (
Identifier::new("Foo"),
Some(Type::Integer.with_position((55, 58)))
),
(Identifier::new("Bar"), None) (Identifier::new("Bar"), None)
] ]
)) ))

View File

@ -24,10 +24,10 @@ fn simple_enum_type_check() {
actual: Type::String, actual: Type::String,
expected: Type::Integer, expected: Type::Integer,
}, },
actual_position: (0, 0).into(), actual_position: (123, 127).into(),
expected_position: (0, 0).into() expected_position: (47, 50).into()
}, },
position: (0, 0).into() position: (105, 141).into()
}]) }])
) )
} }