Begin AbstractTree refactoring
This commit is contained in:
parent
d98f724355
commit
fb413e24b0
@ -9,7 +9,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct As {
|
pub struct As {
|
||||||
@ -26,35 +26,33 @@ impl As {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for As {
|
impl AbstractNode for As {
|
||||||
fn validate(
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
&self,
|
Ok(())
|
||||||
_context: &mut Context,
|
}
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
match self.constructor {
|
match self.constructor {
|
||||||
TypeConstructor::Raw(_) => {}
|
TypeConstructor::Raw(_) => {}
|
||||||
_ => todo!("Create an error for this occurence."),
|
_ => todo!("Create an error for this occurence."),
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.expression.expected_type(_context)? {
|
match self.expression.expected_type(_context)? {
|
||||||
Type::Boolean | Type::Float | Type::Integer | Type::String => {}
|
Some(Type::Boolean) | Some(Type::Float) | Some(Type::Integer) | Some(Type::String) => {}
|
||||||
_ => todo!("Create an error for this occurence."),
|
_ => todo!("Create an error for this occurence."),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Evaluate for As {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let expression_position = self.expression.position();
|
let expression_position = self.expression.position();
|
||||||
let action = self.expression.evaluate(context, _manage_memory)?;
|
let evaluation = self.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(
|
||||||
@ -70,12 +68,12 @@ impl Evaluate for As {
|
|||||||
_ => todo!("Create an error for this occurence."),
|
_ => todo!("Create an error for this occurence."),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Evaluation::Return(converted))
|
Ok(Some(Evaluation::Return(converted)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpectedType for As {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
|
self.constructor
|
||||||
self.constructor.clone().construct(&context)
|
.construct(&context)
|
||||||
|
.map(|r#type| Some(r#type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
type_constructor::{RawTypeConstructor, TypeInvokationConstructor},
|
||||||
Evaluation, ExpectedType, Expression, Run, Statement, Type, TypeConstructor, Validate,
|
AbstractNode, Evaluation, Expression, Statement, Type, TypeConstructor, WithPosition,
|
||||||
WithPosition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -44,8 +43,37 @@ impl Assignment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Assignment {
|
impl AbstractNode for Assignment {
|
||||||
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
|
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 {
|
||||||
|
return Err(ValidationError::CannotAssignToNone(
|
||||||
|
self.statement.position(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(constructor) = &self.constructor {
|
||||||
|
let r#type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
|
r#type
|
||||||
|
.check(&statement_type)
|
||||||
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
|
conflict,
|
||||||
|
actual_position: self.statement.position(),
|
||||||
|
expected_position: Some(constructor.position()),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
context.set_type(self.identifier.node.clone(), r#type.clone())?;
|
||||||
|
} else {
|
||||||
|
context.set_type(self.identifier.node.clone(), statement_type.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
if let Some(TypeConstructor::Raw(WithPosition {
|
if let Some(TypeConstructor::Raw(WithPosition {
|
||||||
node: RawTypeConstructor::None,
|
node: RawTypeConstructor::None,
|
||||||
position,
|
position,
|
||||||
@ -54,7 +82,7 @@ impl Validate for Assignment {
|
|||||||
return Err(ValidationError::CannotAssignToNone(position.clone()));
|
return Err(ValidationError::CannotAssignToNone(position.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let relevant_statement = self.statement.last_child_statement();
|
let relevant_statement = self.statement.last_evaluated_statement();
|
||||||
let statement_type = relevant_statement.expected_type(context)?;
|
let statement_type = relevant_statement.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Void = &statement_type {
|
if let Type::Void = &statement_type {
|
||||||
@ -137,12 +165,10 @@ impl Validate for Assignment {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Run for Assignment {
|
fn evaluate(
|
||||||
fn run(
|
|
||||||
self,
|
self,
|
||||||
context: &mut 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.run(context, manage_memory)?;
|
||||||
@ -249,4 +275,8 @@ impl Run for Assignment {
|
|||||||
|
|
||||||
Ok(Some(Evaluation::Void))
|
Ok(Some(Evaluation::Void))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluation, ExpectedType, Run, Statement, Type, 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 AsyncBlock {
|
pub struct AsyncBlock {
|
||||||
@ -21,20 +21,26 @@ impl AsyncBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for AsyncBlock {
|
impl AbstractNode for AsyncBlock {
|
||||||
fn validate(&self, _context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
for statement in &self.statements {
|
||||||
|
statement.define_types(_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, _context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
statement.validate(_context, manage_memory)?;
|
statement.validate(_context, manage_memory)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Run for AsyncBlock {
|
fn evaluate(
|
||||||
fn run(
|
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let statement_count = self.statements.len();
|
let statement_count = self.statements.len();
|
||||||
@ -61,10 +67,8 @@ impl Run for AsyncBlock {
|
|||||||
)
|
)
|
||||||
.unwrap_or(final_result.into_inner()?)
|
.unwrap_or(final_result.into_inner()?)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for AsyncBlock {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
self.statements.last().unwrap().expected_type(_context)
|
||||||
self.statements.first().unwrap().expected_type(_context)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluation, ExpectedType, Run, Statement, Type, 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 Block {
|
pub struct Block {
|
||||||
@ -26,24 +26,26 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Block {
|
impl AbstractNode for Block {
|
||||||
fn validate(
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
&self,
|
for statement in &self.statements {
|
||||||
_context: &mut Context,
|
statement.define_types(_context)?;
|
||||||
_manage_memory: bool,
|
}
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
statement.validate(_context, _manage_memory)?;
|
statement.validate(_context, _manage_memory)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Run for Block {
|
fn evaluate(
|
||||||
fn run(
|
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let mut previous = None;
|
let mut previous = None;
|
||||||
@ -54,10 +56,8 @@ impl Run for Block {
|
|||||||
|
|
||||||
Ok(previous)
|
Ok(previous)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for Block {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
self.last_statement().expected_type(_context)
|
self.last_statement().expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum BuiltInFunctionCall {
|
pub enum BuiltInFunctionCall {
|
||||||
@ -25,13 +25,12 @@ pub enum BuiltInFunctionCall {
|
|||||||
Sleep(Expression),
|
Sleep(Expression),
|
||||||
WriteLine(Expression),
|
WriteLine(Expression),
|
||||||
}
|
}
|
||||||
|
impl AbstractNode for BuiltInFunctionCall {
|
||||||
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for BuiltInFunctionCall {
|
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
fn validate(
|
|
||||||
&self,
|
|
||||||
_context: &mut Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<(), ValidationError> {
|
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::JsonParse(_, expression) => {
|
BuiltInFunctionCall::JsonParse(_, expression) => {
|
||||||
expression.validate(_context, _manage_memory)
|
expression.validate(_context, _manage_memory)
|
||||||
@ -49,14 +48,12 @@ impl Validate for BuiltInFunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Evaluate for BuiltInFunctionCall {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::JsonParse(_type, expression) => {
|
BuiltInFunctionCall::JsonParse(_type, expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let action = expression.clone().evaluate(context, _manage_memory)?;
|
||||||
@ -71,7 +68,7 @@ impl Evaluate for BuiltInFunctionCall {
|
|||||||
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(Evaluation::Return(deserialized))
|
Ok(Some(Evaluation::Return(deserialized)))
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::ExpectedString {
|
ValidationError::ExpectedString {
|
||||||
@ -96,7 +93,7 @@ impl Evaluate for BuiltInFunctionCall {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(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 action = expression.clone().evaluate(context, _manage_memory)?;
|
||||||
@ -113,16 +110,16 @@ impl Evaluate for BuiltInFunctionCall {
|
|||||||
String::with_capacity(0)
|
String::with_capacity(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Evaluation::Return(Value::string(file_contents)))
|
Ok(Some(Evaluation::Return(Value::string(file_contents))))
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::ReadLine => {
|
BuiltInFunctionCall::ReadLine => {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
|
|
||||||
stdin().read_line(&mut buffer)?;
|
stdin().read_line(&mut buffer)?;
|
||||||
|
|
||||||
Ok(Evaluation::Return(Value::string(
|
Ok(Some(Evaluation::Return(Value::string(
|
||||||
buffer.strip_suffix('\n').unwrap_or(&buffer),
|
buffer.strip_suffix('\n').unwrap_or(&buffer),
|
||||||
)))
|
))))
|
||||||
}
|
}
|
||||||
BuiltInFunctionCall::Sleep(expression) => {
|
BuiltInFunctionCall::Sleep(expression) => {
|
||||||
let action = expression.clone().evaluate(context, _manage_memory)?;
|
let action = expression.clone().evaluate(context, _manage_memory)?;
|
||||||
@ -162,17 +159,17 @@ impl Evaluate for BuiltInFunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for BuiltInFunctionCall {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunctionCall::JsonParse(r#type, _) => Ok(r#type.clone().construct(&context)?),
|
BuiltInFunctionCall::JsonParse(r#type, _) => {
|
||||||
BuiltInFunctionCall::Length(_) => Ok(Type::Integer),
|
Ok(Some(r#type.clone().construct(&context)?))
|
||||||
BuiltInFunctionCall::ReadFile(_) => Ok(Type::String),
|
}
|
||||||
BuiltInFunctionCall::ReadLine => Ok(Type::String),
|
BuiltInFunctionCall::Length(_) => Ok(Some(Type::Integer)),
|
||||||
BuiltInFunctionCall::Sleep(_) => Ok(Type::Void),
|
BuiltInFunctionCall::ReadFile(_) => Ok(Some(Type::String)),
|
||||||
BuiltInFunctionCall::WriteLine(_) => Ok(Type::Void),
|
BuiltInFunctionCall::ReadLine => Ok(Some(Type::String)),
|
||||||
|
BuiltInFunctionCall::Sleep(_) => Ok(None),
|
||||||
|
BuiltInFunctionCall::WriteLine(_) => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
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::{Evaluation, Run, 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 EnumDeclaration {
|
pub struct EnumDeclaration {
|
||||||
@ -25,12 +29,8 @@ impl EnumDeclaration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for EnumDeclaration {
|
impl AbstractNode for EnumDeclaration {
|
||||||
fn run(
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
self,
|
|
||||||
context: &mut Context,
|
|
||||||
_manage_memory: bool,
|
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
|
||||||
let EnumDeclaration {
|
let EnumDeclaration {
|
||||||
name,
|
name,
|
||||||
type_parameters,
|
type_parameters,
|
||||||
@ -74,6 +74,29 @@ impl Run for EnumDeclaration {
|
|||||||
|
|
||||||
context.set_type(name.node, r#type)?;
|
context.set_type(name.node, r#type)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(
|
||||||
|
&self,
|
||||||
|
context: &Context,
|
||||||
|
manage_memory: bool,
|
||||||
|
) -> Result<(), crate::error::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>, crate::error::ValidationError> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
As, BuiltInFunctionCall, Evaluate, Evaluation, ExpectedType, FunctionCall, ListIndex, Logic,
|
AbstractNode, As, BuiltInFunctionCall, Evaluation, FunctionCall, ListIndex, Logic, MapIndex,
|
||||||
MapIndex, Math, SourcePosition, Type, Validate, ValueNode, WithPosition,
|
Math, SourcePosition, Type, ValueNode, WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -40,8 +40,22 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Expression {
|
impl AbstractNode for Expression {
|
||||||
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
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::MapIndex(inner) => inner.node.define_types(_context),
|
||||||
|
Expression::ListIndex(inner) => inner.node.define_types(_context),
|
||||||
|
Expression::Logic(inner) => inner.node.define_types(_context),
|
||||||
|
Expression::Math(inner) => inner.node.define_types(_context),
|
||||||
|
Expression::Value(inner) => inner.node.define_types(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Expression::As(r#as) => r#as.node.validate(context, manage_memory),
|
Expression::As(r#as) => r#as.node.validate(context, manage_memory),
|
||||||
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
Expression::BuiltInFunctionCall(built_in_function_call) => {
|
||||||
@ -73,14 +87,12 @@ impl Validate for Expression {
|
|||||||
Expression::Value(value_node) => value_node.node.validate(context, manage_memory),
|
Expression::Value(value_node) => value_node.node.validate(context, manage_memory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Evaluate for Expression {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
match self {
|
match self {
|
||||||
Expression::As(r#as) => r#as.node.evaluate(context, manage_memory),
|
Expression::As(r#as) => r#as.node.evaluate(context, manage_memory),
|
||||||
Expression::FunctionCall(function_call) => {
|
Expression::FunctionCall(function_call) => {
|
||||||
@ -94,7 +106,7 @@ impl Evaluate for Expression {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(value) = value_option {
|
if let Some(value) = value_option {
|
||||||
Ok(Evaluation::Return(value))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::VariableNotFound {
|
ValidationError::VariableNotFound {
|
||||||
@ -114,21 +126,21 @@ impl Evaluate for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for Expression {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
match self {
|
match self {
|
||||||
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) => {
|
||||||
if let Some(r#type) = _context.get_type(&identifier.node)? {
|
let get_type = _context.get_type(identifier)?;
|
||||||
Ok(r#type)
|
|
||||||
} else {
|
if get_type.is_none() {
|
||||||
Err(ValidationError::VariableNotFound {
|
Err(ValidationError::VariableNotFound {
|
||||||
identifier: identifier.node.clone(),
|
identifier: identifier.node.clone(),
|
||||||
position: identifier.position,
|
position: identifier.position,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Ok(get_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
|
Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
@ -33,8 +33,20 @@ impl FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for FunctionCall {
|
impl AbstractNode for FunctionCall {
|
||||||
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
self.function.define_ypes(_context)?;
|
||||||
|
|
||||||
|
let mut previous = ();
|
||||||
|
|
||||||
|
for expression in &self.value_arguments {
|
||||||
|
previous = expression.define_types(_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(previous)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
self.function.validate(context, manage_memory)?;
|
self.function.validate(context, manage_memory)?;
|
||||||
|
|
||||||
for expression in &self.value_arguments {
|
for expression in &self.value_arguments {
|
||||||
@ -69,14 +81,12 @@ impl Validate for FunctionCall {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Evaluate for FunctionCall {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
clear_variables: bool,
|
clear_variables: bool,
|
||||||
) -> Result<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 action = self.function.evaluate(context, clear_variables)?;
|
||||||
let value = if let Evaluation::Return(value) = action {
|
let value = if let Evaluation::Return(value) = action {
|
||||||
@ -131,10 +141,8 @@ impl Evaluate for FunctionCall {
|
|||||||
.clone()
|
.clone()
|
||||||
.call(arguments, &mut function_context, clear_variables)
|
.call(arguments, &mut function_context, clear_variables)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for FunctionCall {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
let function_node_type = self.function.expected_type(context)?;
|
let function_node_type = self.function.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Function {
|
if let Type::Function {
|
||||||
@ -157,10 +165,10 @@ impl ExpectedType for FunctionCall {
|
|||||||
if identifier == &return_identifier {
|
if identifier == &return_identifier {
|
||||||
let concrete_type = constructor.clone().construct(&context)?;
|
let concrete_type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
return Ok(Type::Generic {
|
return Ok(Some(Type::Generic {
|
||||||
identifier: identifier.clone(),
|
identifier: identifier.clone(),
|
||||||
concrete_type: Some(Box::new(concrete_type)),
|
concrete_type: Some(Box::new(concrete_type)),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,16 +181,16 @@ impl ExpectedType for FunctionCall {
|
|||||||
if identifier == return_identifier {
|
if identifier == return_identifier {
|
||||||
let concrete_type = expression.expected_type(context)?;
|
let concrete_type = expression.expected_type(context)?;
|
||||||
|
|
||||||
return Ok(Type::Generic {
|
return Ok(Some(Type::Generic {
|
||||||
identifier,
|
identifier,
|
||||||
concrete_type: Some(Box::new(concrete_type)),
|
concrete_type: Some(Box::new(concrete_type)),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(*return_type)
|
Ok(Some(*return_type))
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
actual: function_node_type,
|
actual: function_node_type,
|
||||||
|
@ -6,9 +6,7 @@ use crate::{
|
|||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{AbstractNode, Block, Evaluation, Expression, Type, WithPosition};
|
||||||
Block, Evaluate, Evaluation, ExpectedType, Expression, Run, Type, Validate, WithPosition,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct IfElse {
|
pub struct IfElse {
|
||||||
@ -34,8 +32,26 @@ impl IfElse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for IfElse {
|
impl AbstractNode for IfElse {
|
||||||
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
self.if_expression.define_types(_context)?;
|
||||||
|
self.if_block.define_type(_context)?;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
else_block.node.define_types(_context)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
|
||||||
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)?;
|
||||||
|
|
||||||
@ -90,12 +106,10 @@ impl Validate for IfElse {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Run for IfElse {
|
fn evaluate(
|
||||||
fn run(
|
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
_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();
|
||||||
@ -154,10 +168,8 @@ impl Run for IfElse {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for IfElse {
|
fn expected_type(&self, _context: &Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
self.if_block.node.expected_type(_context)
|
self.if_block.node.expected_type(_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{AbstractNode, Evaluation, Expression, Type, Validate, ValueNode, WithPosition};
|
||||||
Evaluate, Evaluation, ExpectedType, Expression, Type, Validate, 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 {
|
||||||
@ -32,12 +30,16 @@ impl Validate for ListIndex {
|
|||||||
let collection_type = self.collection.expected_type(context)?;
|
let collection_type = self.collection.expected_type(context)?;
|
||||||
let index_type = self.index.expected_type(context)?;
|
let index_type = self.index.expected_type(context)?;
|
||||||
|
|
||||||
|
if index_type.is_none() {
|
||||||
|
return Err(ValidationError::CannotIndexWithVoid(self.index.position()));
|
||||||
|
}
|
||||||
|
|
||||||
match collection_type {
|
match collection_type {
|
||||||
Type::List {
|
Type::List {
|
||||||
length: _,
|
length: _,
|
||||||
item_type: _,
|
item_type: _,
|
||||||
} => {
|
} => {
|
||||||
if index_type == Type::Integer {
|
if index_type == Some(Type::Integer) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::CannotIndexWith {
|
Err(ValidationError::CannotIndexWith {
|
||||||
@ -57,12 +59,12 @@ impl Validate for ListIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluate for ListIndex {
|
impl AbstractNode for ListIndex {
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_clear_variables: bool,
|
_clear_variables: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let left_position = self.collection.position();
|
let left_position = self.collection.position();
|
||||||
let left_action = self.collection.evaluate(context, _clear_variables)?;
|
let left_action = self.collection.evaluate(context, _clear_variables)?;
|
||||||
let left_value = if let Evaluation::Return(value) = left_action {
|
let left_value = if let Evaluation::Return(value) = left_action {
|
||||||
@ -86,7 +88,7 @@ impl Evaluate for ListIndex {
|
|||||||
let found_item = list.get(index as usize);
|
let found_item = list.get(index as usize);
|
||||||
|
|
||||||
if let Some(item) = found_item {
|
if let Some(item) = found_item {
|
||||||
Ok(Evaluation::Return(item.clone()))
|
Ok(Some(Evaluation::Return(item.clone())))
|
||||||
} else {
|
} else {
|
||||||
Ok(Evaluation::Void)
|
Ok(Evaluation::Void)
|
||||||
}
|
}
|
||||||
@ -101,10 +103,8 @@ impl Evaluate for ListIndex {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for ListIndex {
|
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<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::{Evaluate, Evaluation, ExpectedType, Expression, Type, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Type, Validate};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Logic {
|
pub enum Logic {
|
||||||
@ -90,12 +90,12 @@ impl Validate for Logic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluate for Logic {
|
impl AbstractNode for Logic {
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<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> {
|
||||||
let expression_position = expression.position();
|
let expression_position = expression.position();
|
||||||
let action = expression.evaluate(&mut context.clone(), _manage_memory)?;
|
let action = expression.evaluate(&mut context.clone(), _manage_memory)?;
|
||||||
@ -193,13 +193,11 @@ impl Evaluate for Logic {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Evaluation::Return(Value::boolean(boolean)))
|
Ok(Some(Evaluation::Return(Value::boolean(boolean))))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpectedType for Logic {
|
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
Ok(Some(Type::Boolean))
|
||||||
Ok(Type::Boolean)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluation, Run, Statement, Validate};
|
use super::{AbstractNode, Evaluation, Statement, Validate};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct Loop {
|
pub struct Loop {
|
||||||
@ -36,8 +36,8 @@ impl Validate for Loop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for Loop {
|
impl AbstractNode for Loop {
|
||||||
fn run(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
@ -52,4 +52,11 @@ impl Run for Loop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(
|
||||||
|
&self,
|
||||||
|
_context: &mut Context,
|
||||||
|
) -> Result<Option<super::Type>, ValidationError> {
|
||||||
|
self.last_statement().expected_type(_context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@ use crate::{
|
|||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{AbstractNode, Evaluation, Expression, Type, Validate, ValueNode, WithPosition};
|
||||||
Evaluate, Evaluation, ExpectedType, Expression, Type, Validate, 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 {
|
||||||
@ -35,12 +33,12 @@ impl Validate for MapIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluate for MapIndex {
|
impl AbstractNode for MapIndex {
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let collection_position = self.collection.position();
|
let collection_position = self.collection.position();
|
||||||
let action = self.collection.evaluate(context, _manage_memory)?;
|
let action = self.collection.evaluate(context, _manage_memory)?;
|
||||||
let collection = if let Evaluation::Return(value) = action {
|
let collection = if let Evaluation::Return(value) = action {
|
||||||
@ -54,12 +52,11 @@ impl Evaluate for MapIndex {
|
|||||||
if let (ValueInner::Map(map), Expression::Identifier(index)) =
|
if let (ValueInner::Map(map), Expression::Identifier(index)) =
|
||||||
(collection.inner().as_ref(), self.index)
|
(collection.inner().as_ref(), self.index)
|
||||||
{
|
{
|
||||||
let action = map
|
let evaluation = map
|
||||||
.get(&index.node)
|
.get(&index.node)
|
||||||
.map(|value| Evaluation::Return(value.clone()))
|
.map(|value| Some(Evaluation::Return(value.clone())));
|
||||||
.unwrap_or(Evaluation::Void);
|
|
||||||
|
|
||||||
Ok(action)
|
Ok(evaluation)
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::ValidationFailure(
|
Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::CannotIndex {
|
ValidationError::CannotIndex {
|
||||||
@ -69,10 +66,8 @@ impl Evaluate for MapIndex {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ExpectedType for MapIndex {
|
fn expected_type(&self, context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<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)
|
||||||
{
|
{
|
||||||
@ -87,7 +82,7 @@ impl ExpectedType for MapIndex {
|
|||||||
|
|
||||||
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
if let ValueInner::Map(map) = collection.inner().as_ref() {
|
||||||
return if let Some(value) = map.get(&index.node) {
|
return if let Some(value) = map.get(&index.node) {
|
||||||
Ok(value.r#type(context)?)
|
Ok(Some(value.r#type(context)?))
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::PropertyNotFound {
|
Err(ValidationError::PropertyNotFound {
|
||||||
identifier: index.node.clone(),
|
identifier: index.node.clone(),
|
||||||
@ -110,9 +105,9 @@ impl ExpectedType for MapIndex {
|
|||||||
return if let Some(constructor) = constructor_option {
|
return if let Some(constructor) = constructor_option {
|
||||||
let r#type = constructor.clone().construct(&context)?;
|
let r#type = constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
Ok(r#type)
|
Ok(Some(r#type))
|
||||||
} else {
|
} else {
|
||||||
Ok(expression.expected_type(context)?)
|
expression.expected_type(context)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluate, Evaluation, ExpectedType, Expression, SourcePosition, Type, Validate};
|
use super::{AbstractNode, Evaluation, Expression, SourcePosition, Type, Validate};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Math {
|
pub enum Math {
|
||||||
@ -68,12 +68,12 @@ impl Validate for Math {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluate for Math {
|
impl AbstractNode for Math {
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &mut Context,
|
||||||
_clear_variables: bool,
|
_clear_variables: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let run_and_expect_value =
|
let run_and_expect_value =
|
||||||
|position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> {
|
|position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> {
|
||||||
let action = expression.evaluate(&mut _context.clone(), _clear_variables)?;
|
let action = expression.evaluate(&mut _context.clone(), _clear_variables)?;
|
||||||
@ -293,12 +293,10 @@ impl Evaluate for Math {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Evaluation::Return(value))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpectedType for Math {
|
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
match self {
|
match self {
|
||||||
Math::Add(left, right)
|
Math::Add(left, right)
|
||||||
| Math::Subtract(left, right)
|
| Math::Subtract(left, right)
|
||||||
@ -309,11 +307,11 @@ impl ExpectedType for Math {
|
|||||||
let right_type = right.expected_type(_context)?;
|
let right_type = right.expected_type(_context)?;
|
||||||
|
|
||||||
if let Type::Float = left_type {
|
if let Type::Float = left_type {
|
||||||
return Ok(Type::Float);
|
return Ok(Some(Type::Float));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Type::Float = right_type {
|
if let Type::Float = right_type {
|
||||||
return Ok(Type::Float);
|
return Ok(Some(Type::Float));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(left_type)
|
Ok(left_type)
|
||||||
|
@ -94,7 +94,6 @@ pub enum Evaluation {
|
|||||||
Break,
|
Break,
|
||||||
Continue,
|
Continue,
|
||||||
Return(Value),
|
Return(Value),
|
||||||
Void,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -116,10 +115,37 @@ impl AbstractTree {
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Value>, Vec<DustError>> {
|
) -> Result<Option<Value>, Vec<DustError>> {
|
||||||
let valid_statements = self.validate(context, manage_memory)?;
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
|
for statement in &self.0 {
|
||||||
|
let define_result = statement.define_types(context);
|
||||||
|
|
||||||
|
if let Err(error) = define_result {
|
||||||
|
errors.push(DustError::Validation {
|
||||||
|
error,
|
||||||
|
position: statement.position(),
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let validation_result = statement.validate(context, manage_memory);
|
||||||
|
|
||||||
|
if let Err(error) = validation_result {
|
||||||
|
errors.push(DustError::Validation {
|
||||||
|
error,
|
||||||
|
position: statement.position(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !errors.is_empty() {
|
||||||
|
return Err(errors);
|
||||||
|
}
|
||||||
|
|
||||||
let mut previous_value = None;
|
let mut previous_value = None;
|
||||||
|
|
||||||
for statement in valid_statements {
|
for statement in self.0 {
|
||||||
let position = statement.position();
|
let position = statement.position();
|
||||||
let run = statement.run(context, manage_memory);
|
let run = statement.run(context, manage_memory);
|
||||||
|
|
||||||
@ -140,50 +166,6 @@ impl AbstractTree {
|
|||||||
|
|
||||||
Ok(previous_value)
|
Ok(previous_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(
|
|
||||||
self,
|
|
||||||
context: &mut Context,
|
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Vec<Statement>, Vec<DustError>> {
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
let mut valid_statements = Vec::new();
|
|
||||||
|
|
||||||
for statement in self.0 {
|
|
||||||
let validation = statement.validate(context, manage_memory);
|
|
||||||
|
|
||||||
if let Err(validation_error) = validation {
|
|
||||||
errors.push(DustError::Validation {
|
|
||||||
error: validation_error,
|
|
||||||
position: statement.position(),
|
|
||||||
})
|
|
||||||
} else if errors.is_empty() {
|
|
||||||
if let Statement::StructureDefinition(_) = statement {
|
|
||||||
let position = statement.position();
|
|
||||||
let run = statement.run(context, true);
|
|
||||||
|
|
||||||
if let Err(runtime_error) = run {
|
|
||||||
errors.push(DustError::Runtime {
|
|
||||||
error: runtime_error,
|
|
||||||
position,
|
|
||||||
});
|
|
||||||
|
|
||||||
return Err(errors);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
valid_statements.push(statement)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if errors.is_empty() {
|
|
||||||
Ok(valid_statements)
|
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for AbstractTree {
|
impl Index<usize> for AbstractTree {
|
||||||
@ -194,26 +176,16 @@ impl Index<usize> for AbstractTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Validate {
|
pub trait AbstractNode {
|
||||||
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError>;
|
fn define_types(&self, context: &Context) -> Result<(), ValidationError>;
|
||||||
}
|
|
||||||
|
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>;
|
||||||
|
|
||||||
pub trait Evaluate: ExpectedType {
|
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &Context,
|
||||||
manage_memory: bool,
|
|
||||||
) -> Result<Evaluation, RuntimeError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Run {
|
|
||||||
fn run(
|
|
||||||
self,
|
|
||||||
context: &mut Context,
|
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError>;
|
) -> Result<Option<Evaluation>, RuntimeError>;
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ExpectedType {
|
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError>;
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError>;
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Assignment, AsyncBlock, Block, EnumDeclaration, Evaluate, Evaluation, ExpectedType, Expression,
|
AbstractNode, Assignment, AsyncBlock, Block, DefineTypes, EnumDeclaration, Evaluation,
|
||||||
IfElse, Loop, Run, SourcePosition, StructureDefinition, Type, TypeAlias, Validate, While,
|
Expression, IfElse, Loop, SourcePosition, StructureDefinition, Type, TypeAlias, Validate,
|
||||||
WithPosition,
|
While, WithPosition,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
@ -43,7 +43,7 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_child_statement(&self) -> &Self {
|
pub fn last_evaluated_statement(&self) -> &Self {
|
||||||
match self {
|
match self {
|
||||||
Statement::Block(inner) => inner.node.last_statement(),
|
Statement::Block(inner) => inner.node.last_statement(),
|
||||||
Statement::Loop(inner) => inner.node.last_statement(),
|
Statement::Loop(inner) => inner.node.last_statement(),
|
||||||
@ -52,30 +52,50 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for Statement {
|
impl DefineTypes for Statement {
|
||||||
fn run(
|
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
|
match self {
|
||||||
|
Statement::Expression(expression) => expression.define_types(_context),
|
||||||
|
Statement::IfElse(if_else) => if_else.node.define_types(_context),
|
||||||
|
Statement::Block(block) => block.node.define_types(_context),
|
||||||
|
Statement::AsyncBlock(async_block) => async_block.node.define_types(_context),
|
||||||
|
Statement::Assignment(assignment) => assignment.node.define_types(_context),
|
||||||
|
Statement::Break(_) => Ok(None),
|
||||||
|
Statement::Loop(r#loop) => r#loop.node.define_types(_context),
|
||||||
|
Statement::StructureDefinition(struct_definition) => {
|
||||||
|
struct_definition.node.define_types(_context)
|
||||||
|
}
|
||||||
|
Statement::TypeAlias(type_alias) => type_alias.node.define_types(_context),
|
||||||
|
Statement::EnumDeclaration(enum_declaration) => {
|
||||||
|
enum_declaration.node.define_types(_context)
|
||||||
|
}
|
||||||
|
Statement::While(r#while) => r#while.node.define_types(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractNode for Statement {
|
||||||
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let result = match self {
|
let result = match self {
|
||||||
Statement::Assignment(assignment) => assignment.node.run(context, manage_memory),
|
Statement::Assignment(assignment) => assignment.node.evaluate(context, manage_memory),
|
||||||
Statement::AsyncBlock(async_block) => async_block.node.run(context, manage_memory),
|
Statement::AsyncBlock(async_block) => async_block.node.evaluate(context, manage_memory),
|
||||||
Statement::Block(block) => block.node.run(context, manage_memory),
|
Statement::Block(block) => block.node.evaluate(context, manage_memory),
|
||||||
Statement::Break(_) => Ok(Some(Evaluation::Break)),
|
Statement::Break(_) => Ok(Some(Evaluation::Break)),
|
||||||
Statement::Expression(expression) => {
|
Statement::Expression(expression) => expression.evaluate(context, manage_memory),
|
||||||
let evaluation = expression.evaluate(context, manage_memory)?;
|
Statement::IfElse(if_else) => if_else.node.evaluate(context, manage_memory),
|
||||||
|
Statement::Loop(r#loop) => r#loop.node.evaluate(context, manage_memory),
|
||||||
Ok(Some(evaluation))
|
|
||||||
}
|
|
||||||
Statement::IfElse(if_else) => if_else.node.run(context, manage_memory),
|
|
||||||
Statement::Loop(r#loop) => r#loop.node.run(context, manage_memory),
|
|
||||||
Statement::StructureDefinition(structure_definition) => {
|
Statement::StructureDefinition(structure_definition) => {
|
||||||
structure_definition.node.run(context, manage_memory)
|
structure_definition.node.evaluate(context, manage_memory)
|
||||||
}
|
}
|
||||||
Statement::TypeAlias(type_alias) => type_alias.node.run(context, manage_memory),
|
Statement::TypeAlias(type_alias) => type_alias.node.evaluate(context, manage_memory),
|
||||||
Statement::EnumDeclaration(type_alias) => type_alias.node.run(context, manage_memory),
|
Statement::EnumDeclaration(type_alias) => {
|
||||||
Statement::While(r#while) => r#while.node.run(context, manage_memory),
|
type_alias.node.evaluate(context, manage_memory)
|
||||||
|
}
|
||||||
|
Statement::While(r#while) => r#while.node.evaluate(context, manage_memory),
|
||||||
};
|
};
|
||||||
|
|
||||||
if manage_memory {
|
if manage_memory {
|
||||||
@ -84,6 +104,26 @@ impl Run for Statement {
|
|||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
match self {
|
||||||
|
Statement::Expression(expression) => expression.expected_type(_context),
|
||||||
|
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
|
||||||
|
Statement::Block(block) => block.node.expected_type(_context),
|
||||||
|
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
|
||||||
|
Statement::Assignment(assignment) => assignment.node.expected_type(_context),
|
||||||
|
Statement::Break(_) => Ok(None),
|
||||||
|
Statement::Loop(r#loop) => r#loop.node.expected_type(_context),
|
||||||
|
Statement::StructureDefinition(struct_definition) => {
|
||||||
|
struct_definition.node.expected_type(_context)
|
||||||
|
}
|
||||||
|
Statement::TypeAlias(type_alias) => type_alias.node.expected_type(_context),
|
||||||
|
Statement::EnumDeclaration(enum_declaration) => {
|
||||||
|
enum_declaration.node.expected_type(_context)
|
||||||
|
}
|
||||||
|
Statement::While(r#while) => r#while.node.expected_type(_context),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validate for Statement {
|
impl Validate for Statement {
|
||||||
@ -107,15 +147,3 @@ impl Validate for Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpectedType for Statement {
|
|
||||||
fn expected_type(&self, _context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
match self {
|
|
||||||
Statement::Expression(expression) => expression.expected_type(_context),
|
|
||||||
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
|
|
||||||
Statement::Block(block) => block.node.expected_type(_context),
|
|
||||||
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
|
|
||||||
_ => Ok(Type::Void),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{context::Context, error::RuntimeError, identifier::Identifier};
|
use crate::{context::Context, error::RuntimeError, identifier::Identifier};
|
||||||
|
|
||||||
use super::{Evaluation, Run, Type, TypeConstructor};
|
use super::{AbstractNode, Evaluation, Type, TypeConstructor};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct StructureDefinition {
|
pub struct StructureDefinition {
|
||||||
@ -16,8 +16,8 @@ impl StructureDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for StructureDefinition {
|
impl AbstractNode for StructureDefinition {
|
||||||
fn run(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
@ -39,4 +39,11 @@ impl Run for StructureDefinition {
|
|||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(
|
||||||
|
&self,
|
||||||
|
context: &mut Context,
|
||||||
|
) -> Result<Option<Type>, crate::error::ValidationError> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@ pub enum Type {
|
|||||||
name: Identifier,
|
name: Identifier,
|
||||||
fields: Vec<(Identifier, Type)>,
|
fields: Vec<(Identifier, Type)>,
|
||||||
},
|
},
|
||||||
Void,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
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::{Evaluation, Run, TypeConstructor, WithPosition};
|
use super::{AbstractNode, DefineTypes, 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 {
|
||||||
@ -19,16 +23,26 @@ impl TypeAlias {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for TypeAlias {
|
impl AbstractNode for TypeAlias {
|
||||||
fn run(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_manage_memory: bool,
|
manage_memory: bool,
|
||||||
) -> Result<Option<Evaluation>, RuntimeError> {
|
) -> 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)?;
|
let r#type = self.constructor.construct(&context)?;
|
||||||
|
|
||||||
context.set_type(self.identifier.node, r#type)?;
|
context.set_type(self.identifier.node, r#type)?;
|
||||||
|
|
||||||
Ok(None)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,14 +52,14 @@ impl TypeConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construct(self, context: &Context) -> Result<Type, ValidationError> {
|
pub fn construct(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||||
let r#type = match self {
|
let r#type = match self {
|
||||||
TypeConstructor::Invokation(TypeInvokationConstructor { identifier, .. }) => {
|
TypeConstructor::Invokation(TypeInvokationConstructor { identifier, .. }) => {
|
||||||
let invoked_type = if let Some(r#type) = context.get_type(&identifier.node)? {
|
let invoked_type = if let Some(r#type) = context.get_type(&identifier.node)? {
|
||||||
r#type
|
r#type
|
||||||
} else {
|
} else {
|
||||||
return Err(ValidationError::VariableNotFound {
|
return Err(ValidationError::VariableNotFound {
|
||||||
identifier: identifier.node,
|
identifier: identifier.node.clone(),
|
||||||
position: identifier.position,
|
position: identifier.position,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -90,7 +90,7 @@ impl TypeConstructor {
|
|||||||
name,
|
name,
|
||||||
type_parameters,
|
type_parameters,
|
||||||
variants,
|
variants,
|
||||||
} = enum_type_constructor.node;
|
} = &enum_type_constructor.node;
|
||||||
let mut type_variants = Vec::with_capacity(variants.len());
|
let mut type_variants = Vec::with_capacity(variants.len());
|
||||||
|
|
||||||
for (variant_name, constructors) in variants {
|
for (variant_name, constructors) in variants {
|
||||||
@ -103,19 +103,19 @@ impl TypeConstructor {
|
|||||||
types.push(r#type);
|
types.push(r#type);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_variants.push((variant_name.node, Some(types)));
|
type_variants.push((variant_name.node.clone(), Some(types)));
|
||||||
} else {
|
} else {
|
||||||
type_variants.push((variant_name.node, None))
|
type_variants.push((variant_name.node.clone(), None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Enum {
|
Type::Enum {
|
||||||
name: name.node,
|
name: name.node.clone(),
|
||||||
type_parameters: type_parameters.map(|identifiers| {
|
type_parameters: type_parameters.as_ref().map(|identifiers| {
|
||||||
identifiers
|
identifiers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|identifier| Type::Generic {
|
.map(|identifier| Type::Generic {
|
||||||
identifier: identifier.node,
|
identifier: identifier.node.clone(),
|
||||||
concrete_type: None,
|
concrete_type: None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@ -128,12 +128,12 @@ impl TypeConstructor {
|
|||||||
type_parameters: declared_type_parameters,
|
type_parameters: declared_type_parameters,
|
||||||
value_parameters: declared_value_parameters,
|
value_parameters: declared_value_parameters,
|
||||||
return_type,
|
return_type,
|
||||||
} = function_type_constructor.node;
|
} = &function_type_constructor.node;
|
||||||
|
|
||||||
let type_parameters = declared_type_parameters.map(|identifiers| {
|
let type_parameters = declared_type_parameters.as_ref().map(|identifiers| {
|
||||||
identifiers
|
identifiers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|identifier| identifier.node)
|
.map(|identifier| identifier.node.clone())
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
let mut value_parameters = Vec::with_capacity(declared_value_parameters.len());
|
let mut value_parameters = Vec::with_capacity(declared_value_parameters.len());
|
||||||
@ -153,11 +153,11 @@ impl TypeConstructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeConstructor::List(constructor) => {
|
TypeConstructor::List(constructor) => {
|
||||||
let ListTypeConstructor { length, item_type } = constructor.node;
|
let ListTypeConstructor { length, item_type } = &constructor.node;
|
||||||
let constructed_type = item_type.construct(context)?;
|
let constructed_type = item_type.construct(context)?;
|
||||||
|
|
||||||
Type::List {
|
Type::List {
|
||||||
length,
|
length: *length,
|
||||||
item_type: Box::new(constructed_type),
|
item_type: Box::new(constructed_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Block, Evaluate, Evaluation, ExpectedType, Expression, Type, TypeConstructor, Validate,
|
AbstractNode, Block, Evaluation, Expression, Type, TypeConstructor, Validate, WithPosition,
|
||||||
WithPosition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -165,12 +164,12 @@ impl Validate for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evaluate for ValueNode {
|
impl AbstractNode for ValueNode {
|
||||||
fn evaluate(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
) -> Result<Evaluation, RuntimeError> {
|
) -> Result<Option<Evaluation>, RuntimeError> {
|
||||||
let value = match self {
|
let value = match self {
|
||||||
ValueNode::Boolean(boolean) => Value::boolean(boolean),
|
ValueNode::Boolean(boolean) => Value::boolean(boolean),
|
||||||
ValueNode::EnumInstance {
|
ValueNode::EnumInstance {
|
||||||
@ -297,7 +296,92 @@ impl Evaluate for ValueNode {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Evaluation::Return(value))
|
Ok(Some(Evaluation::Return(value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
let r#type = match self {
|
||||||
|
ValueNode::Boolean(_) => Type::Boolean,
|
||||||
|
ValueNode::EnumInstance { type_name, .. } => {
|
||||||
|
if let Some(r#type) = context.get_type(&type_name.node)? {
|
||||||
|
r#type
|
||||||
|
} else {
|
||||||
|
return Err(ValidationError::EnumDefinitionNotFound {
|
||||||
|
identifier: type_name.node.clone(),
|
||||||
|
position: Some(type_name.position),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Float(_) => Type::Float,
|
||||||
|
ValueNode::Integer(_) => Type::Integer,
|
||||||
|
ValueNode::List(items) => {
|
||||||
|
let item_type = items.first().unwrap().expected_type(context)?;
|
||||||
|
|
||||||
|
Type::List {
|
||||||
|
length: items.len(),
|
||||||
|
item_type: Box::new(item_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Map(_) => Type::Map,
|
||||||
|
ValueNode::Range(_) => Type::Range,
|
||||||
|
ValueNode::String(_) => Type::String,
|
||||||
|
ValueNode::Function {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters,
|
||||||
|
return_type,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
|
||||||
|
|
||||||
|
for (_, type_constructor) in value_parameters {
|
||||||
|
let r#type = type_constructor.clone().construct(&context)?;
|
||||||
|
|
||||||
|
value_parameter_types.push(r#type);
|
||||||
|
}
|
||||||
|
|
||||||
|
let type_parameters = type_parameters.clone().map(|parameters| {
|
||||||
|
parameters
|
||||||
|
.iter()
|
||||||
|
.map(|identifier| identifier.clone())
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
let return_type = return_type.clone().construct(&context)?;
|
||||||
|
|
||||||
|
Type::Function {
|
||||||
|
type_parameters,
|
||||||
|
value_parameters: value_parameter_types,
|
||||||
|
return_type: Box::new(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueNode::Structure {
|
||||||
|
name,
|
||||||
|
fields: expressions,
|
||||||
|
} => {
|
||||||
|
let mut types = Vec::with_capacity(expressions.len());
|
||||||
|
|
||||||
|
for (identifier, expression) in expressions {
|
||||||
|
let r#type = expression.expected_type(context)?;
|
||||||
|
|
||||||
|
types.push((
|
||||||
|
identifier.clone(),
|
||||||
|
WithPosition {
|
||||||
|
node: r#type,
|
||||||
|
position: expression.position(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Structure {
|
||||||
|
name: name.node.clone(),
|
||||||
|
fields: types
|
||||||
|
.into_iter()
|
||||||
|
.map(|(identifier, r#type)| (identifier.node, r#type.node))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(r#type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,90 +504,3 @@ impl Ord for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpectedType for ValueNode {
|
|
||||||
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
|
|
||||||
let r#type = match self {
|
|
||||||
ValueNode::Boolean(_) => Type::Boolean,
|
|
||||||
ValueNode::EnumInstance { type_name, .. } => {
|
|
||||||
if let Some(r#type) = context.get_type(&type_name.node)? {
|
|
||||||
r#type
|
|
||||||
} else {
|
|
||||||
return Err(ValidationError::EnumDefinitionNotFound {
|
|
||||||
identifier: type_name.node.clone(),
|
|
||||||
position: Some(type_name.position),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueNode::Float(_) => Type::Float,
|
|
||||||
ValueNode::Integer(_) => Type::Integer,
|
|
||||||
ValueNode::List(items) => {
|
|
||||||
let item_type = items.first().unwrap().expected_type(context)?;
|
|
||||||
|
|
||||||
Type::List {
|
|
||||||
length: items.len(),
|
|
||||||
item_type: Box::new(item_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueNode::Map(_) => Type::Map,
|
|
||||||
ValueNode::Range(_) => Type::Range,
|
|
||||||
ValueNode::String(_) => Type::String,
|
|
||||||
ValueNode::Function {
|
|
||||||
type_parameters,
|
|
||||||
value_parameters,
|
|
||||||
return_type,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
|
|
||||||
|
|
||||||
for (_, type_constructor) in value_parameters {
|
|
||||||
let r#type = type_constructor.clone().construct(&context)?;
|
|
||||||
|
|
||||||
value_parameter_types.push(r#type);
|
|
||||||
}
|
|
||||||
|
|
||||||
let type_parameters = type_parameters.clone().map(|parameters| {
|
|
||||||
parameters
|
|
||||||
.iter()
|
|
||||||
.map(|identifier| identifier.clone())
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
let return_type = return_type.clone().construct(&context)?;
|
|
||||||
|
|
||||||
Type::Function {
|
|
||||||
type_parameters,
|
|
||||||
value_parameters: value_parameter_types,
|
|
||||||
return_type: Box::new(return_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueNode::Structure {
|
|
||||||
name,
|
|
||||||
fields: expressions,
|
|
||||||
} => {
|
|
||||||
let mut types = Vec::with_capacity(expressions.len());
|
|
||||||
|
|
||||||
for (identifier, expression) in expressions {
|
|
||||||
let r#type = expression.expected_type(context)?;
|
|
||||||
|
|
||||||
types.push((
|
|
||||||
identifier.clone(),
|
|
||||||
WithPosition {
|
|
||||||
node: r#type,
|
|
||||||
position: expression.position(),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Type::Structure {
|
|
||||||
name: name.node.clone(),
|
|
||||||
fields: types
|
|
||||||
.into_iter()
|
|
||||||
.map(|(identifier, r#type)| (identifier.node, r#type.node))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(r#type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Evaluate, Evaluation, Expression, Run, Statement, Validate};
|
use super::{AbstractNode, Evaluation, Expression, Statement, Type, Validate};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct While {
|
pub struct While {
|
||||||
@ -40,8 +40,8 @@ impl Validate for While {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Run for While {
|
impl AbstractNode for While {
|
||||||
fn run(
|
fn evaluate(
|
||||||
self,
|
self,
|
||||||
_context: &mut Context,
|
_context: &mut Context,
|
||||||
_manage_memory: bool,
|
_manage_memory: bool,
|
||||||
@ -74,4 +74,8 @@ impl Run for While {
|
|||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &mut Context) -> Result<Option<Type>, ValidationError> {
|
||||||
|
self.statements.last().unwrap().expected_type(_context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ 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,
|
||||||
|
@ -14,7 +14,7 @@ use serde::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Block, Evaluation, Run, Type, WithPosition},
|
abstract_tree::{Block, Evaluation, Type, WithPosition},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
|
Loading…
Reference in New Issue
Block a user