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