Implement structure parsing
This commit is contained in:
parent
16d443d8a6
commit
bcc89f2c7d
@ -65,7 +65,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedFunction {
|
ValidationError::ExpectedFunction {
|
||||||
actual: value.r#type(),
|
actual: value.r#type(context)?,
|
||||||
position: self.function.position,
|
position: self.function.position,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -63,8 +63,8 @@ impl AbstractTree for IfElse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let action = self.if_expression.node.run(_context)?;
|
let action = self.if_expression.node.run(context)?;
|
||||||
let value = if let Action::Return(value) = action {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -75,16 +75,16 @@ impl AbstractTree for IfElse {
|
|||||||
|
|
||||||
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
|
if let ValueInner::Boolean(if_boolean) = value.inner().as_ref() {
|
||||||
if *if_boolean {
|
if *if_boolean {
|
||||||
self.if_block.run(_context)
|
self.if_block.run(context)
|
||||||
} else if let Some(else_statement) = self.else_block {
|
} else if let Some(else_statement) = self.else_block {
|
||||||
else_statement.run(_context)
|
else_statement.run(context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedBoolean {
|
ValidationError::ExpectedBoolean {
|
||||||
actual: value.r#type(),
|
actual: value.r#type(context)?,
|
||||||
position: self.if_expression.position,
|
position: self.if_expression.position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -68,8 +68,8 @@ impl AbstractTree for ListIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let left_action = self.left.node.run(_context)?;
|
let left_action = self.left.node.run(context)?;
|
||||||
let left_value = if let Action::Return(value) = left_action {
|
let left_value = if let Action::Return(value) = left_action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -77,7 +77,7 @@ impl AbstractTree for ListIndex {
|
|||||||
ValidationError::InterpreterExpectedReturn(self.left.position),
|
ValidationError::InterpreterExpectedReturn(self.left.position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let right_action = self.right.node.run(_context)?;
|
let right_action = self.right.node.run(context)?;
|
||||||
let right_value = if let Action::Return(value) = right_action {
|
let right_value = if let Action::Return(value) = right_action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -97,9 +97,9 @@ impl AbstractTree for ListIndex {
|
|||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::CannotIndexWith {
|
ValidationError::CannotIndexWith {
|
||||||
collection_type: left_value.r#type(),
|
collection_type: left_value.r#type(context)?,
|
||||||
collection_position: self.left.position,
|
collection_position: self.left.position,
|
||||||
index_type: right_value.r#type(),
|
index_type: right_value.r#type(context)?,
|
||||||
index_position: self.right.position,
|
index_position: self.right.position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -83,10 +83,10 @@ impl AbstractTree for Logic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let run_and_expect_value =
|
let run_and_expect_value =
|
||||||
|expression: WithPosition<Expression>| -> Result<Value, RuntimeError> {
|
|expression: WithPosition<Expression>| -> Result<Value, RuntimeError> {
|
||||||
let action = expression.node.run(_context)?;
|
let action = expression.node.run(context)?;
|
||||||
let value = if let Action::Return(value) = action {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -100,7 +100,7 @@ impl AbstractTree for Logic {
|
|||||||
|
|
||||||
let run_and_expect_boolean =
|
let run_and_expect_boolean =
|
||||||
|expression: WithPosition<Expression>| -> Result<bool, RuntimeError> {
|
|expression: WithPosition<Expression>| -> Result<bool, RuntimeError> {
|
||||||
let action = expression.node.run(_context)?;
|
let action = expression.node.run(context)?;
|
||||||
let value = if let Action::Return(value) = action {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -114,7 +114,7 @@ impl AbstractTree for Logic {
|
|||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedBoolean {
|
ValidationError::ExpectedBoolean {
|
||||||
actual: value.r#type(),
|
actual: value.r#type(context)?,
|
||||||
position: expression.position,
|
position: expression.position,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
@ -19,15 +19,15 @@ impl MapIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for MapIndex {
|
impl AbstractTree for MapIndex {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||||
let left_type = self.left.node.expected_type(_context)?;
|
let left_type = self.left.node.expected_type(context)?;
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
Expression::Identifier(collection_identifier),
|
Expression::Identifier(collection_identifier),
|
||||||
Expression::Identifier(index_identifier),
|
Expression::Identifier(index_identifier),
|
||||||
) = (&self.left.node, &self.right.node)
|
) = (&self.left.node, &self.right.node)
|
||||||
{
|
{
|
||||||
let collection = if let Some(collection) = _context.get_value(collection_identifier)? {
|
let collection = if let Some(collection) = context.get_value(collection_identifier)? {
|
||||||
collection
|
collection
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::VariableNotFound(
|
return Err(ValidationError::VariableNotFound(
|
||||||
@ -37,7 +37,7 @@ impl AbstractTree for MapIndex {
|
|||||||
|
|
||||||
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
||||||
return if let Some(value) = map.get(index_identifier) {
|
return if let Some(value) = map.get(index_identifier) {
|
||||||
Ok(value.r#type())
|
Ok(value.r#type(context)?)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::PropertyNotFound {
|
Err(ValidationError::PropertyNotFound {
|
||||||
identifier: index_identifier.clone(),
|
identifier: index_identifier.clone(),
|
||||||
@ -56,9 +56,9 @@ impl AbstractTree for MapIndex {
|
|||||||
.find_map(|(property, type_option, expression)| {
|
.find_map(|(property, type_option, expression)| {
|
||||||
if property == identifier {
|
if property == identifier {
|
||||||
if let Some(r#type) = type_option {
|
if let Some(r#type) = type_option {
|
||||||
Some(r#type.node.expected_type(_context))
|
Some(r#type.node.expected_type(context))
|
||||||
} else {
|
} else {
|
||||||
Some(expression.node.expected_type(_context))
|
Some(expression.node.expected_type(context))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -74,7 +74,7 @@ impl AbstractTree for MapIndex {
|
|||||||
Err(ValidationError::CannotIndexWith {
|
Err(ValidationError::CannotIndexWith {
|
||||||
collection_type: left_type,
|
collection_type: left_type,
|
||||||
collection_position: self.left.position,
|
collection_position: self.left.position,
|
||||||
index_type: self.right.node.expected_type(_context)?,
|
index_type: self.right.node.expected_type(context)?,
|
||||||
index_position: self.right.position,
|
index_position: self.right.position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -100,8 +100,8 @@ impl AbstractTree for MapIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let action = self.left.node.run(_context)?;
|
let action = self.left.node.run(context)?;
|
||||||
let collection = if let Action::Return(value) = action {
|
let collection = if let Action::Return(value) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -122,9 +122,9 @@ impl AbstractTree for MapIndex {
|
|||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::CannotIndexWith {
|
ValidationError::CannotIndexWith {
|
||||||
collection_type: collection.r#type(),
|
collection_type: collection.r#type(context)?,
|
||||||
collection_position: self.left.position,
|
collection_position: self.left.position,
|
||||||
index_type: self.right.node.expected_type(_context)?,
|
index_type: self.right.node.expected_type(context)?,
|
||||||
index_position: self.right.position,
|
index_position: self.right.position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -25,7 +25,7 @@ pub enum ValueNode {
|
|||||||
String(String),
|
String(String),
|
||||||
Structure {
|
Structure {
|
||||||
name: Identifier,
|
name: Identifier,
|
||||||
fields: Vec<(Identifier, Type)>,
|
fields: Vec<(Identifier, WithPosition<Expression>)>,
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
||||||
@ -244,14 +244,6 @@ impl Ord for ValueNode {
|
|||||||
fields: right_fields,
|
fields: right_fields,
|
||||||
},
|
},
|
||||||
) => todo!(),
|
) => todo!(),
|
||||||
(
|
|
||||||
Structure { name, fields },
|
|
||||||
Function {
|
|
||||||
parameters,
|
|
||||||
return_type,
|
|
||||||
body,
|
|
||||||
},
|
|
||||||
) => todo!(),
|
|
||||||
(Structure { name, fields }, _) => todo!(),
|
(Structure { name, fields }, _) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Identifier, Type},
|
abstract_tree::{Identifier, Type},
|
||||||
error::RwLockPoisonError,
|
error::{RwLockPoisonError, ValidationError},
|
||||||
value::{BUILT_IN_FUNCTIONS, BUILT_IN_MODULES},
|
value::{BUILT_IN_FUNCTIONS, BUILT_IN_MODULES},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
@ -72,11 +72,11 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockPoisonError> {
|
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
|
||||||
if let Some(value_data) = self.inner.read()?.get(identifier) {
|
if let Some(value_data) = self.inner.read()?.get(identifier) {
|
||||||
let r#type = match value_data {
|
let r#type = match value_data {
|
||||||
ValueData::Type(r#type) => r#type.clone(),
|
ValueData::Type(r#type) => r#type.clone(),
|
||||||
ValueData::Value(value) => value.r#type(),
|
ValueData::Value(value) => value.r#type(self)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(Some(r#type.clone()));
|
return Ok(Some(r#type.clone()));
|
||||||
|
@ -291,6 +291,12 @@ impl From<RwLockPoisonError> for ValidationError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<PoisonError<T>> for ValidationError {
|
||||||
|
fn from(_: PoisonError<T>) -> Self {
|
||||||
|
ValidationError::RwLockPoison(RwLockPoisonError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct RwLockPoisonError;
|
pub struct RwLockPoisonError;
|
||||||
|
|
||||||
|
@ -336,7 +336,30 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let structure_field = identifier
|
||||||
|
.clone()
|
||||||
|
.then_ignore(just(Token::Operator(Operator::Assign)))
|
||||||
|
.then(positioned_expression.clone());
|
||||||
|
|
||||||
|
let structure_instance = identifier
|
||||||
|
.clone()
|
||||||
|
.then(
|
||||||
|
structure_field
|
||||||
|
.separated_by(just(Token::Control(Control::Comma)))
|
||||||
|
.allow_trailing()
|
||||||
|
.collect()
|
||||||
|
.delimited_by(
|
||||||
|
just(Token::Control(Control::CurlyOpen)),
|
||||||
|
just(Token::Control(Control::CurlyClose)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.map_with(|(name, fields), state| {
|
||||||
|
Expression::Value(ValueNode::Structure { name, fields })
|
||||||
|
.with_position(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
|
structure_instance,
|
||||||
range,
|
range,
|
||||||
logic_math_indexes_and_function_calls,
|
logic_math_indexes_and_function_calls,
|
||||||
function,
|
function,
|
||||||
@ -417,12 +440,12 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
.with_position(state.span())
|
.with_position(state.span())
|
||||||
});
|
});
|
||||||
|
|
||||||
let structure_field = identifier.clone().then(type_specification.clone());
|
let structure_field_definition = identifier.clone().then(type_specification.clone());
|
||||||
|
|
||||||
let structure_definition = just(Token::Keyword("struct"))
|
let structure_definition = just(Token::Keyword("struct"))
|
||||||
.ignore_then(identifier.clone())
|
.ignore_then(identifier.clone())
|
||||||
.then(
|
.then(
|
||||||
structure_field
|
structure_field_definition
|
||||||
.separated_by(just(Token::Control(Control::Comma)))
|
.separated_by(just(Token::Control(Control::Comma)))
|
||||||
.allow_trailing()
|
.allow_trailing()
|
||||||
.collect()
|
.collect()
|
||||||
@ -458,6 +481,37 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn structure_instance() {
|
||||||
|
assert_eq!(
|
||||||
|
parse(
|
||||||
|
&lex("
|
||||||
|
Foo {
|
||||||
|
bar = 42,
|
||||||
|
baz = 'hiya',
|
||||||
|
}
|
||||||
|
")
|
||||||
|
.unwrap()
|
||||||
|
)
|
||||||
|
.unwrap()[0]
|
||||||
|
.node,
|
||||||
|
Statement::Expression(Expression::Value(ValueNode::Structure {
|
||||||
|
name: Identifier::new("Foo"),
|
||||||
|
fields: vec![
|
||||||
|
(
|
||||||
|
Identifier::new("bar"),
|
||||||
|
Expression::Value(ValueNode::Integer(42)).with_position((57, 59))
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Identifier::new("baz"),
|
||||||
|
Expression::Value(ValueNode::String("hiya".to_string()))
|
||||||
|
.with_position((91, 97))
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn structure_definition() {
|
fn structure_definition() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
66
src/value.rs
66
src/value.rs
@ -15,7 +15,7 @@ use stanza::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractTree, Action, Block, Identifier, Type, WithPosition},
|
abstract_tree::{AbstractTree, Action, Block, Expression, Identifier, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
@ -74,8 +74,8 @@ impl Value {
|
|||||||
Value(Arc::new(ValueInner::Function(Function::BuiltIn(function))))
|
Value(Arc::new(ValueInner::Function(Function::BuiltIn(function))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> Type {
|
pub fn r#type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||||
match self.0.as_ref() {
|
let r#type = match self.0.as_ref() {
|
||||||
ValueInner::Boolean(_) => Type::Boolean,
|
ValueInner::Boolean(_) => Type::Boolean,
|
||||||
ValueInner::Float(_) => Type::Float,
|
ValueInner::Float(_) => Type::Float,
|
||||||
ValueInner::Integer(_) => Type::Integer,
|
ValueInner::Integer(_) => Type::Integer,
|
||||||
@ -83,7 +83,7 @@ impl Value {
|
|||||||
let mut types = Vec::with_capacity(values.len());
|
let mut types = Vec::with_capacity(values.len());
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
types.push(value.r#type());
|
types.push(value.r#type(context)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::ListExact(types)
|
Type::ListExact(types)
|
||||||
@ -102,7 +102,29 @@ impl Value {
|
|||||||
},
|
},
|
||||||
Function::BuiltIn(built_in_function) => built_in_function.r#type(),
|
Function::BuiltIn(built_in_function) => built_in_function.r#type(),
|
||||||
},
|
},
|
||||||
|
ValueInner::Structure {
|
||||||
|
name,
|
||||||
|
fields: expressions,
|
||||||
|
} => {
|
||||||
|
let mut fields = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
|
for (identifier, expression) in expressions {
|
||||||
|
let r#type = expression
|
||||||
|
.node
|
||||||
|
.expected_type(context)?
|
||||||
|
.with_position(expression.position);
|
||||||
|
|
||||||
|
fields.push((identifier.clone(), r#type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type::Structure {
|
||||||
|
name: name.clone(),
|
||||||
|
fields,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(r#type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_boolean(&self) -> Option<bool> {
|
pub fn as_boolean(&self) -> Option<bool> {
|
||||||
@ -176,6 +198,7 @@ impl Display for Value {
|
|||||||
ValueInner::Function(Function::BuiltIn(built_in_function)) => {
|
ValueInner::Function(Function::BuiltIn(built_in_function)) => {
|
||||||
write!(f, "{built_in_function}")
|
write!(f, "{built_in_function}")
|
||||||
}
|
}
|
||||||
|
ValueInner::Structure { name, fields } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,6 +227,10 @@ pub enum ValueInner {
|
|||||||
Map(BTreeMap<Identifier, Value>),
|
Map(BTreeMap<Identifier, Value>),
|
||||||
Range(Range<i64>),
|
Range(Range<i64>),
|
||||||
String(String),
|
String(String),
|
||||||
|
Structure {
|
||||||
|
name: Identifier,
|
||||||
|
fields: Vec<(Identifier, WithPosition<Expression>)>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for ValueInner {}
|
impl Eq for ValueInner {}
|
||||||
@ -243,6 +270,25 @@ impl Ord for ValueInner {
|
|||||||
(String(_), _) => Ordering::Greater,
|
(String(_), _) => Ordering::Greater,
|
||||||
(Function(left), Function(right)) => left.cmp(right),
|
(Function(left), Function(right)) => left.cmp(right),
|
||||||
(Function(_), _) => Ordering::Greater,
|
(Function(_), _) => Ordering::Greater,
|
||||||
|
(
|
||||||
|
Structure {
|
||||||
|
name: left_name,
|
||||||
|
fields: left_fields,
|
||||||
|
},
|
||||||
|
Structure {
|
||||||
|
name: right_name,
|
||||||
|
fields: right_fields,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let name_cmp = left_name.cmp(right_name);
|
||||||
|
|
||||||
|
if name_cmp.is_eq() {
|
||||||
|
left_fields.cmp(right_fields)
|
||||||
|
} else {
|
||||||
|
name_cmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Structure { .. }, _) => Ordering::Greater,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -347,7 +393,7 @@ impl BuiltInFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, arguments: Vec<Value>, _context: &Context) -> Result<Action, RuntimeError> {
|
pub fn call(&self, arguments: Vec<Value>, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunction::IntParse => {
|
BuiltInFunction::IntParse => {
|
||||||
let string = arguments.get(0).unwrap();
|
let string = arguments.get(0).unwrap();
|
||||||
@ -359,10 +405,18 @@ impl BuiltInFunction {
|
|||||||
|
|
||||||
// Ok(Action::Return(Value::integer(integer)))
|
// Ok(Action::Return(Value::integer(integer)))
|
||||||
} else {
|
} else {
|
||||||
|
let mut actual = Vec::with_capacity(arguments.len());
|
||||||
|
|
||||||
|
for value in arguments {
|
||||||
|
let r#type = value.r#type(context)?;
|
||||||
|
|
||||||
|
actual.push(r#type);
|
||||||
|
}
|
||||||
|
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::WrongArguments {
|
ValidationError::WrongArguments {
|
||||||
expected: vec![Type::String],
|
expected: vec![Type::String],
|
||||||
actual: arguments.iter().map(|value| value.r#type()).collect(),
|
actual,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user