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,
|
_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."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}")?;
|
||||||
|
|
||||||
|
if let Some(types) = types {
|
||||||
|
write!(f, "(")?;
|
||||||
|
|
||||||
for r#type in types {
|
for r#type in types {
|
||||||
write!(f, "{}", r#type)?
|
write!(f, "{}", r#type)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
|
@ -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>>,
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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)?;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user