Add two new tests and refactor to pass them
This commit is contained in:
parent
3addb767fa
commit
a02cee0b9f
@ -245,7 +245,7 @@ impl FunctionLogic for JsonParse {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Type::Function {
|
Type::Function {
|
||||||
type_parameters: None,
|
type_parameters: Some(vec![Identifier::from("T")]),
|
||||||
value_parameters: Some(vec![(Identifier::from("input"), type_t.clone())]),
|
value_parameters: Some(vec![(Identifier::from("input"), type_t.clone())]),
|
||||||
return_type: Some(Box::new(type_t)),
|
return_type: Some(Box::new(type_t)),
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,8 @@ impl AbstractNode for FunctionCall {
|
|||||||
return_type: _,
|
return_type: _,
|
||||||
} = function_node_type
|
} = function_node_type
|
||||||
{
|
{
|
||||||
if let (Some(parameters), Some(arguments)) = (type_parameters, &self.type_arguments) {
|
match (type_parameters, &self.type_arguments) {
|
||||||
|
(Some(parameters), Some(arguments)) => {
|
||||||
if parameters.len() != arguments.len() {
|
if parameters.len() != arguments.len() {
|
||||||
return Err(ValidationError::WrongTypeArguments {
|
return Err(ValidationError::WrongTypeArguments {
|
||||||
arguments: arguments.clone(),
|
arguments: arguments.clone(),
|
||||||
@ -76,9 +77,27 @@ impl AbstractNode for FunctionCall {
|
|||||||
for (identifier, constructor) in parameters.into_iter().zip(arguments.iter()) {
|
for (identifier, constructor) in parameters.into_iter().zip(arguments.iter()) {
|
||||||
let r#type = constructor.construct(context)?;
|
let r#type = constructor.construct(context)?;
|
||||||
|
|
||||||
context.set_type(identifier, r#type, self.function_expression.position())?;
|
context.set_type(
|
||||||
|
identifier,
|
||||||
|
r#type,
|
||||||
|
self.function_expression.position(),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(Some(parameters), None) => {
|
||||||
|
return Err(ValidationError::WrongTypeArguments {
|
||||||
|
arguments: Vec::with_capacity(0),
|
||||||
|
parameters: parameters.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(None, Some(arguments)) => {
|
||||||
|
return Err(ValidationError::WrongTypeArguments {
|
||||||
|
arguments: arguments.clone(),
|
||||||
|
parameters: Vec::with_capacity(0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
(None, None) => {}
|
||||||
|
}
|
||||||
|
|
||||||
match (value_parameters, &self.value_arguments) {
|
match (value_parameters, &self.value_arguments) {
|
||||||
(Some(parameters), Some(arguments)) => {
|
(Some(parameters), Some(arguments)) => {
|
||||||
|
@ -43,8 +43,20 @@ pub enum Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
/// Returns a concrete type, either the type itself or the concrete type of a generic type.
|
||||||
|
pub fn concrete_type(&self) -> &Type {
|
||||||
|
match self {
|
||||||
|
Type::Generic {
|
||||||
|
concrete_type: Some(concrete_type),
|
||||||
|
..
|
||||||
|
} => concrete_type.concrete_type(),
|
||||||
|
_ => self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks that the type is compatible with another type.
|
||||||
pub fn check(&self, other: &Type) -> Result<(), TypeConflict> {
|
pub fn check(&self, other: &Type) -> Result<(), TypeConflict> {
|
||||||
match (self, other) {
|
match (self.concrete_type(), other.concrete_type()) {
|
||||||
(Type::Any, _)
|
(Type::Any, _)
|
||||||
| (_, Type::Any)
|
| (_, Type::Any)
|
||||||
| (Type::Boolean, Type::Boolean)
|
| (Type::Boolean, Type::Boolean)
|
||||||
|
@ -124,6 +124,10 @@ pub struct InterpreterError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InterpreterError {
|
impl InterpreterError {
|
||||||
|
pub fn new(source_id: Arc<str>, errors: Vec<DustError>) -> Self {
|
||||||
|
InterpreterError { source_id, errors }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn errors(&self) -> &Vec<DustError> {
|
pub fn errors(&self) -> &Vec<DustError> {
|
||||||
&self.errors
|
&self.errors
|
||||||
}
|
}
|
||||||
@ -477,6 +481,8 @@ impl InterpreterError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use abstract_tree::{AbstractNode, SourcePosition};
|
||||||
|
|
||||||
use self::standard_library::std_full_compiled;
|
use self::standard_library::std_full_compiled;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -486,6 +492,9 @@ mod tests {
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
for abstract_tree in std_full_compiled() {
|
for abstract_tree in std_full_compiled() {
|
||||||
|
abstract_tree
|
||||||
|
.define_and_validate(&context, true, SourcePosition(0, usize::MAX))
|
||||||
|
.unwrap();
|
||||||
abstract_tree.run(&context, true).unwrap();
|
abstract_tree.run(&context, true).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
use abstract_tree::{Expression, ValueNode, WithPos};
|
||||||
use dust_lang::*;
|
use dust_lang::*;
|
||||||
|
use error::{DustError, ValidationError};
|
||||||
|
use identifier::Identifier;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function_scope() {
|
fn function_scope() {
|
||||||
@ -109,3 +112,54 @@ fn recursion() {
|
|||||||
Ok(Some(Value::integer(13)))
|
Ok(Some(Value::integer(13)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_argument_error() {
|
||||||
|
assert_eq!(
|
||||||
|
interpret(
|
||||||
|
"test",
|
||||||
|
"
|
||||||
|
foobar = fn (a: int, b: int) -> int { a + b }
|
||||||
|
foobar(1)
|
||||||
|
"
|
||||||
|
),
|
||||||
|
Err(InterpreterError::new(
|
||||||
|
"test".into(),
|
||||||
|
vec![DustError::Validation {
|
||||||
|
error: ValidationError::WrongValueArguments {
|
||||||
|
parameters: vec![
|
||||||
|
(Identifier::new("a"), Type::Integer),
|
||||||
|
(Identifier::new("b"), Type::Integer),
|
||||||
|
],
|
||||||
|
arguments: vec![Expression::Value(
|
||||||
|
ValueNode::Integer(1).with_position((78, 79)),
|
||||||
|
)],
|
||||||
|
},
|
||||||
|
position: (71, 80).into()
|
||||||
|
}]
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_argument_error() {
|
||||||
|
assert_eq!(
|
||||||
|
interpret(
|
||||||
|
"test",
|
||||||
|
"
|
||||||
|
foobar = fn <T> (a: T) -> T { a }
|
||||||
|
foobar(1)
|
||||||
|
"
|
||||||
|
),
|
||||||
|
Err(InterpreterError::new(
|
||||||
|
"test".into(),
|
||||||
|
vec![DustError::Validation {
|
||||||
|
error: ValidationError::WrongTypeArguments {
|
||||||
|
parameters: vec![Identifier::new("T")],
|
||||||
|
arguments: vec![]
|
||||||
|
},
|
||||||
|
position: (59, 68).into()
|
||||||
|
}]
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user