Fix lots of parsing and type inferencing
This commit is contained in:
parent
e7e5d1c08d
commit
0b8880ae55
@ -33,7 +33,7 @@ impl Evaluate for As {
|
||||
_manage_memory: bool,
|
||||
) -> Result<(), ValidationError> {
|
||||
match self.constructor {
|
||||
TypeConstructor::Type(_) => {}
|
||||
TypeConstructor::Raw(_) => {}
|
||||
_ => todo!("Create an error for this occurence."),
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,8 @@ use crate::{
|
||||
};
|
||||
|
||||
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)]
|
||||
@ -44,21 +45,66 @@ impl Assignment {
|
||||
|
||||
impl Evaluate for Assignment {
|
||||
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(
|
||||
self.statement.position(),
|
||||
));
|
||||
}
|
||||
|
||||
let statement = self
|
||||
.statement
|
||||
.last_child_statement()
|
||||
.unwrap_or(&self.statement);
|
||||
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.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))) =
|
||||
(&self.constructor, statement)
|
||||
(&self.constructor, relevant_statement)
|
||||
{
|
||||
let declared_type = constructor.clone().construct(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 {
|
||||
context.set_type(parameter, declared_type)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -84,24 +132,8 @@ impl Evaluate for Assignment {
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -40,11 +40,11 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn last_child_statement(&self) -> Option<&Self> {
|
||||
pub fn last_child_statement(&self) -> &Self {
|
||||
match self {
|
||||
Statement::Block(block) => Some(block.node.last_statement()),
|
||||
Statement::Loop(r#loop) => Some(r#loop.node.last_statement()),
|
||||
_ => None,
|
||||
Statement::Block(inner) => inner.node.last_statement(),
|
||||
Statement::Loop(inner) => inner.node.last_statement(),
|
||||
statement => statement,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ pub enum Type {
|
||||
Any,
|
||||
Boolean,
|
||||
Enum {
|
||||
variants: Vec<(Identifier, Vec<Type>)>,
|
||||
type_parameters: Option<Vec<Type>>,
|
||||
variants: Vec<(Identifier, Option<Vec<Type>>)>,
|
||||
},
|
||||
Float,
|
||||
Function {
|
||||
@ -229,14 +230,20 @@ impl Display for Type {
|
||||
match self {
|
||||
Type::Any => write!(f, "any"),
|
||||
Type::Boolean => write!(f, "bool"),
|
||||
Type::Enum { variants } => {
|
||||
write!(f, "enum {{")?;
|
||||
Type::Enum { variants, .. } => {
|
||||
write!(f, "enum ")?;
|
||||
|
||||
write!(f, " {{")?;
|
||||
|
||||
for (identifier, types) in variants {
|
||||
writeln!(f, "{identifier}(")?;
|
||||
writeln!(f, "{identifier}")?;
|
||||
|
||||
if let Some(types) = types {
|
||||
write!(f, "(")?;
|
||||
|
||||
for r#type in types {
|
||||
write!(f, "{}", r#type)?
|
||||
write!(f, "{}", r#type)?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, ")")?;
|
||||
|
@ -10,10 +10,10 @@ use super::{SourcePosition, Type, WithPosition};
|
||||
pub enum TypeConstructor {
|
||||
Enum(WithPosition<EnumTypeConstructor>),
|
||||
Function(WithPosition<FunctionTypeConstructor>),
|
||||
Identifier(WithPosition<Identifier>),
|
||||
Invokation(TypeInvokationConstructor),
|
||||
List(WithPosition<ListTypeConstructor>),
|
||||
ListOf(WithPosition<Box<TypeConstructor>>),
|
||||
Type(WithPosition<Type>),
|
||||
Raw(WithPosition<Type>),
|
||||
}
|
||||
|
||||
impl TypeConstructor {
|
||||
@ -21,17 +21,61 @@ impl TypeConstructor {
|
||||
match self {
|
||||
TypeConstructor::Enum(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::ListOf(WithPosition { position, .. }) => *position,
|
||||
TypeConstructor::Type(WithPosition { position, .. }) => *position,
|
||||
TypeConstructor::Raw(WithPosition { position, .. }) => *position,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn construct(self, context: &Context) -> Result<Type, ValidationError> {
|
||||
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) => {
|
||||
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());
|
||||
|
||||
for (variant_name, constructors) in variants {
|
||||
@ -44,11 +88,22 @@ impl TypeConstructor {
|
||||
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_parameters: type_parameters.map(|identifiers| {
|
||||
identifiers
|
||||
.into_iter()
|
||||
.map(|identifier| Type::Generic {
|
||||
identifier: identifier.node,
|
||||
concrete_type: None,
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
variants: type_variants,
|
||||
}
|
||||
}
|
||||
@ -81,21 +136,6 @@ impl TypeConstructor {
|
||||
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) => {
|
||||
let ListTypeConstructor { length, item_type } = positioned_constructor.node;
|
||||
let constructed_type = item_type.construct(context)?;
|
||||
@ -110,7 +150,7 @@ impl TypeConstructor {
|
||||
|
||||
Type::ListOf(Box::new(item_type))
|
||||
}
|
||||
TypeConstructor::Type(r#type) => r#type.node,
|
||||
TypeConstructor::Raw(r#type) => r#type.node,
|
||||
};
|
||||
|
||||
Ok(r#type)
|
||||
@ -141,3 +181,9 @@ pub struct ListTypeConstructor {
|
||||
pub length: usize,
|
||||
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>>,
|
||||
}
|
||||
|
@ -41,12 +41,26 @@ pub enum ValueNode {
|
||||
|
||||
impl Evaluate for ValueNode {
|
||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||
if let ValueNode::EnumInstance { type_name, .. } = self {
|
||||
if let Some(_) = context.get_type(&type_name.node)? {
|
||||
if let ValueNode::EnumInstance {
|
||||
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 {
|
||||
return Err(ValidationError::EnumDefinitionNotFound(
|
||||
type_name.node.clone(),
|
||||
));
|
||||
return Err(ValidationError::EnumDefinitionNotFound {
|
||||
identifier: type_name.node.clone(),
|
||||
position: Some(type_name.position),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,17 +245,28 @@ impl Evaluate for ValueNode {
|
||||
return_type,
|
||||
body,
|
||||
} => {
|
||||
let type_parameters =
|
||||
type_parameters.map(|parameter_list| parameter_list.into_iter().collect());
|
||||
let function_context = context.create_child();
|
||||
let mut value_parameters = Vec::with_capacity(constructors.len());
|
||||
|
||||
for (identifier, constructor) in constructors {
|
||||
let r#type = constructor.construct(&context)?;
|
||||
let r#type = constructor.construct(&function_context)?;
|
||||
|
||||
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)
|
||||
}
|
||||
@ -401,9 +426,10 @@ impl ExpectedType for ValueNode {
|
||||
if let Some(r#type) = context.get_type(&type_name.node)? {
|
||||
r#type
|
||||
} else {
|
||||
return Err(ValidationError::EnumDefinitionNotFound(
|
||||
type_name.node.clone(),
|
||||
));
|
||||
return Err(ValidationError::EnumDefinitionNotFound {
|
||||
identifier: type_name.node.clone(),
|
||||
position: Some(type_name.position),
|
||||
});
|
||||
}
|
||||
}
|
||||
ValueNode::Float(_) => Type::Float,
|
||||
|
@ -132,6 +132,10 @@ pub enum ValidationError {
|
||||
position: SourcePosition,
|
||||
},
|
||||
ExpectedValue(SourcePosition),
|
||||
FullTypeNotKnown {
|
||||
identifier: Identifier,
|
||||
position: SourcePosition,
|
||||
},
|
||||
InterpreterExpectedReturn(SourcePosition),
|
||||
RwLockPoison(RwLockPoisonError),
|
||||
TypeCheck {
|
||||
@ -160,7 +164,14 @@ pub enum ValidationError {
|
||||
identifier: Identifier,
|
||||
position: SourcePosition,
|
||||
},
|
||||
EnumDefinitionNotFound(Identifier),
|
||||
EnumDefinitionNotFound {
|
||||
identifier: Identifier,
|
||||
position: Option<SourcePosition>,
|
||||
},
|
||||
EnumVariantNotFound {
|
||||
identifier: Identifier,
|
||||
position: SourcePosition,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<RwLockPoisonError> for ValidationError {
|
||||
|
@ -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::TypeCheck {
|
||||
conflict,
|
||||
@ -425,7 +436,25 @@ impl InterpreterError {
|
||||
)
|
||||
}
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ use crate::{
|
||||
lexer::{Control, Keyword, Operator, Token},
|
||||
};
|
||||
|
||||
use self::type_constructor::TypeInvokationConstructor;
|
||||
|
||||
pub type ParserInput<'src> =
|
||||
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::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))
|
||||
.ignore_then(
|
||||
@ -147,10 +149,6 @@ pub fn parser<'src>(
|
||||
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(
|
||||
type_constructor
|
||||
.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((
|
||||
type_invokation,
|
||||
function_type,
|
||||
list_type,
|
||||
list_of_type,
|
||||
primitive_type,
|
||||
identifier_type,
|
||||
enum_type,
|
||||
))
|
||||
});
|
||||
@ -703,10 +723,10 @@ pub fn parser<'src>(
|
||||
.repeated()
|
||||
.or_not()
|
||||
.ignore_then(choice((
|
||||
async_block,
|
||||
if_else,
|
||||
assignment,
|
||||
expression_statement,
|
||||
async_block,
|
||||
if_else,
|
||||
r#break,
|
||||
block_statement,
|
||||
r#loop,
|
||||
@ -725,6 +745,53 @@ mod tests {
|
||||
|
||||
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]
|
||||
fn enum_type_empty() {
|
||||
assert_eq!(
|
||||
@ -762,15 +829,13 @@ mod tests {
|
||||
(
|
||||
Identifier::new("X").with_position((21, 22)),
|
||||
Some(vec![
|
||||
TypeConstructor::Type(Type::String.with_position((23, 26))),
|
||||
TypeConstructor::Type(
|
||||
Type::Integer.with_position((28, 31))
|
||||
)
|
||||
TypeConstructor::Raw(Type::String.with_position((23, 26))),
|
||||
TypeConstructor::Raw(Type::Integer.with_position((28, 31)))
|
||||
])
|
||||
),
|
||||
(
|
||||
Identifier::new("Y").with_position((34, 35)),
|
||||
Some(vec![TypeConstructor::Type(
|
||||
Some(vec![TypeConstructor::Raw(
|
||||
Type::Integer.with_position((36, 39))
|
||||
)])
|
||||
)
|
||||
@ -800,14 +865,22 @@ mod tests {
|
||||
variants: vec![
|
||||
(
|
||||
Identifier::new("X").with_position((28, 29)),
|
||||
Some(vec![TypeConstructor::Identifier(
|
||||
Identifier::new("T").with_position((30, 31))
|
||||
Some(vec![TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T")
|
||||
.with_position((30, 31)),
|
||||
type_arguments: None,
|
||||
}
|
||||
)])
|
||||
),
|
||||
(
|
||||
Identifier::new("Y").with_position((34, 35)),
|
||||
Some(vec![TypeConstructor::Identifier(
|
||||
Identifier::new("U").with_position((36, 37))
|
||||
Some(vec![TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("U")
|
||||
.with_position((36, 37)),
|
||||
type_arguments: None,
|
||||
}
|
||||
)])
|
||||
),
|
||||
],
|
||||
@ -894,7 +967,7 @@ mod tests {
|
||||
Statement::TypeAssignment(
|
||||
TypeAssignment::new(
|
||||
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))
|
||||
)
|
||||
@ -908,7 +981,7 @@ mod tests {
|
||||
Statement::Expression(Expression::As(
|
||||
Box::new(As::new(
|
||||
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))
|
||||
))
|
||||
@ -1053,7 +1126,7 @@ mod tests {
|
||||
Statement::Assignment(
|
||||
Assignment::new(
|
||||
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,
|
||||
Statement::Expression(Expression::Value(
|
||||
ValueNode::Boolean(true).with_position((16, 20))
|
||||
@ -1074,7 +1147,7 @@ mod tests {
|
||||
Some(TypeConstructor::List(
|
||||
ListTypeConstructor {
|
||||
length: 2,
|
||||
item_type: Box::new(TypeConstructor::Type(
|
||||
item_type: Box::new(TypeConstructor::Raw(
|
||||
Type::Integer.with_position((9, 12))
|
||||
))
|
||||
}
|
||||
@ -1098,7 +1171,7 @@ mod tests {
|
||||
Assignment::new(
|
||||
Identifier::new("foobar").with_position((0, 6)),
|
||||
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))
|
||||
)),
|
||||
AssignmentOperator::Assign,
|
||||
@ -1126,11 +1199,14 @@ mod tests {
|
||||
type_parameters: Some(vec![
|
||||
Identifier::new("T").with_position((15, 16))
|
||||
]),
|
||||
value_parameters: vec![TypeConstructor::Type(
|
||||
value_parameters: vec![TypeConstructor::Raw(
|
||||
Type::Integer.with_position((19, 22))
|
||||
)],
|
||||
return_type: Box::new(TypeConstructor::Identifier(
|
||||
Identifier::new("T").with_position((27, 28))
|
||||
return_type: Box::new(TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((27, 28)),
|
||||
type_arguments: None,
|
||||
}
|
||||
)),
|
||||
}
|
||||
.with_position((11, 28))
|
||||
@ -1163,7 +1239,7 @@ mod tests {
|
||||
Statement::Expression(Expression::FunctionCall(
|
||||
FunctionCall::new(
|
||||
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
|
||||
Some(vec![TypeConstructor::Type(
|
||||
Some(vec![TypeConstructor::Raw(
|
||||
Type::String.with_position((9, 12))
|
||||
)]),
|
||||
vec![Expression::Value(
|
||||
@ -1193,7 +1269,7 @@ mod tests {
|
||||
ValueNode::Function {
|
||||
type_parameters: None,
|
||||
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(
|
||||
ValueNode::Integer(0).with_position((15, 16))
|
||||
))])
|
||||
@ -1210,9 +1286,9 @@ mod tests {
|
||||
type_parameters: None,
|
||||
value_parameters: vec![(
|
||||
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(
|
||||
Identifier::new("x").with_position((21, 22))
|
||||
))])
|
||||
@ -1233,20 +1309,23 @@ mod tests {
|
||||
value_parameters: vec![
|
||||
(
|
||||
Identifier::new("x"),
|
||||
TypeConstructor::Identifier(
|
||||
Identifier::new("T").with_position((14, 15))
|
||||
)
|
||||
TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((14, 15)),
|
||||
type_arguments: None,
|
||||
})
|
||||
),
|
||||
(
|
||||
Identifier::new("y"),
|
||||
TypeConstructor::Identifier(
|
||||
Identifier::new("U").with_position((20, 21))
|
||||
)
|
||||
TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||
identifier: Identifier::new("U").with_position((20, 21)),
|
||||
type_arguments: None,
|
||||
})
|
||||
)
|
||||
],
|
||||
return_type: TypeConstructor::Identifier(
|
||||
Identifier::new("T").with_position((26, 27))
|
||||
),
|
||||
return_type: TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((26, 27)),
|
||||
type_arguments: None,
|
||||
}),
|
||||
body: Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||
Identifier::new("x").with_position((30, 31))
|
||||
))])
|
||||
@ -1531,7 +1610,7 @@ mod tests {
|
||||
Statement::Assignment(
|
||||
Assignment::new(
|
||||
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,
|
||||
Statement::Expression(Expression::Value(
|
||||
ValueNode::Integer(1).with_position((14, 15))
|
||||
|
@ -564,7 +564,10 @@ impl ValueInner {
|
||||
if let Some(r#type) = context.get_type(type_name)? {
|
||||
r#type
|
||||
} else {
|
||||
return Err(ValidationError::EnumDefinitionNotFound(type_name.clone()));
|
||||
return Err(ValidationError::EnumDefinitionNotFound {
|
||||
identifier: type_name.clone(),
|
||||
position: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
ValueInner::Float(_) => Type::Float,
|
||||
@ -720,11 +723,14 @@ impl Function {
|
||||
|
||||
pub fn call(
|
||||
self,
|
||||
arguments: Vec<Value>,
|
||||
value_arguments: Vec<Value>,
|
||||
context: &mut Context,
|
||||
clear_variables: bool,
|
||||
) -> 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)?;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user