Continue refactoring
This commit is contained in:
parent
fb413e24b0
commit
88906fb6d7
@ -56,7 +56,7 @@ impl AbstractNode for As {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let r#type = self.constructor.construct(&context)?;
|
let r#type = self.constructor.construct(&context)?;
|
||||||
|
@ -46,13 +46,13 @@ impl Assignment {
|
|||||||
impl AbstractNode for Assignment {
|
impl AbstractNode for Assignment {
|
||||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
let relevant_statement = self.statement.last_evaluated_statement();
|
let relevant_statement = self.statement.last_evaluated_statement();
|
||||||
let statement_type = relevant_statement.expected_type(context)?;
|
let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
|
||||||
|
r#type
|
||||||
if let Type::Void = &statement_type {
|
} else {
|
||||||
return Err(ValidationError::CannotAssignToNone(
|
return Err(ValidationError::CannotAssignToNone(
|
||||||
self.statement.position(),
|
self.statement.position(),
|
||||||
));
|
));
|
||||||
}
|
};
|
||||||
|
|
||||||
if let Some(constructor) = &self.constructor {
|
if let Some(constructor) = &self.constructor {
|
||||||
let r#type = constructor.clone().construct(&context)?;
|
let r#type = constructor.clone().construct(&context)?;
|
||||||
@ -83,13 +83,13 @@ impl AbstractNode for Assignment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let relevant_statement = self.statement.last_evaluated_statement();
|
let relevant_statement = self.statement.last_evaluated_statement();
|
||||||
let statement_type = relevant_statement.expected_type(context)?;
|
let statement_type = if let Some(r#type) = relevant_statement.expected_type(context)? {
|
||||||
|
r#type
|
||||||
if let Type::Void = &statement_type {
|
} else {
|
||||||
return Err(ValidationError::CannotAssignToNone(
|
return Err(ValidationError::CannotAssignToNone(
|
||||||
self.statement.position(),
|
self.statement.position(),
|
||||||
));
|
));
|
||||||
}
|
};
|
||||||
|
|
||||||
if let Some(constructor) = &self.constructor {
|
if let Some(constructor) = &self.constructor {
|
||||||
let r#type = constructor.clone().construct(&context)?;
|
let r#type = constructor.clone().construct(&context)?;
|
||||||
@ -138,11 +138,11 @@ impl AbstractNode for Assignment {
|
|||||||
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)?;
|
||||||
|
|
||||||
if let Type::Function {
|
if let Some(Type::Function {
|
||||||
return_type,
|
return_type,
|
||||||
type_parameters: Some(type_parameters),
|
type_parameters: Some(type_parameters),
|
||||||
..
|
..
|
||||||
} = function_type
|
}) = function_type
|
||||||
{
|
{
|
||||||
if let Type::Generic { identifier, .. } = *return_type {
|
if let Type::Generic { identifier, .. } = *return_type {
|
||||||
let returned_parameter = type_parameters
|
let returned_parameter = type_parameters
|
||||||
@ -157,7 +157,7 @@ impl AbstractNode for Assignment {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedFunction {
|
return Err(ValidationError::ExpectedFunction {
|
||||||
actual: function_type,
|
actual: function_type.unwrap(),
|
||||||
position: function_call.position,
|
position: function_call.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ impl AbstractNode for Assignment {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let evaluation = self.statement.run(context, manage_memory)?;
|
let evaluation = self.statement.evaluate(context, manage_memory)?;
|
||||||
let right = match evaluation {
|
let right = match evaluation {
|
||||||
Some(Evaluation::Return(value)) => value,
|
Some(Evaluation::Return(value)) => value,
|
||||||
evaluation => return Ok(evaluation),
|
evaluation => return Ok(evaluation),
|
||||||
@ -273,10 +273,10 @@ impl AbstractNode for Assignment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(Evaluation::Void))
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,7 @@ impl AbstractNode for AsyncBlock {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(self, _context: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
self,
|
|
||||||
_context: &Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
let statement_count = self.statements.len();
|
let statement_count = self.statements.len();
|
||||||
let final_result = Mutex::new(Ok(None));
|
let final_result = Mutex::new(Ok(None));
|
||||||
|
|
||||||
@ -51,7 +47,7 @@ impl AbstractNode for AsyncBlock {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map_any(
|
.find_map_any(
|
||||||
|(index, statement)| -> Option<Result<Option<Evaluation>, RuntimeError>> {
|
|(index, statement)| -> Option<Result<Option<Evaluation>, RuntimeError>> {
|
||||||
let result = statement.run(&mut _context.clone(), false);
|
let result = statement.evaluate(&_context, false);
|
||||||
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
|
@ -51,7 +51,7 @@ impl AbstractNode for Block {
|
|||||||
let mut previous = None;
|
let mut previous = None;
|
||||||
|
|
||||||
for statement in self.statements {
|
for statement in self.statements {
|
||||||
previous = statement.run(_context, _manage_memory)?;
|
previous = statement.evaluate(_context, _manage_memory)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(previous)
|
Ok(previous)
|
||||||
@ -86,7 +86,7 @@ mod tests {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block.run(&mut Context::new(None), true).unwrap(),
|
block.evaluate(&Context::new(None), true).unwrap(),
|
||||||
Some(Evaluation::Return(Value::integer(42)))
|
Some(Evaluation::Return(Value::integer(42)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -103,8 +103,8 @@ mod tests {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
block.expected_type(&mut Context::new(None)),
|
block.expected_type(&Context::new(None)),
|
||||||
Ok(Type::Integer)
|
Ok(Some(Type::Integer))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,15 @@ pub enum BuiltInFunctionCall {
|
|||||||
WriteLine(Expression),
|
WriteLine(Expression),
|
||||||
}
|
}
|
||||||
impl AbstractNode for BuiltInFunctionCall {
|
impl AbstractNode for BuiltInFunctionCall {
|
||||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
Ok(())
|
match self {
|
||||||
|
BuiltInFunctionCall::JsonParse(_, expression) => expression.define_types(_context),
|
||||||
|
BuiltInFunctionCall::Length(expression) => expression.define_types(_context),
|
||||||
|
BuiltInFunctionCall::ReadFile(expression) => expression.define_types(_context),
|
||||||
|
BuiltInFunctionCall::ReadLine => Ok(()),
|
||||||
|
BuiltInFunctionCall::Sleep(expression) => expression.define_types(_context),
|
||||||
|
BuiltInFunctionCall::WriteLine(expression) => expression.define_types(_context),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
@ -54,56 +61,53 @@ impl AbstractNode for BuiltInFunctionCall {
|
|||||||
context: &Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
fn evaluate_expression(
|
||||||
|
expression: Expression,
|
||||||
|
context: &Context,
|
||||||
|
_manage_memory: bool,
|
||||||
|
) -> Result<Value, RuntimeError> {
|
||||||
|
let position = expression.position();
|
||||||
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
|
|
||||||
|
if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
|
Ok(value)
|
||||||
|
} else {
|
||||||
|
Err(RuntimeError::ValidationFailure(
|
||||||
|
ValidationError::ExpectedExpression(position),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::JsonParse(_type, expression) => {
|
BuiltInFunctionCall::JsonParse(_type, expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let position = expression.position();
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = evaluate_expression(expression, context, _manage_memory)?;
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
if let ValueInner::String(string) = value.inner().as_ref() {
|
if let ValueInner::String(string) = value.inner().as_ref() {
|
||||||
let deserialized = serde_json::from_str(string)?;
|
let deserialized = serde_json::from_str(&string)?;
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(deserialized)))
|
Ok(Some(Evaluation::Return(deserialized)))
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedString {
|
ValidationError::ExpectedString {
|
||||||
actual: value.r#type(context)?,
|
actual: value.r#type(context)?,
|
||||||
position: expression.position(),
|
position,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::Length(expression) => {
|
BuiltInFunctionCall::Length(expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let value = evaluate_expression(expression, context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
let length = if let ValueInner::List(list) = value.inner().as_ref() {
|
let length = if let ValueInner::List(list) = value.inner().as_ref() {
|
||||||
list.len() as i64
|
list.len() as i64
|
||||||
} else {
|
} else {
|
||||||
0
|
todo!("Create an error for this occurence.")
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(Evaluation::Return(Value::integer(length))))
|
Ok(Some(Evaluation::Return(Value::integer(length))))
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::ReadFile(expression) => {
|
BuiltInFunctionCall::ReadFile(expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let value = evaluate_expression(expression, context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
let file_contents = if let ValueInner::String(path) = value.inner().as_ref() {
|
let file_contents = if let ValueInner::String(path) = value.inner().as_ref() {
|
||||||
read_to_string(path)?
|
read_to_string(path)?
|
||||||
} else {
|
} else {
|
||||||
@ -122,30 +126,16 @@ impl AbstractNode for BuiltInFunctionCall {
|
|||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::Sleep(expression) => {
|
BuiltInFunctionCall::Sleep(expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let value = evaluate_expression(expression, context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
if let ValueInner::Integer(milliseconds) = value.inner().as_ref() {
|
if let ValueInner::Integer(milliseconds) = value.inner().as_ref() {
|
||||||
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
thread::sleep(Duration::from_millis(*milliseconds as u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Evaluation::Void)
|
Ok(None)
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::WriteLine(expression) => {
|
BuiltInFunctionCall::WriteLine(expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let value = evaluate_expression(expression, context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ValidationFailure(
|
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position()),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
if let ValueInner::String(output) = value.inner().as_ref() {
|
if let ValueInner::String(output) = value.inner().as_ref() {
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
@ -155,7 +145,7 @@ impl AbstractNode for BuiltInFunctionCall {
|
|||||||
stdout.flush()?;
|
stdout.flush()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Evaluation::Void)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ impl AbstractNode for EnumDeclaration {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
type_variants.push((name.node, types));
|
type_variants.push((name.node.clone(), types));
|
||||||
}
|
}
|
||||||
|
|
||||||
let r#type = Type::Enum {
|
let r#type = Type::Enum {
|
||||||
@ -72,31 +72,20 @@ impl AbstractNode for EnumDeclaration {
|
|||||||
variants: type_variants,
|
variants: type_variants,
|
||||||
};
|
};
|
||||||
|
|
||||||
context.set_type(name.node, r#type)?;
|
context.set_type(name.node.clone(), r#type)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(
|
fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
|
||||||
&self,
|
|
||||||
context: &Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<(), crate::error::ValidationError> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
self,
|
|
||||||
context: &Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(
|
fn expected_type(&self, _: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
&self,
|
|
||||||
context: &Context,
|
|
||||||
) -> Result<Option<Type>, crate::error::ValidationError> {
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::As(inner) => inner.node.define_types(_context),
|
Expression::As(inner) => inner.node.define_types(_context),
|
||||||
Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context),
|
Expression::BuiltInFunctionCall(inner) => inner.node.define_types(_context),
|
||||||
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
Expression::FunctionCall(inner) => inner.node.define_types(_context),
|
||||||
Expression::Identifier(inner) => inner.node.define_types(_context),
|
Expression::Identifier(_) => Ok(()),
|
||||||
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
Expression::MapIndex(inner) => inner.node.define_types(_context),
|
||||||
Expression::ListIndex(inner) => inner.node.define_types(_context),
|
Expression::ListIndex(inner) => inner.node.define_types(_context),
|
||||||
Expression::Logic(inner) => inner.node.define_types(_context),
|
Expression::Logic(inner) => inner.node.define_types(_context),
|
||||||
@ -132,7 +132,7 @@ impl AbstractNode for Expression {
|
|||||||
Expression::As(r#as) => r#as.node.expected_type(_context),
|
Expression::As(r#as) => r#as.node.expected_type(_context),
|
||||||
Expression::FunctionCall(function_call) => function_call.node.expected_type(_context),
|
Expression::FunctionCall(function_call) => function_call.node.expected_type(_context),
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let get_type = _context.get_type(identifier)?;
|
let get_type = _context.get_type(&identifier.node)?;
|
||||||
|
|
||||||
if get_type.is_none() {
|
if get_type.is_none() {
|
||||||
Err(ValidationError::VariableNotFound {
|
Err(ValidationError::VariableNotFound {
|
||||||
|
@ -35,7 +35,7 @@ impl FunctionCall {
|
|||||||
|
|
||||||
impl AbstractNode for FunctionCall {
|
impl AbstractNode for FunctionCall {
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
self.function.define_ypes(_context)?;
|
self.function.define_types(_context)?;
|
||||||
|
|
||||||
let mut previous = ();
|
let mut previous = ();
|
||||||
|
|
||||||
@ -53,7 +53,13 @@ impl AbstractNode for FunctionCall {
|
|||||||
expression.validate(context, manage_memory)?;
|
expression.validate(context, manage_memory)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let function_node_type = self.function.expected_type(context)?;
|
let function_node_type = if let Some(r#type) = self.function.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(
|
||||||
|
self.function.position(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
if let Type::Function {
|
if let Type::Function {
|
||||||
type_parameters,
|
type_parameters,
|
||||||
@ -88,12 +94,12 @@ impl AbstractNode for FunctionCall {
|
|||||||
clear_variables: bool,
|
clear_variables: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let function_position = self.function.position();
|
let function_position = self.function.position();
|
||||||
let action = self.function.evaluate(context, clear_variables)?;
|
let evaluation = self.function.evaluate(context, clear_variables)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(function_position),
|
ValidationError::ExpectedExpression(function_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let function = if let ValueInner::Function(function) = value.inner().as_ref() {
|
let function = if let ValueInner::Function(function) = value.inner().as_ref() {
|
||||||
@ -111,15 +117,15 @@ impl AbstractNode for FunctionCall {
|
|||||||
for expression in self.value_arguments {
|
for expression in self.value_arguments {
|
||||||
let expression_position = expression.position();
|
let expression_position = expression.position();
|
||||||
let action = expression.evaluate(context, clear_variables)?;
|
let action = expression.evaluate(context, clear_variables)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let evalution = if let Some(Evaluation::Return(value)) = action {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
arguments.push(value);
|
arguments.push(evalution);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut function_context = Context::new(Some(&context));
|
let mut function_context = Context::new(Some(&context));
|
||||||
@ -143,13 +149,19 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
let function_node_type = self.function.expected_type(context)?;
|
let function_type = if let Some(r#type) = self.function.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(
|
||||||
|
self.function.position(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
if let Type::Function {
|
if let Type::Function {
|
||||||
return_type,
|
return_type,
|
||||||
type_parameters,
|
type_parameters,
|
||||||
..
|
..
|
||||||
} = function_node_type
|
} = function_type
|
||||||
{
|
{
|
||||||
if let Type::Generic {
|
if let Type::Generic {
|
||||||
identifier: return_identifier,
|
identifier: return_identifier,
|
||||||
@ -179,7 +191,14 @@ impl AbstractNode for FunctionCall {
|
|||||||
.zip(type_parameters.into_iter())
|
.zip(type_parameters.into_iter())
|
||||||
{
|
{
|
||||||
if identifier == return_identifier {
|
if identifier == return_identifier {
|
||||||
let concrete_type = expression.expected_type(context)?;
|
let concrete_type =
|
||||||
|
if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(
|
||||||
|
expression.position(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
return Ok(Some(Type::Generic {
|
return Ok(Some(Type::Generic {
|
||||||
identifier,
|
identifier,
|
||||||
@ -193,7 +212,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
Ok(Some(*return_type))
|
Ok(Some(*return_type))
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
actual: function_node_type,
|
actual: function_type,
|
||||||
position: self.function.position(),
|
position: self.function.position(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -35,16 +35,16 @@ impl IfElse {
|
|||||||
impl AbstractNode for IfElse {
|
impl AbstractNode for IfElse {
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
self.if_expression.define_types(_context)?;
|
self.if_expression.define_types(_context)?;
|
||||||
self.if_block.define_type(_context)?;
|
self.if_block.node.define_types(_context)?;
|
||||||
|
|
||||||
if let Some(else_ifs) = self.else_ifs {
|
if let Some(else_ifs) = &self.else_ifs {
|
||||||
for (expression, block) in else_ifs {
|
for (expression, block) in else_ifs {
|
||||||
expression.define_types(_context)?;
|
expression.define_types(_context)?;
|
||||||
block.node.define_types(_context)?;
|
block.node.define_types(_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(else_block) = self.else_block {
|
if let Some(else_block) = &self.else_block {
|
||||||
else_block.node.define_types(_context)?;
|
else_block.node.define_types(_context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,22 +55,36 @@ impl AbstractNode for IfElse {
|
|||||||
self.if_expression.validate(context, manage_memory)?;
|
self.if_expression.validate(context, manage_memory)?;
|
||||||
self.if_block.node.validate(context, manage_memory)?;
|
self.if_block.node.validate(context, manage_memory)?;
|
||||||
|
|
||||||
let expected_type = self.if_block.node.expected_type(context)?;
|
let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? {
|
||||||
let if_expression_type = self.if_expression.expected_type(context)?;
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(
|
||||||
|
self.if_expression.position(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let expected_type = if let Some(r#type) = self.if_block.node.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(self.if_block.position));
|
||||||
|
};
|
||||||
|
|
||||||
if let Type::Boolean = if_expression_type {
|
if let Type::Boolean = if_expression_type {
|
||||||
if let Some(else_block) = &self.else_block {
|
if let Some(else_block) = &self.else_block {
|
||||||
else_block.node.validate(context, manage_memory)?;
|
else_block.node.validate(context, manage_memory)?;
|
||||||
|
|
||||||
let actual = else_block.node.expected_type(context)?;
|
let actual_type = if let Some(r#type) = else_block.node.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(else_block.position));
|
||||||
|
};
|
||||||
|
|
||||||
expected_type
|
expected_type.check(&actual_type).map_err(|conflict| {
|
||||||
.check(&actual)
|
ValidationError::TypeCheck {
|
||||||
.map_err(|conflict| ValidationError::TypeCheck {
|
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: else_block.node.last_statement().position(),
|
actual_position: else_block.node.last_statement().position(),
|
||||||
expected_position: Some(self.if_block.node.first_statement().position()),
|
expected_position: Some(self.if_block.node.first_statement().position()),
|
||||||
})?;
|
}
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::ExpectedBoolean {
|
return Err(ValidationError::ExpectedBoolean {
|
||||||
@ -83,12 +97,16 @@ impl AbstractNode for IfElse {
|
|||||||
for (expression, block) in else_ifs {
|
for (expression, block) in else_ifs {
|
||||||
let expression_type = expression.expected_type(context)?;
|
let expression_type = expression.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Boolean = expression_type {
|
if let Some(Type::Boolean) = expression_type {
|
||||||
block.node.validate(context, manage_memory)?;
|
block.node.validate(context, manage_memory)?;
|
||||||
|
|
||||||
let actual = block.node.expected_type(context)?;
|
let actual_type = if let Some(r#type) = block.node.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(block.position));
|
||||||
|
};
|
||||||
|
|
||||||
expected_type.check(&actual).map_err(|conflict| {
|
expected_type.check(&actual_type).map_err(|conflict| {
|
||||||
ValidationError::TypeCheck {
|
ValidationError::TypeCheck {
|
||||||
conflict,
|
conflict,
|
||||||
actual_position: self.if_block.node.last_statement().position(),
|
actual_position: self.if_block.node.last_statement().position(),
|
||||||
@ -113,35 +131,35 @@ impl AbstractNode for IfElse {
|
|||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let if_position = self.if_expression.position();
|
let if_position = self.if_expression.position();
|
||||||
let action = self.if_expression.evaluate(context, _manage_memory)?;
|
let evaluation = self.if_expression.evaluate(context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(if_position),
|
ValidationError::ExpectedExpression(if_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
||||||
return self.if_block.node.run(context, _manage_memory);
|
return self.if_block.node.evaluate(context, _manage_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(else_ifs) = self.else_ifs {
|
if let Some(else_ifs) = self.else_ifs {
|
||||||
for (expression, block) in else_ifs {
|
for (expression, block) in else_ifs {
|
||||||
let expression_position = expression.position();
|
let expression_position = expression.position();
|
||||||
let action = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
|
if let ValueInner::Boolean(else_if_boolean) = value.inner().as_ref() {
|
||||||
if *else_if_boolean {
|
if *else_if_boolean {
|
||||||
return block.node.run(context, _manage_memory);
|
return block.node.evaluate(context, _manage_memory);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
@ -155,7 +173,7 @@ impl AbstractNode for IfElse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(else_statement) = self.else_block {
|
if let Some(else_statement) = self.else_block {
|
||||||
else_statement.node.run(context, _manage_memory)
|
else_statement.node.evaluate(context, _manage_memory)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -195,7 +213,7 @@ mod tests {
|
|||||||
Some(Vec::with_capacity(0)),
|
Some(Vec::with_capacity(0)),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
.run(&mut Context::new(None), true)
|
.evaluate(&Context::new(None), true)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(Evaluation::Return(Value::string("foo".to_string())))
|
Some(Evaluation::Return(Value::string("foo".to_string())))
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, Validate, ValueNode, WithPosition};
|
use super::{AbstractNode, Evaluation, Expression, Type, ValueNode, WithPosition};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct ListIndex {
|
pub struct ListIndex {
|
||||||
@ -22,8 +22,13 @@ impl ListIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for ListIndex {
|
impl AbstractNode for ListIndex {
|
||||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
|
self.collection.define_types(context)?;
|
||||||
|
self.index.define_types(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
self.collection.validate(context, _manage_memory)?;
|
self.collection.validate(context, _manage_memory)?;
|
||||||
self.index.validate(context, _manage_memory)?;
|
self.index.validate(context, _manage_memory)?;
|
||||||
|
|
||||||
@ -57,12 +62,10 @@ impl Validate for ListIndex {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for ListIndex {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_clear_variables: bool,
|
_clear_variables: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let left_position = self.collection.position();
|
let left_position = self.collection.position();
|
||||||
@ -71,7 +74,7 @@ impl AbstractNode for ListIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(left_position),
|
ValidationError::ExpectedExpression(left_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
let right_position = self.index.position();
|
let right_position = self.index.position();
|
||||||
@ -80,7 +83,7 @@ impl AbstractNode for ListIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(right_position),
|
ValidationError::ExpectedExpression(right_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,7 +107,7 @@ impl AbstractNode for ListIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
let left_type = self.collection.expected_type(_context)?;
|
let left_type = self.collection.expected_type(_context)?;
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Logic {
|
pub enum Logic {
|
||||||
@ -22,8 +22,46 @@ pub enum Logic {
|
|||||||
Not(Expression),
|
Not(Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Logic {
|
impl AbstractNode for Logic {
|
||||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
Logic::Equal(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::NotEqual(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::Greater(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::Less(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::GreaterOrEqual(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::LessOrEqual(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::And(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::Or(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Logic::Not(expression) => expression.define_types(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Logic::Equal(left, right)
|
Logic::Equal(left, right)
|
||||||
| Logic::NotEqual(left, right)
|
| Logic::NotEqual(left, right)
|
||||||
@ -88,12 +126,10 @@ impl Validate for Logic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for Logic {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
|
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
|
||||||
@ -103,7 +139,7 @@ impl AbstractNode for Logic {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,7 +153,7 @@ impl AbstractNode for Logic {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -196,7 +232,7 @@ impl AbstractNode for Logic {
|
|||||||
Ok(Some(Evaluation::Return(Value::boolean(boolean))))
|
Ok(Some(Evaluation::Return(Value::boolean(boolean))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
Ok(Some(Type::Boolean))
|
Ok(Some(Type::Boolean))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Statement, Validate};
|
use super::{AbstractNode, Evaluation, Statement, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Loop {
|
pub struct Loop {
|
||||||
@ -21,25 +21,26 @@ impl Loop {
|
|||||||
self.statements.last().unwrap()
|
self.statements.last().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl AbstractNode for Loop {
|
||||||
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
for statement in &self.statements {
|
||||||
|
statement.define_types(_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for Loop {
|
Ok(())
|
||||||
fn validate(
|
}
|
||||||
&self,
|
|
||||||
_context: &mut Context,
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
statement.validate(_context, false)?;
|
statement.validate(_context, false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for Loop {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
loop {
|
loop {
|
||||||
@ -53,10 +54,7 @@ impl AbstractNode for Loop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
&self,
|
|
||||||
_context: &mut Context,
|
|
||||||
) -> Result<Option<super::Type>, ValidationError> {
|
|
||||||
self.last_statement().expected_type(_context)
|
self.last_statement().expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Type, Validate, ValueNode, WithPosition};
|
use super::{AbstractNode, Evaluation, Expression, Type, ValueNode, WithPosition};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct MapIndex {
|
pub struct MapIndex {
|
||||||
@ -23,20 +23,19 @@ impl MapIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for MapIndex {
|
impl AbstractNode for MapIndex {
|
||||||
fn validate(
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
&self,
|
self.collection.define_types(_context)?;
|
||||||
_context: &mut Context,
|
self.index.define_types(_context)
|
||||||
_manage_memory: bool,
|
}
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
self.collection.validate(_context, _manage_memory)
|
self.collection.validate(_context, _manage_memory)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for MapIndex {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let collection_position = self.collection.position();
|
let collection_position = self.collection.position();
|
||||||
@ -45,7 +44,7 @@ impl AbstractNode for MapIndex {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(collection_position),
|
ValidationError::ExpectedExpression(collection_position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ impl AbstractNode for MapIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
if let (Expression::Identifier(collection), Expression::Identifier(index)) =
|
if let (Expression::Identifier(collection), Expression::Identifier(index)) =
|
||||||
(&self.collection, &self.index)
|
(&self.collection, &self.index)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, SourcePosition, Type, Validate};
|
use super::{AbstractNode, Evaluation, Expression, SourcePosition, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Math {
|
pub enum Math {
|
||||||
@ -18,8 +18,33 @@ pub enum Math {
|
|||||||
Modulo(Expression, Expression),
|
Modulo(Expression, Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Math {
|
impl AbstractNode for Math {
|
||||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
Math::Add(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Math::Subtract(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Math::Multiply(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Math::Divide(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
Math::Modulo(left, right) => {
|
||||||
|
left.define_types(_context)?;
|
||||||
|
right.define_types(_context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Math::Add(left, right) => {
|
Math::Add(left, right) => {
|
||||||
let left_position = left.position();
|
let left_position = left.position();
|
||||||
@ -66,12 +91,10 @@ impl Validate for Math {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for Math {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &Context,
|
||||||
_clear_variables: bool,
|
_clear_variables: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let run_and_expect_value =
|
let run_and_expect_value =
|
||||||
@ -81,7 +104,7 @@ impl AbstractNode for Math {
|
|||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(position),
|
ValidationError::ExpectedExpression(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -296,7 +319,7 @@ impl AbstractNode for Math {
|
|||||||
Ok(Some(Evaluation::Return(value)))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Math::Add(left, right)
|
Math::Add(left, right)
|
||||||
| Math::Subtract(left, right)
|
| Math::Subtract(left, right)
|
||||||
|
@ -6,9 +6,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AbstractNode, Assignment, AsyncBlock, Block, DefineTypes, EnumDeclaration, Evaluation,
|
AbstractNode, Assignment, AsyncBlock, Block, EnumDeclaration, Evaluation, Expression, IfElse,
|
||||||
Expression, IfElse, Loop, SourcePosition, StructureDefinition, Type, TypeAlias, Validate,
|
Loop, SourcePosition, StructureDefinition, Type, TypeAlias, While, WithPosition,
|
||||||
While, WithPosition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -52,7 +51,7 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefineTypes for Statement {
|
impl AbstractNode for Statement {
|
||||||
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Expression(expression) => expression.define_types(_context),
|
Statement::Expression(expression) => expression.define_types(_context),
|
||||||
@ -72,12 +71,26 @@ impl DefineTypes for Statement {
|
|||||||
Statement::While(r#while) => r#while.node.define_types(_context),
|
Statement::While(r#while) => r#while.node.define_types(_context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for Statement {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory),
|
||||||
|
Statement::AsyncBlock(async_block) => {
|
||||||
|
async_block.node.validate(_context, _manage_memory)
|
||||||
|
}
|
||||||
|
Statement::Block(block) => block.node.validate(_context, _manage_memory),
|
||||||
|
Statement::Break(_) => Ok(()),
|
||||||
|
Statement::Expression(expression) => expression.validate(_context, _manage_memory),
|
||||||
|
Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory),
|
||||||
|
Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory),
|
||||||
|
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory),
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let result = match self {
|
let result = match self {
|
||||||
@ -105,7 +118,7 @@ impl AbstractNode for Statement {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Expression(expression) => expression.expected_type(_context),
|
Statement::Expression(expression) => expression.expected_type(_context),
|
||||||
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
|
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
|
||||||
@ -125,25 +138,3 @@ impl AbstractNode for Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Statement {
|
|
||||||
fn validate(
|
|
||||||
&self,
|
|
||||||
_context: &mut Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
match self {
|
|
||||||
Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory),
|
|
||||||
Statement::AsyncBlock(async_block) => {
|
|
||||||
async_block.node.validate(_context, _manage_memory)
|
|
||||||
}
|
|
||||||
Statement::Block(block) => block.node.validate(_context, _manage_memory),
|
|
||||||
Statement::Break(_) => Ok(()),
|
|
||||||
Statement::Expression(expression) => expression.validate(_context, _manage_memory),
|
|
||||||
Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory),
|
|
||||||
Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory),
|
|
||||||
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory),
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{context::Context, error::RuntimeError, identifier::Identifier};
|
use crate::{
|
||||||
|
context::Context,
|
||||||
|
error::{RuntimeError, ValidationError},
|
||||||
|
identifier::Identifier,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Type, TypeConstructor};
|
use super::{AbstractNode, Evaluation, Type, TypeConstructor};
|
||||||
|
|
||||||
@ -17,9 +21,32 @@ impl StructureDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for StructureDefinition {
|
impl AbstractNode for StructureDefinition {
|
||||||
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
|
let mut fields = Vec::with_capacity(self.fields.len());
|
||||||
|
|
||||||
|
for (identifier, constructor) in self.fields {
|
||||||
|
let r#type = constructor.construct(&context)?;
|
||||||
|
|
||||||
|
fields.push((identifier, r#type));
|
||||||
|
}
|
||||||
|
|
||||||
|
let struct_type = Type::Structure {
|
||||||
|
name: self.name.clone(),
|
||||||
|
fields,
|
||||||
|
};
|
||||||
|
|
||||||
|
context.set_type(self.name, struct_type)?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let mut fields = Vec::with_capacity(self.fields.len());
|
let mut fields = Vec::with_capacity(self.fields.len());
|
||||||
@ -40,10 +67,7 @@ impl AbstractNode for StructureDefinition {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
&self,
|
|
||||||
context: &mut Context,
|
|
||||||
) -> Result<Option<Type>, crate::error::ValidationError> {
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, DefineTypes, Evaluation, Type, TypeConstructor, WithPosition};
|
use super::{AbstractNode, Evaluation, Type, TypeConstructor, WithPosition};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct TypeAlias {
|
pub struct TypeAlias {
|
||||||
@ -24,20 +24,6 @@ impl TypeAlias {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractNode for TypeAlias {
|
impl AbstractNode for TypeAlias {
|
||||||
fn evaluate(
|
|
||||||
self,
|
|
||||||
context: &mut Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DefineTypes for TypeAlias {
|
|
||||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
let r#type = self.constructor.construct(&context)?;
|
let r#type = self.constructor.construct(&context)?;
|
||||||
|
|
||||||
@ -45,4 +31,20 @@ impl DefineTypes for TypeAlias {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn evaluate(
|
||||||
|
self,
|
||||||
|
context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AbstractNode, Block, Evaluation, Expression, Type, TypeConstructor, Validate, WithPosition,
|
AbstractNode, Block, Evaluation, Expression, Type, TypeConstructor, WithPos, WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -39,8 +39,46 @@ pub enum ValueNode {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for ValueNode {
|
impl AbstractNode for ValueNode {
|
||||||
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
ValueNode::EnumInstance { content, .. } => {
|
||||||
|
if let Some(expressions) = content {
|
||||||
|
for expression in expressions {
|
||||||
|
expression.define_types(_context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::List(expressions) => {
|
||||||
|
for expression in expressions {
|
||||||
|
expression.define_types(_context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Map(fields) => {
|
||||||
|
for (_, _, expression) in fields {
|
||||||
|
expression.define_types(_context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Structure { fields, .. } => {
|
||||||
|
for (_, expression) in fields {
|
||||||
|
expression.define_types(_context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Function {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
body.node.define_types(_context)?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
if let ValueNode::EnumInstance {
|
if let ValueNode::EnumInstance {
|
||||||
type_name, variant, ..
|
type_name, variant, ..
|
||||||
} = self
|
} = self
|
||||||
@ -69,7 +107,11 @@ impl Validate for ValueNode {
|
|||||||
expression.validate(context, _manage_memory)?;
|
expression.validate(context, _manage_memory)?;
|
||||||
|
|
||||||
if let Some(constructor) = constructor_option {
|
if let Some(constructor) = constructor_option {
|
||||||
let actual_type = expression.expected_type(context)?;
|
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
|
};
|
||||||
let exprected_type = constructor.clone().construct(&context)?;
|
let exprected_type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
exprected_type.check(&actual_type).map_err(|conflict| {
|
exprected_type.check(&actual_type).map_err(|conflict| {
|
||||||
@ -114,7 +156,11 @@ impl Validate for ValueNode {
|
|||||||
|
|
||||||
body.node.validate(&mut function_context, _manage_memory)?;
|
body.node.validate(&mut function_context, _manage_memory)?;
|
||||||
|
|
||||||
let actual_return_type = body.node.expected_type(&mut function_context)?;
|
let actual_return_type = if let Some(r#type) = body.node.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(body.position));
|
||||||
|
};
|
||||||
|
|
||||||
return_type
|
return_type
|
||||||
.clone()
|
.clone()
|
||||||
@ -147,7 +193,11 @@ impl Validate for ValueNode {
|
|||||||
}) = context.get_type(&name.node)?
|
}) = context.get_type(&name.node)?
|
||||||
{
|
{
|
||||||
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
|
||||||
let actual_type = expression.expected_type(context)?;
|
let actual_type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
|
};
|
||||||
|
|
||||||
expected_type.check(&actual_type).map_err(|conflict| {
|
expected_type.check(&actual_type).map_err(|conflict| {
|
||||||
ValidationError::TypeCheck {
|
ValidationError::TypeCheck {
|
||||||
@ -162,12 +212,10 @@ impl Validate for ValueNode {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for ValueNode {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let value = match self {
|
let value = match self {
|
||||||
@ -184,11 +232,11 @@ impl AbstractNode for ValueNode {
|
|||||||
let position = expression.position();
|
let position = expression.position();
|
||||||
let evaluation = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
|
|
||||||
if let Evaluation::Return(value) = evaluation {
|
if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
values.push(value);
|
values.push(value);
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(position),
|
ValidationError::ExpectedExpression(position),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,13 +253,13 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut value_list = Vec::with_capacity(expression_list.len());
|
let mut value_list = Vec::with_capacity(expression_list.len());
|
||||||
|
|
||||||
for expression in expression_list {
|
for expression in expression_list {
|
||||||
let expression_position = expression.position();
|
let position = expression.position();
|
||||||
let evaluation = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = evaluation {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -224,13 +272,13 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut property_map = BTreeMap::new();
|
let mut property_map = BTreeMap::new();
|
||||||
|
|
||||||
for (identifier, _type, expression) in property_list {
|
for (identifier, _type, expression) in property_list {
|
||||||
let expression_position = expression.position();
|
let position = expression.position();
|
||||||
let action = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -279,13 +327,13 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut fields = Vec::with_capacity(expressions.len());
|
let mut fields = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
for (identifier, expression) in expressions {
|
for (identifier, expression) in expressions {
|
||||||
let expression_position = expression.position();
|
let position = expression.position();
|
||||||
let action = expression.evaluate(context, _manage_memory)?;
|
let evaluation = expression.evaluate(context, _manage_memory)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Some(Evaluation::Return(value)) = evaluation {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(position),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -299,7 +347,7 @@ impl AbstractNode for ValueNode {
|
|||||||
Ok(Some(Evaluation::Return(value)))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
let r#type = match self {
|
let r#type = match self {
|
||||||
ValueNode::Boolean(_) => Type::Boolean,
|
ValueNode::Boolean(_) => Type::Boolean,
|
||||||
ValueNode::EnumInstance { type_name, .. } => {
|
ValueNode::EnumInstance { type_name, .. } => {
|
||||||
@ -314,11 +362,16 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
ValueNode::Float(_) => Type::Float,
|
ValueNode::Float(_) => Type::Float,
|
||||||
ValueNode::Integer(_) => Type::Integer,
|
ValueNode::Integer(_) => Type::Integer,
|
||||||
ValueNode::List(items) => {
|
ValueNode::List(expressions) => {
|
||||||
let item_type = items.first().unwrap().expected_type(context)?;
|
let first_item = expressions.first().unwrap();
|
||||||
|
let item_type = if let Some(r#type) = first_item.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(first_item.position()));
|
||||||
|
};
|
||||||
|
|
||||||
Type::List {
|
Type::List {
|
||||||
length: items.len(),
|
length: expressions.len(),
|
||||||
item_type: Box::new(item_type),
|
item_type: Box::new(item_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,14 +413,15 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut types = Vec::with_capacity(expressions.len());
|
let mut types = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
for (identifier, expression) in expressions {
|
for (identifier, expression) in expressions {
|
||||||
let r#type = expression.expected_type(context)?;
|
let r#type = if let Some(r#type) = expression.expected_type(context)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::ExpectedExpression(expression.position()));
|
||||||
|
};
|
||||||
|
|
||||||
types.push((
|
types.push((
|
||||||
identifier.clone(),
|
identifier.clone(),
|
||||||
WithPosition {
|
r#type.with_position(expression.position()),
|
||||||
node: r#type,
|
|
||||||
position: expression.position(),
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Evaluation, Expression, Statement, Type, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Statement, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct While {
|
pub struct While {
|
||||||
@ -24,12 +24,18 @@ impl While {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for While {
|
impl AbstractNode for While {
|
||||||
fn validate(
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
&self,
|
self.expression.define_types(_context)?;
|
||||||
_context: &mut Context,
|
|
||||||
_manage_memory: bool,
|
for statement in &self.statements {
|
||||||
) -> Result<(), ValidationError> {
|
statement.define_types(_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
self.expression.validate(_context, false)?;
|
self.expression.validate(_context, false)?;
|
||||||
|
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
@ -38,12 +44,10 @@ impl Validate for While {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractNode for While {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let get_boolean = || -> Result<Value, RuntimeError> {
|
let get_boolean = || -> Result<Value, RuntimeError> {
|
||||||
@ -57,7 +61,7 @@ impl AbstractNode for While {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression_position),
|
ValidationError::ExpectedExpression(expression_position),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -75,7 +79,7 @@ impl AbstractNode for While {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
self.statements.last().unwrap().expected_type(_context)
|
self.statements.last().unwrap().expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ impl<'a> Context<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_value(&mut self, identifier: Identifier, value: Value) -> Result<(), PoisonError> {
|
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), PoisonError> {
|
||||||
log::debug!("Setting {identifier} to value {value}.");
|
log::debug!("Setting {identifier} to value {value}.");
|
||||||
|
|
||||||
let mut variables = self.variables.write()?;
|
let mut variables = self.variables.write()?;
|
||||||
@ -136,7 +136,7 @@ impl<'a> Context<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clean(&mut self) -> Result<(), PoisonError> {
|
pub fn clean(&self) -> Result<(), PoisonError> {
|
||||||
if *self.is_clean.read()? {
|
if *self.is_clean.read()? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,6 @@ pub enum ValidationError {
|
|||||||
index_type: Type,
|
index_type: Type,
|
||||||
index_position: SourcePosition,
|
index_position: SourcePosition,
|
||||||
},
|
},
|
||||||
CannotIndexWithVoid(SourcePosition),
|
|
||||||
ExpectedString {
|
ExpectedString {
|
||||||
actual: Type,
|
actual: Type,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
@ -137,7 +136,7 @@ pub enum ValidationError {
|
|||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
},
|
},
|
||||||
InterpreterExpectedReturn(SourcePosition),
|
ExpectedExpression(SourcePosition),
|
||||||
RwLockPoison(PoisonError),
|
RwLockPoison(PoisonError),
|
||||||
TypeCheck {
|
TypeCheck {
|
||||||
/// The mismatch that caused the error.
|
/// The mismatch that caused the error.
|
||||||
|
@ -416,7 +416,7 @@ impl InterpreterError {
|
|||||||
.with_message(format!("This has type {}.", index_type.fg(type_color),)),
|
.with_message(format!("This has type {}.", index_type.fg(type_color),)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
ValidationError::InterpreterExpectedReturn(_) => todo!(),
|
ValidationError::ExpectedExpression(_) => todo!(),
|
||||||
ValidationError::ExpectedFunction { .. } => todo!(),
|
ValidationError::ExpectedFunction { .. } => todo!(),
|
||||||
ValidationError::ExpectedValue(_) => todo!(),
|
ValidationError::ExpectedValue(_) => todo!(),
|
||||||
ValidationError::PropertyNotFound { .. } => todo!(),
|
ValidationError::PropertyNotFound { .. } => todo!(),
|
||||||
@ -455,6 +455,7 @@ impl InterpreterError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValidationError::EnumVariantNotFound { .. } => todo!(),
|
ValidationError::EnumVariantNotFound { .. } => todo!(),
|
||||||
|
ValidationError::CannotIndexWithVoid(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ use serde::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Block, Evaluation, Type, WithPosition},
|
abstract_tree::{AbstractNode, Block, Evaluation, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
@ -725,8 +725,8 @@ impl Function {
|
|||||||
self,
|
self,
|
||||||
value_arguments: Vec<Value>,
|
value_arguments: Vec<Value>,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
clear_variables: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
for ((identifier, _), value) in self
|
for ((identifier, _), value) in self
|
||||||
.value_parameters
|
.value_parameters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -735,12 +735,6 @@ impl Function {
|
|||||||
context.set_value(identifier.clone(), value)?;
|
context.set_value(identifier.clone(), value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.body.run(context, clear_variables).map(|eval_option| {
|
self.body.evaluate(context, manage_memory)
|
||||||
if let Some(evaluation) = eval_option {
|
|
||||||
evaluation
|
|
||||||
} else {
|
|
||||||
Evaluation::Void
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user