Fix lots of parsing and type inferencing

This commit is contained in:
Jeff 2024-06-19 20:14:51 -04:00
parent e7e5d1c08d
commit 0b8880ae55
10 changed files with 349 additions and 113 deletions

View File

@ -33,7 +33,7 @@ impl Evaluate for As {
_manage_memory: bool, _manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
match self.constructor { match self.constructor {
TypeConstructor::Type(_) => {} TypeConstructor::Raw(_) => {}
_ => todo!("Create an error for this occurence."), _ => todo!("Create an error for this occurence."),
}; };

View File

@ -8,7 +8,8 @@ use crate::{
}; };
use super::{ use super::{
Evaluate, Evaluation, ExpectedType, Expression, Statement, Type, TypeConstructor, WithPosition, type_constructor::TypeInvokationConstructor, Evaluate, Evaluation, ExpectedType, Expression,
Statement, Type, TypeConstructor, WithPosition,
}; };
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -44,21 +45,66 @@ impl Assignment {
impl Evaluate for Assignment { impl Evaluate for Assignment {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
let statement_type = self.statement.expected_type(context)?; if let Some(TypeConstructor::Raw(WithPosition {
node: Type::None,
position,
})) = &self.constructor
{
return Err(ValidationError::CannotAssignToNone(position.clone()));
}
if let Type::None = statement_type { let relevant_statement = self.statement.last_child_statement();
let statement_type = relevant_statement.expected_type(context)?;
if let Type::None = &statement_type {
return Err(ValidationError::CannotAssignToNone( return Err(ValidationError::CannotAssignToNone(
self.statement.position(), self.statement.position(),
)); ));
} }
let statement = self if let Some(constructor) = &self.constructor {
.statement let r#type = constructor.clone().construct(&context)?;
.last_child_statement()
.unwrap_or(&self.statement); r#type
.check(&statement_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.statement.position(),
expected_position: Some(constructor.position()),
})?;
context.set_type(self.identifier.node.clone(), r#type.clone())?;
} else {
context.set_type(self.identifier.node.clone(), statement_type.clone())?;
}
self.statement.validate(context, manage_memory)?;
if let (
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
identifier,
type_arguments,
})),
Statement::Expression(Expression::Value(_)),
Type::Enum {
type_parameters, ..
},
) = (&self.constructor, relevant_statement, &statement_type)
{
if let (Some(parameters), Some(arguments)) = (type_parameters, type_arguments) {
if parameters.len() != arguments.len() {
return Err(ValidationError::FullTypeNotKnown {
identifier: identifier.node.clone(),
position: self.constructor.clone().unwrap().position(),
});
}
}
return Ok(());
}
if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) = if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) =
(&self.constructor, statement) (&self.constructor, relevant_statement)
{ {
let declared_type = constructor.clone().construct(context)?; let declared_type = constructor.clone().construct(context)?;
let function_type = function_call.node.function().expected_type(context)?; let function_type = function_call.node.function().expected_type(context)?;
@ -76,6 +122,8 @@ impl Evaluate for Assignment {
if let Some(parameter) = returned_parameter { if let Some(parameter) = returned_parameter {
context.set_type(parameter, declared_type)?; context.set_type(parameter, declared_type)?;
return Ok(());
} }
} }
} else { } else {
@ -84,24 +132,8 @@ impl Evaluate for Assignment {
position: function_call.position, position: function_call.position,
}); });
} }
} else if let Some(constructor) = &self.constructor {
let r#type = constructor.clone().construct(&context)?;
r#type
.check(&statement_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.statement.position(),
expected_position: Some(constructor.position()),
})?;
context.set_type(self.identifier.node.clone(), r#type.clone())?;
} else {
context.set_type(self.identifier.node.clone(), statement_type)?;
} }
self.statement.validate(context, manage_memory)?;
Ok(()) Ok(())
} }

View File

@ -40,11 +40,11 @@ impl Statement {
} }
} }
pub fn last_child_statement(&self) -> Option<&Self> { pub fn last_child_statement(&self) -> &Self {
match self { match self {
Statement::Block(block) => Some(block.node.last_statement()), Statement::Block(inner) => inner.node.last_statement(),
Statement::Loop(r#loop) => Some(r#loop.node.last_statement()), Statement::Loop(inner) => inner.node.last_statement(),
_ => None, statement => statement,
} }
} }
} }

View File

@ -16,7 +16,8 @@ pub enum Type {
Any, Any,
Boolean, Boolean,
Enum { Enum {
variants: Vec<(Identifier, Vec<Type>)>, type_parameters: Option<Vec<Type>>,
variants: Vec<(Identifier, Option<Vec<Type>>)>,
}, },
Float, Float,
Function { Function {
@ -229,14 +230,20 @@ impl Display for Type {
match self { match self {
Type::Any => write!(f, "any"), Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
Type::Enum { variants } => { Type::Enum { variants, .. } => {
write!(f, "enum {{")?; write!(f, "enum ")?;
write!(f, " {{")?;
for (identifier, types) in variants { for (identifier, types) in variants {
writeln!(f, "{identifier}(")?; writeln!(f, "{identifier}")?;
for r#type in types { if let Some(types) = types {
write!(f, "{}", r#type)? write!(f, "(")?;
for r#type in types {
write!(f, "{}", r#type)?;
}
} }
write!(f, ")")?; write!(f, ")")?;

View File

@ -10,10 +10,10 @@ use super::{SourcePosition, Type, WithPosition};
pub enum TypeConstructor { pub enum TypeConstructor {
Enum(WithPosition<EnumTypeConstructor>), Enum(WithPosition<EnumTypeConstructor>),
Function(WithPosition<FunctionTypeConstructor>), Function(WithPosition<FunctionTypeConstructor>),
Identifier(WithPosition<Identifier>), Invokation(TypeInvokationConstructor),
List(WithPosition<ListTypeConstructor>), List(WithPosition<ListTypeConstructor>),
ListOf(WithPosition<Box<TypeConstructor>>), ListOf(WithPosition<Box<TypeConstructor>>),
Type(WithPosition<Type>), Raw(WithPosition<Type>),
} }
impl TypeConstructor { impl TypeConstructor {
@ -21,17 +21,61 @@ impl TypeConstructor {
match self { match self {
TypeConstructor::Enum(WithPosition { position, .. }) => *position, TypeConstructor::Enum(WithPosition { position, .. }) => *position,
TypeConstructor::Function(WithPosition { position, .. }) => *position, TypeConstructor::Function(WithPosition { position, .. }) => *position,
TypeConstructor::Identifier(WithPosition { position, .. }) => *position, TypeConstructor::Invokation(TypeInvokationConstructor {
identifier,
type_arguments,
}) => {
if let Some(arguments) = type_arguments {
SourcePosition(
identifier.position.0,
arguments.last().unwrap().position().1,
)
} else {
SourcePosition(identifier.position.0, identifier.position.1)
}
}
TypeConstructor::List(WithPosition { position, .. }) => *position, TypeConstructor::List(WithPosition { position, .. }) => *position,
TypeConstructor::ListOf(WithPosition { position, .. }) => *position, TypeConstructor::ListOf(WithPosition { position, .. }) => *position,
TypeConstructor::Type(WithPosition { position, .. }) => *position, TypeConstructor::Raw(WithPosition { position, .. }) => *position,
} }
} }
pub fn construct(self, context: &Context) -> Result<Type, ValidationError> { pub fn construct(self, context: &Context) -> Result<Type, ValidationError> {
let r#type = match self { let r#type = match self {
TypeConstructor::Invokation(TypeInvokationConstructor { identifier, .. }) => {
let invoked_type = if let Some(r#type) = context.get_type(&identifier.node)? {
r#type
} else {
return Err(ValidationError::VariableNotFound {
identifier: identifier.node,
position: identifier.position,
});
};
if let Type::Enum {
type_parameters,
variants,
} = invoked_type
{
let mut mapped_variants = Vec::with_capacity(variants.len());
for (variant_name, content) in variants {
mapped_variants.push((variant_name.clone(), content.clone()));
}
Type::Enum {
type_parameters: type_parameters.clone(),
variants: mapped_variants,
}
} else {
invoked_type
}
}
TypeConstructor::Enum(enum_type_constructor) => { TypeConstructor::Enum(enum_type_constructor) => {
let EnumTypeConstructor { variants, .. } = enum_type_constructor.node; let EnumTypeConstructor {
type_parameters,
variants,
} = enum_type_constructor.node;
let mut type_variants = Vec::with_capacity(variants.len()); let mut type_variants = Vec::with_capacity(variants.len());
for (variant_name, constructors) in variants { for (variant_name, constructors) in variants {
@ -44,11 +88,22 @@ impl TypeConstructor {
types.push(r#type); types.push(r#type);
} }
type_variants.push((variant_name.node, types)); type_variants.push((variant_name.node, Some(types)));
} else {
type_variants.push((variant_name.node, None))
} }
} }
Type::Enum { Type::Enum {
type_parameters: type_parameters.map(|identifiers| {
identifiers
.into_iter()
.map(|identifier| Type::Generic {
identifier: identifier.node,
concrete_type: None,
})
.collect()
}),
variants: type_variants, variants: type_variants,
} }
} }
@ -81,21 +136,6 @@ impl TypeConstructor {
return_type, return_type,
} }
} }
TypeConstructor::Identifier(WithPosition {
node: identifier, ..
}) => {
if let Some(r#type) = context.get_type(&identifier)? {
Type::Generic {
identifier,
concrete_type: Some(Box::new(r#type)),
}
} else {
Type::Generic {
identifier,
concrete_type: None,
}
}
}
TypeConstructor::List(positioned_constructor) => { TypeConstructor::List(positioned_constructor) => {
let ListTypeConstructor { length, item_type } = positioned_constructor.node; let ListTypeConstructor { length, item_type } = positioned_constructor.node;
let constructed_type = item_type.construct(context)?; let constructed_type = item_type.construct(context)?;
@ -110,7 +150,7 @@ impl TypeConstructor {
Type::ListOf(Box::new(item_type)) Type::ListOf(Box::new(item_type))
} }
TypeConstructor::Type(r#type) => r#type.node, TypeConstructor::Raw(r#type) => r#type.node,
}; };
Ok(r#type) Ok(r#type)
@ -141,3 +181,9 @@ pub struct ListTypeConstructor {
pub length: usize, pub length: usize,
pub item_type: Box<TypeConstructor>, pub item_type: Box<TypeConstructor>,
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeInvokationConstructor {
pub identifier: WithPosition<Identifier>,
pub type_arguments: Option<Vec<TypeConstructor>>,
}

View File

@ -41,12 +41,26 @@ pub enum ValueNode {
impl Evaluate for ValueNode { impl Evaluate for ValueNode {
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
if let ValueNode::EnumInstance { type_name, .. } = self { if let ValueNode::EnumInstance {
if let Some(_) = context.get_type(&type_name.node)? { type_name, variant, ..
} = self
{
if let Some(Type::Enum { variants, .. }) = context.get_type(&type_name.node)? {
if variants
.iter()
.find(|(identifier, _)| identifier == &variant.node)
.is_none()
{
return Err(ValidationError::EnumVariantNotFound {
identifier: variant.node.clone(),
position: variant.position,
});
}
} else { } else {
return Err(ValidationError::EnumDefinitionNotFound( return Err(ValidationError::EnumDefinitionNotFound {
type_name.node.clone(), identifier: type_name.node.clone(),
)); position: Some(type_name.position),
});
} }
} }
@ -231,17 +245,28 @@ impl Evaluate for ValueNode {
return_type, return_type,
body, body,
} => { } => {
let type_parameters = let function_context = context.create_child();
type_parameters.map(|parameter_list| parameter_list.into_iter().collect());
let mut value_parameters = Vec::with_capacity(constructors.len()); let mut value_parameters = Vec::with_capacity(constructors.len());
for (identifier, constructor) in constructors { for (identifier, constructor) in constructors {
let r#type = constructor.construct(&context)?; let r#type = constructor.construct(&function_context)?;
value_parameters.push((identifier, r#type)); value_parameters.push((identifier, r#type));
} }
let return_type = return_type.construct(&context)?; if let Some(identifiers) = &type_parameters {
for identifier in identifiers {
function_context.set_type(
identifier.clone(),
Type::Generic {
identifier: identifier.clone(),
concrete_type: None,
},
)?;
}
}
let return_type = return_type.construct(&function_context)?;
Value::function(type_parameters, value_parameters, return_type, body.node) Value::function(type_parameters, value_parameters, return_type, body.node)
} }
@ -401,9 +426,10 @@ impl ExpectedType for ValueNode {
if let Some(r#type) = context.get_type(&type_name.node)? { if let Some(r#type) = context.get_type(&type_name.node)? {
r#type r#type
} else { } else {
return Err(ValidationError::EnumDefinitionNotFound( return Err(ValidationError::EnumDefinitionNotFound {
type_name.node.clone(), identifier: type_name.node.clone(),
)); position: Some(type_name.position),
});
} }
} }
ValueNode::Float(_) => Type::Float, ValueNode::Float(_) => Type::Float,

View File

@ -132,6 +132,10 @@ pub enum ValidationError {
position: SourcePosition, position: SourcePosition,
}, },
ExpectedValue(SourcePosition), ExpectedValue(SourcePosition),
FullTypeNotKnown {
identifier: Identifier,
position: SourcePosition,
},
InterpreterExpectedReturn(SourcePosition), InterpreterExpectedReturn(SourcePosition),
RwLockPoison(RwLockPoisonError), RwLockPoison(RwLockPoisonError),
TypeCheck { TypeCheck {
@ -160,7 +164,14 @@ pub enum ValidationError {
identifier: Identifier, identifier: Identifier,
position: SourcePosition, position: SourcePosition,
}, },
EnumDefinitionNotFound(Identifier), EnumDefinitionNotFound {
identifier: Identifier,
position: Option<SourcePosition>,
},
EnumVariantNotFound {
identifier: Identifier,
position: SourcePosition,
},
} }
impl From<RwLockPoisonError> for ValidationError { impl From<RwLockPoisonError> for ValidationError {

View File

@ -335,6 +335,17 @@ impl InterpreterError {
)), )),
); );
} }
ValidationError::FullTypeNotKnown {
identifier,
position,
} => builder.add_label(
Label::new((self.source_id.clone(), position.0..position.1)).with_message(
format!(
"The full type for {} must be known.",
identifier.fg(identifier_color)
),
),
),
ValidationError::RwLockPoison(_) => todo!(), ValidationError::RwLockPoison(_) => todo!(),
ValidationError::TypeCheck { ValidationError::TypeCheck {
conflict, conflict,
@ -425,7 +436,25 @@ impl InterpreterError {
) )
} }
ValidationError::ExpectedString { .. } => todo!(), ValidationError::ExpectedString { .. } => todo!(),
ValidationError::EnumDefinitionNotFound(_) => todo!(), ValidationError::EnumDefinitionNotFound {
identifier,
position,
} => {
let message = format!(
"The enum {} does not exist in this context.",
identifier.fg(identifier_color),
);
if let Some(position) = position {
builder.add_label(
Label::new((self.source_id.clone(), position.0..position.1))
.with_message(message),
)
} else {
builder = builder.with_message(message);
}
}
ValidationError::EnumVariantNotFound { .. } => todo!(),
} }
} }

View File

@ -9,6 +9,8 @@ use crate::{
lexer::{Control, Keyword, Operator, Token}, lexer::{Control, Keyword, Operator, Token},
}; };
use self::type_constructor::TypeInvokationConstructor;
pub type ParserInput<'src> = pub type ParserInput<'src> =
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>; SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
@ -79,7 +81,7 @@ pub fn parser<'src>(
just(Token::Keyword(Keyword::Range)).to(Type::Range), just(Token::Keyword(Keyword::Range)).to(Type::Range),
just(Token::Keyword(Keyword::Str)).to(Type::String), just(Token::Keyword(Keyword::Str)).to(Type::String),
)) ))
.map_with(|r#type, state| TypeConstructor::Type(r#type.with_position(state.span()))); .map_with(|r#type, state| TypeConstructor::Raw(r#type.with_position(state.span())));
let function_type = just(Token::Keyword(Keyword::Fn)) let function_type = just(Token::Keyword(Keyword::Fn))
.ignore_then( .ignore_then(
@ -147,10 +149,6 @@ pub fn parser<'src>(
TypeConstructor::ListOf(Box::new(item_type).with_position(state.span())) TypeConstructor::ListOf(Box::new(item_type).with_position(state.span()))
}); });
let identifier_type = positioned_identifier
.clone()
.map(|identifier| TypeConstructor::Identifier(identifier));
let enum_variant = positioned_identifier.clone().then( let enum_variant = positioned_identifier.clone().then(
type_constructor type_constructor
.clone() .clone()
@ -196,12 +194,34 @@ pub fn parser<'src>(
) )
}); });
let type_invokation = positioned_identifier
.clone()
.then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.at_least(1)
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
)
.or_not(),
)
.map(|(identifier, type_arguments)| {
TypeConstructor::Invokation(TypeInvokationConstructor {
identifier,
type_arguments,
})
});
choice(( choice((
type_invokation,
function_type, function_type,
list_type, list_type,
list_of_type, list_of_type,
primitive_type, primitive_type,
identifier_type,
enum_type, enum_type,
)) ))
}); });
@ -703,10 +723,10 @@ pub fn parser<'src>(
.repeated() .repeated()
.or_not() .or_not()
.ignore_then(choice(( .ignore_then(choice((
async_block,
if_else,
assignment, assignment,
expression_statement, expression_statement,
async_block,
if_else,
r#break, r#break,
block_statement, block_statement,
r#loop, r#loop,
@ -725,6 +745,53 @@ mod tests {
use super::*; use super::*;
#[test]
fn type_invokation() {
assert_eq!(
parse(&lex("x: Foo(int) = Foo::Bar(42)").unwrap()).unwrap()[0],
Statement::Assignment(
Assignment::new(
Identifier::new("x").with_position((0, 1)),
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
identifier: Identifier::new("Foo").with_position((3, 6)),
type_arguments: Some(vec![TypeConstructor::Raw(
Type::Integer.with_position((7, 10))
)]),
})),
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(
ValueNode::EnumInstance {
type_name: Identifier::new("Foo").with_position((14, 17)),
variant: Identifier::new("Bar").with_position((19, 22)),
content: Some(vec![Expression::Value(
ValueNode::Integer(42).with_position((23, 25))
)])
}
.with_position((14, 26))
))
)
.with_position((0, 26))
)
);
}
#[test]
fn enum_instance() {
assert_eq!(
parse(&lex("Foo::Bar(42)").unwrap()).unwrap()[0],
Statement::Expression(Expression::Value(
ValueNode::EnumInstance {
type_name: Identifier::new("Foo").with_position((0, 3)),
variant: Identifier::new("Bar").with_position((5, 8)),
content: Some(vec![Expression::Value(
ValueNode::Integer(42).with_position((9, 11))
)])
}
.with_position((0, 12))
))
);
}
#[test] #[test]
fn enum_type_empty() { fn enum_type_empty() {
assert_eq!( assert_eq!(
@ -762,15 +829,13 @@ mod tests {
( (
Identifier::new("X").with_position((21, 22)), Identifier::new("X").with_position((21, 22)),
Some(vec![ Some(vec![
TypeConstructor::Type(Type::String.with_position((23, 26))), TypeConstructor::Raw(Type::String.with_position((23, 26))),
TypeConstructor::Type( TypeConstructor::Raw(Type::Integer.with_position((28, 31)))
Type::Integer.with_position((28, 31))
)
]) ])
), ),
( (
Identifier::new("Y").with_position((34, 35)), Identifier::new("Y").with_position((34, 35)),
Some(vec![TypeConstructor::Type( Some(vec![TypeConstructor::Raw(
Type::Integer.with_position((36, 39)) Type::Integer.with_position((36, 39))
)]) )])
) )
@ -800,14 +865,22 @@ mod tests {
variants: vec![ variants: vec![
( (
Identifier::new("X").with_position((28, 29)), Identifier::new("X").with_position((28, 29)),
Some(vec![TypeConstructor::Identifier( Some(vec![TypeConstructor::Invokation(
Identifier::new("T").with_position((30, 31)) TypeInvokationConstructor {
identifier: Identifier::new("T")
.with_position((30, 31)),
type_arguments: None,
}
)]) )])
), ),
( (
Identifier::new("Y").with_position((34, 35)), Identifier::new("Y").with_position((34, 35)),
Some(vec![TypeConstructor::Identifier( Some(vec![TypeConstructor::Invokation(
Identifier::new("U").with_position((36, 37)) TypeInvokationConstructor {
identifier: Identifier::new("U")
.with_position((36, 37)),
type_arguments: None,
}
)]) )])
), ),
], ],
@ -894,7 +967,7 @@ mod tests {
Statement::TypeAssignment( Statement::TypeAssignment(
TypeAssignment::new( TypeAssignment::new(
Identifier::new("MyType").with_position((5, 11)), Identifier::new("MyType").with_position((5, 11)),
TypeConstructor::Type(Type::String.with_position((14, 17))) TypeConstructor::Raw(Type::String.with_position((14, 17)))
) )
.with_position((0, 17)) .with_position((0, 17))
) )
@ -908,7 +981,7 @@ mod tests {
Statement::Expression(Expression::As( Statement::Expression(Expression::As(
Box::new(As::new( Box::new(As::new(
Expression::Value(ValueNode::Integer(1).with_position((0, 1))), Expression::Value(ValueNode::Integer(1).with_position((0, 1))),
TypeConstructor::Type(Type::String.with_position((5, 8))) TypeConstructor::Raw(Type::String.with_position((5, 8)))
)) ))
.with_position((0, 8)) .with_position((0, 8))
)) ))
@ -1053,7 +1126,7 @@ mod tests {
Statement::Assignment( Statement::Assignment(
Assignment::new( Assignment::new(
Identifier::new("foobar").with_position((0, 6)), Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::Type(Type::Boolean.with_position((9, 13)))), Some(TypeConstructor::Raw(Type::Boolean.with_position((9, 13)))),
AssignmentOperator::Assign, AssignmentOperator::Assign,
Statement::Expression(Expression::Value( Statement::Expression(Expression::Value(
ValueNode::Boolean(true).with_position((16, 20)) ValueNode::Boolean(true).with_position((16, 20))
@ -1074,7 +1147,7 @@ mod tests {
Some(TypeConstructor::List( Some(TypeConstructor::List(
ListTypeConstructor { ListTypeConstructor {
length: 2, length: 2,
item_type: Box::new(TypeConstructor::Type( item_type: Box::new(TypeConstructor::Raw(
Type::Integer.with_position((9, 12)) Type::Integer.with_position((9, 12))
)) ))
} }
@ -1098,7 +1171,7 @@ mod tests {
Assignment::new( Assignment::new(
Identifier::new("foobar").with_position((0, 6)), Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::ListOf( Some(TypeConstructor::ListOf(
Box::new(TypeConstructor::Type(Type::Boolean.with_position((10, 14)))) Box::new(TypeConstructor::Raw(Type::Boolean.with_position((10, 14))))
.with_position((9, 15)) .with_position((9, 15))
)), )),
AssignmentOperator::Assign, AssignmentOperator::Assign,
@ -1126,11 +1199,14 @@ mod tests {
type_parameters: Some(vec![ type_parameters: Some(vec![
Identifier::new("T").with_position((15, 16)) Identifier::new("T").with_position((15, 16))
]), ]),
value_parameters: vec![TypeConstructor::Type( value_parameters: vec![TypeConstructor::Raw(
Type::Integer.with_position((19, 22)) Type::Integer.with_position((19, 22))
)], )],
return_type: Box::new(TypeConstructor::Identifier( return_type: Box::new(TypeConstructor::Invokation(
Identifier::new("T").with_position((27, 28)) TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((27, 28)),
type_arguments: None,
}
)), )),
} }
.with_position((11, 28)) .with_position((11, 28))
@ -1163,7 +1239,7 @@ mod tests {
Statement::Expression(Expression::FunctionCall( Statement::Expression(Expression::FunctionCall(
FunctionCall::new( FunctionCall::new(
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
Some(vec![TypeConstructor::Type( Some(vec![TypeConstructor::Raw(
Type::String.with_position((9, 12)) Type::String.with_position((9, 12))
)]), )]),
vec![Expression::Value( vec![Expression::Value(
@ -1193,7 +1269,7 @@ mod tests {
ValueNode::Function { ValueNode::Function {
type_parameters: None, type_parameters: None,
value_parameters: vec![], value_parameters: vec![],
return_type: TypeConstructor::Type(Type::Integer.with_position((9, 12))), return_type: TypeConstructor::Raw(Type::Integer.with_position((9, 12))),
body: Block::new(vec![Statement::Expression(Expression::Value( body: Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::Integer(0).with_position((15, 16)) ValueNode::Integer(0).with_position((15, 16))
))]) ))])
@ -1210,9 +1286,9 @@ mod tests {
type_parameters: None, type_parameters: None,
value_parameters: vec![( value_parameters: vec![(
Identifier::new("x"), Identifier::new("x"),
TypeConstructor::Type(Type::Integer.with_position((7, 10))) TypeConstructor::Raw(Type::Integer.with_position((7, 10)))
)], )],
return_type: TypeConstructor::Type(Type::Integer.with_position((15, 18))), return_type: TypeConstructor::Raw(Type::Integer.with_position((15, 18))),
body: Block::new(vec![Statement::Expression(Expression::Identifier( body: Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((21, 22)) Identifier::new("x").with_position((21, 22))
))]) ))])
@ -1233,20 +1309,23 @@ mod tests {
value_parameters: vec![ value_parameters: vec![
( (
Identifier::new("x"), Identifier::new("x"),
TypeConstructor::Identifier( TypeConstructor::Invokation(TypeInvokationConstructor {
Identifier::new("T").with_position((14, 15)) identifier: Identifier::new("T").with_position((14, 15)),
) type_arguments: None,
})
), ),
( (
Identifier::new("y"), Identifier::new("y"),
TypeConstructor::Identifier( TypeConstructor::Invokation(TypeInvokationConstructor {
Identifier::new("U").with_position((20, 21)) identifier: Identifier::new("U").with_position((20, 21)),
) type_arguments: None,
})
) )
], ],
return_type: TypeConstructor::Identifier( return_type: TypeConstructor::Invokation(TypeInvokationConstructor {
Identifier::new("T").with_position((26, 27)) identifier: Identifier::new("T").with_position((26, 27)),
), type_arguments: None,
}),
body: Block::new(vec![Statement::Expression(Expression::Identifier( body: Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((30, 31)) Identifier::new("x").with_position((30, 31))
))]) ))])
@ -1531,7 +1610,7 @@ mod tests {
Statement::Assignment( Statement::Assignment(
Assignment::new( Assignment::new(
Identifier::new("foobar").with_position((0, 6)), Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::Type(Type::Integer.with_position((8, 11)))), Some(TypeConstructor::Raw(Type::Integer.with_position((8, 11)))),
AssignmentOperator::Assign, AssignmentOperator::Assign,
Statement::Expression(Expression::Value( Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((14, 15)) ValueNode::Integer(1).with_position((14, 15))

View File

@ -564,7 +564,10 @@ impl ValueInner {
if let Some(r#type) = context.get_type(type_name)? { if let Some(r#type) = context.get_type(type_name)? {
r#type r#type
} else { } else {
return Err(ValidationError::EnumDefinitionNotFound(type_name.clone())); return Err(ValidationError::EnumDefinitionNotFound {
identifier: type_name.clone(),
position: None,
});
} }
} }
ValueInner::Float(_) => Type::Float, ValueInner::Float(_) => Type::Float,
@ -720,11 +723,14 @@ impl Function {
pub fn call( pub fn call(
self, self,
arguments: Vec<Value>, value_arguments: Vec<Value>,
context: &mut Context, context: &mut Context,
clear_variables: bool, clear_variables: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
for ((identifier, _), value) in self.value_parameters.into_iter().zip(arguments.into_iter()) for ((identifier, _), value) in self
.value_parameters
.into_iter()
.zip(value_arguments.into_iter())
{ {
context.set_value(identifier.clone(), value)?; context.set_value(identifier.clone(), value)?;
} }