Fix type setting bugs; Rename function

This commit is contained in:
Jeff 2024-01-31 20:52:34 -05:00
parent 9a465cb42d
commit e486413aca
33 changed files with 141 additions and 151 deletions

View File

@ -43,16 +43,6 @@ impl AbstractTree for Assignment {
let statement_node = syntax_node.child(child_count - 1).unwrap();
let statement = Statement::from_syntax(statement_node, source, context)?;
// if let AssignmentOperator::Equal = operator {
// let r#type = if let Some(definition) = &type_specification {
// definition.inner().clone()
// } else {
// statement.expected_type(context)?
// };
// context.set_type(identifier.inner().clone(), r#type)?;
// }
Ok(Assignment {
identifier,
type_specification,
@ -62,7 +52,18 @@ impl AbstractTree for Assignment {
})
}
fn check_type(&self, source: &str, context: &Map) -> Result<(), ValidationError> {
fn validate(&self, source: &str, context: &Map) -> Result<(), ValidationError> {
if let AssignmentOperator::Equal = self.operator {
let key = self.identifier.inner().clone();
let r#type = if let Some(definition) = &self.type_specification {
definition.inner().clone()
} else {
self.statement.expected_type(context)?
};
context.set_type(key, r#type)?;
}
if let Some(type_specification) = &self.type_specification {
match self.operator {
AssignmentOperator::Equal => {
@ -123,7 +124,7 @@ impl AbstractTree for Assignment {
}
}
self.statement.check_type(source, context)?;
self.statement.validate(source, context)?;
Ok(())
}

View File

@ -47,7 +47,7 @@ impl AbstractTree for AssignmentOperator {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}
}

View File

@ -52,12 +52,12 @@ impl AbstractTree for Block {
})
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
for statement in &self.statements {
if let Statement::Return(inner_statement) = statement {
return inner_statement.check_type(_source, _context);
return inner_statement.validate(_source, _context);
} else {
statement.check_type(_source, _context)?;
statement.validate(_source, _context)?;
}
}

View File

@ -195,7 +195,7 @@ impl AbstractTree for BuiltInValue {
Ok(self.r#type())
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -51,7 +51,7 @@ impl AbstractTree for Command {
Ok(Type::String)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
todo!()
}

View File

@ -78,17 +78,17 @@ impl AbstractTree for Expression {
}
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
match self {
Expression::Value(value_node) => value_node.check_type(_source, _context),
Expression::Identifier(identifier) => identifier.check_type(_source, _context),
Expression::Math(math) => math.check_type(_source, _context),
Expression::Logic(logic) => logic.check_type(_source, _context),
Expression::FunctionCall(function_call) => function_call.check_type(_source, _context),
Expression::Index(index) => index.check_type(_source, _context),
Expression::Yield(r#yield) => r#yield.check_type(_source, _context),
Expression::New(new) => new.check_type(_source, _context),
Expression::Command(command) => command.check_type(_source, _context),
Expression::Value(value_node) => value_node.validate(_source, _context),
Expression::Identifier(identifier) => identifier.validate(_source, _context),
Expression::Math(math) => math.validate(_source, _context),
Expression::Logic(logic) => logic.validate(_source, _context),
Expression::FunctionCall(function_call) => function_call.validate(_source, _context),
Expression::Index(index) => index.validate(_source, _context),
Expression::Yield(r#yield) => r#yield.validate(_source, _context),
Expression::New(new) => new.validate(_source, _context),
Expression::Command(command) => command.validate(_source, _context),
}
}

View File

@ -3,7 +3,8 @@ use serde::{Deserialize, Serialize};
use crate::{
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Block, Expression, Format, Identifier, Map, SyntaxNode, Type, Value,
AbstractTree, Block, Expression, Format, Identifier, Map, SourcePosition, SyntaxNode, Type,
Value,
};
/// Abstract representation of a for loop statement.
@ -13,6 +14,7 @@ pub struct For {
item_id: Identifier,
collection: Expression,
block: Block,
source_position: SourcePosition,
}
impl AbstractTree for For {
@ -47,6 +49,7 @@ impl AbstractTree for For {
item_id: identifier,
collection: expression,
block: item,
source_position: SourcePosition::from(node.range()),
})
}
@ -54,8 +57,23 @@ impl AbstractTree for For {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.block.check_type(_source, _context)
fn validate(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
let collection_type = self.collection.expected_type(context)?;
let item_type = if let Type::List(item_type) = collection_type {
item_type.as_ref().clone()
} else if let Type::Range = collection_type {
Type::Integer
} else {
return Err(ValidationError::TypeCheck {
expected: Type::Collection,
actual: collection_type,
position: self.source_position,
});
};
let key = self.item_id.inner().clone();
context.set_type(key, item_type)?;
self.block.validate(_source, context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -85,7 +85,7 @@ impl AbstractTree for FunctionCall {
}
}
fn check_type(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
let function_expression_type = self.function_expression.expected_type(context)?;
let parameter_types = match function_expression_type {

View File

@ -62,15 +62,15 @@ impl AbstractTree for FunctionExpression {
}
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
match self {
FunctionExpression::Identifier(identifier) => identifier.check_type(_source, _context),
FunctionExpression::Identifier(identifier) => identifier.validate(_source, _context),
FunctionExpression::FunctionCall(function_call) => {
function_call.check_type(_source, _context)
function_call.validate(_source, _context)
}
FunctionExpression::Value(value_node) => value_node.check_type(_source, _context),
FunctionExpression::Index(index) => index.check_type(_source, _context),
FunctionExpression::Yield(r#yield) => r#yield.check_type(_source, _context),
FunctionExpression::Value(value_node) => value_node.validate(_source, _context),
FunctionExpression::Index(index) => index.validate(_source, _context),
FunctionExpression::Yield(r#yield) => r#yield.validate(_source, _context),
}
}

View File

@ -146,7 +146,7 @@ impl AbstractTree for FunctionNode {
Ok(self.r#type().clone())
}
fn check_type(&self, source: &str, context: &Map) -> Result<(), ValidationError> {
fn validate(&self, source: &str, context: &Map) -> Result<(), ValidationError> {
let function_context = Map::new();
for (key, (_value, r#type)) in context.variables()?.iter() {
@ -174,7 +174,7 @@ impl AbstractTree for FunctionNode {
});
}
self.body.check_type(source, &function_context)?;
self.body.validate(source, &function_context)?;
Ok(())
} else {

View File

@ -39,7 +39,7 @@ impl AbstractTree for Identifier {
Ok(Identifier(text.to_string()))
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -63,9 +63,9 @@ impl AbstractTree for IfElse {
self.if_block.expected_type(context)
}
fn check_type(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
self.if_expression.check_type(_source, context)?;
self.if_block.check_type(_source, context)?;
fn validate(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
self.if_expression.validate(_source, context)?;
self.if_block.validate(_source, context)?;
let expected = self.if_block.expected_type(context)?;
let else_ifs = self
@ -74,8 +74,8 @@ impl AbstractTree for IfElse {
.zip(self.else_if_blocks.iter());
for (expression, block) in else_ifs {
expression.check_type(_source, context)?;
block.check_type(_source, context)?;
expression.validate(_source, context)?;
block.validate(_source, context)?;
let actual = block.expected_type(context)?;

View File

@ -54,12 +54,12 @@ impl AbstractTree for Index {
}
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.collection.check_type(_source, _context)?;
self.index.check_type(_source, _context)?;
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.collection.validate(_source, _context)?;
self.index.validate(_source, _context)?;
if let Some(index_end) = &self.index_end {
index_end.check_type(_source, _context)?;
index_end.validate(_source, _context)?;
}
Ok(())

View File

@ -37,9 +37,9 @@ impl AbstractTree for IndexAssignment {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.index.check_type(_source, _context)?;
self.statement.check_type(_source, _context)
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.index.validate(_source, _context)?;
self.statement.validate(_source, _context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -58,13 +58,13 @@ impl AbstractTree for IndexExpression {
}
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
match self {
IndexExpression::Value(value_node) => value_node.check_type(_source, _context),
IndexExpression::Identifier(identifier) => identifier.check_type(_source, _context),
IndexExpression::Index(index) => index.check_type(_source, _context),
IndexExpression::Value(value_node) => value_node.validate(_source, _context),
IndexExpression::Identifier(identifier) => identifier.validate(_source, _context),
IndexExpression::Index(index) => index.validate(_source, _context),
IndexExpression::FunctionCall(function_call) => {
function_call.check_type(_source, _context)
function_call.validate(_source, _context)
}
}
}

View File

@ -44,9 +44,9 @@ impl AbstractTree for Logic {
Ok(Type::Boolean)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.left.check_type(_source, _context)?;
self.right.check_type(_source, _context)
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.left.validate(_source, _context)?;
self.right.validate(_source, _context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -48,7 +48,7 @@ impl AbstractTree for LogicOperator {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -65,16 +65,16 @@ impl AbstractTree for Match {
first_statement.expected_type(context)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.matcher.check_type(_source, _context)?;
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.matcher.validate(_source, _context)?;
for (expression, statement) in &self.options {
expression.check_type(_source, _context)?;
statement.check_type(_source, _context)?;
expression.validate(_source, _context)?;
statement.validate(_source, _context)?;
}
if let Some(statement) = &self.fallback {
statement.check_type(_source, _context)?;
statement.validate(_source, _context)?;
}
Ok(())

View File

@ -40,9 +40,9 @@ impl AbstractTree for Math {
self.left.expected_type(context)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.left.check_type(_source, _context)?;
self.right.check_type(_source, _context)
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.left.validate(_source, _context)?;
self.right.validate(_source, _context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -40,7 +40,7 @@ impl AbstractTree for MathOperator {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -97,12 +97,12 @@ impl AbstractTree for Root {
Ok(Root { statements })
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
for statement in &self.statements {
if let Statement::Return(inner_statement) = statement {
return inner_statement.check_type(_source, _context);
return inner_statement.validate(_source, _context);
} else {
statement.check_type(_source, _context)?;
statement.validate(_source, _context)?;
}
}
@ -160,7 +160,7 @@ pub trait AbstractTree: Sized + Format {
fn expected_type(&self, context: &Map) -> Result<Type, ValidationError>;
/// Verify the type integrity of the node. Returns a validation error if the tree is invalid.
fn check_type(&self, source: &str, context: &Map) -> Result<(), ValidationError>;
fn validate(&self, source: &str, context: &Map) -> Result<(), ValidationError>;
/// Execute this node's logic and return a value. Returns a runtime error if the node cannot
/// resolve to a value.

View File

@ -29,7 +29,7 @@ impl AbstractTree for New {
todo!()
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
todo!()
}

View File

@ -80,19 +80,19 @@ impl AbstractTree for Statement {
}
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.check_type(_source, _context),
Statement::Expression(expression) => expression.check_type(_source, _context),
Statement::IfElse(if_else) => if_else.check_type(_source, _context),
Statement::Match(r#match) => r#match.check_type(_source, _context),
Statement::While(r#while) => r#while.check_type(_source, _context),
Statement::Block(block) => block.check_type(_source, _context),
Statement::For(r#for) => r#for.check_type(_source, _context),
Statement::Assignment(assignment) => assignment.validate(_source, _context),
Statement::Expression(expression) => expression.validate(_source, _context),
Statement::IfElse(if_else) => if_else.validate(_source, _context),
Statement::Match(r#match) => r#match.validate(_source, _context),
Statement::While(r#while) => r#while.validate(_source, _context),
Statement::Block(block) => block.validate(_source, _context),
Statement::For(r#for) => r#for.validate(_source, _context),
Statement::IndexAssignment(index_assignment) => {
index_assignment.check_type(_source, _context)
index_assignment.validate(_source, _context)
}
Statement::Return(statement) => statement.check_type(_source, _context),
Statement::Return(statement) => statement.validate(_source, _context),
}
}

View File

@ -196,7 +196,7 @@ impl AbstractTree for Type {
Ok(Type::None)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -38,7 +38,7 @@ impl AbstractTree for TypeSpecification {
self.r#type.expected_type(context)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -234,11 +234,11 @@ impl AbstractTree for ValueNode {
Ok(r#type)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
match self {
ValueNode::Function(function) => {
if let Function::ContextDefined(function_node) = function {
function_node.check_type(_source, _context)?;
function_node.validate(_source, _context)?;
}
}
_ => {}

View File

@ -31,9 +31,9 @@ impl AbstractTree for While {
self.block.expected_type(context)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.expression.check_type(_source, _context)?;
self.block.check_type(_source, _context)
fn validate(&self, _source: &str, context: &Map) -> Result<(), ValidationError> {
self.expression.validate(_source, context)?;
self.block.validate(_source, context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -47,8 +47,8 @@ impl AbstractTree for Yield {
self.call.expected_type(context)
}
fn check_type(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.call.check_type(_source, _context)
fn validate(&self, _source: &str, _context: &Map) -> Result<(), ValidationError> {
self.call.validate(_source, _context)
}
fn run(&self, source: &str, context: &Map) -> Result<Value, RuntimeError> {

View File

@ -61,15 +61,15 @@ impl fmt::Debug for Error {
}
impl fmt::Display for Error {
fn fmt(&self, _f: &mut Formatter) -> fmt::Result {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
use Error::*;
match self {
Syntax(_) => todo!(),
Validation(_) => todo!(),
Runtime(_) => todo!(),
ParserCancelled => todo!(),
Language(_) => todo!(),
Syntax(error) => write!(f, "Syntax error: {error}"),
Validation(error) => write!(f, "Validation error: {error}"),
Runtime(error) => write!(f, "Runtime error: {error}"),
ParserCancelled => write!(f, "Parsing was cancelled because the parser took too long."),
Language(error) => write!(f, "Parser failed to load language grammar."),
}
}
}

View File

@ -10,7 +10,7 @@ use crate::Value;
use super::rw_lock_error::RwLockError;
#[derive(PartialEq)]
#[derive(Debug, PartialEq)]
pub enum RuntimeError {
Csv(String),
@ -176,53 +176,8 @@ impl From<FromUtf8Error> for RuntimeError {
}
impl Display for RuntimeError {
fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result {
use RuntimeError::*;
match self {
VariableIdentifierNotFound(_) => todo!(),
RwLock(_) => todo!(),
Csv(_) => todo!(),
Io(_) => todo!(),
Reqwest(_) => todo!(),
Json(_) => todo!(),
SystemTime(_) => todo!(),
Toml(_) => todo!(),
Utf8(_) => todo!(),
ParseFloat(_) => todo!(),
ExpectedBuiltInFunctionArgumentAmount {
function_name: _,
expected: _,
actual: _,
} => todo!(),
ExpectedString { actual: _ } => todo!(),
ExpectedInteger { actual: _ } => todo!(),
ExpectedFloat { actual: _ } => todo!(),
ExpectedNumber { actual: _ } => todo!(),
ExpectedNumberOrString { actual: _ } => todo!(),
ExpectedBoolean { actual: _ } => todo!(),
ExpectedList { actual: _ } => todo!(),
ExpectedMinLengthList {
minimum_len: _,
actual_len: _,
} => todo!(),
ExpectedFixedLenList {
expected_len: _,
actual: _,
} => todo!(),
ExpectedNone { actual: _ } => todo!(),
ExpectedMap { actual: _ } => todo!(),
ExpectedTable { actual: _ } => todo!(),
ExpectedFunction { actual: _ } => todo!(),
ExpectedOption { actual: _ } => todo!(),
ExpectedCollection { actual: _ } => todo!(),
}
}
}
impl Debug for RuntimeError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{self}")
write!(f, "{self:?}")
}
}

View File

@ -1,3 +1,5 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use tree_sitter::{Node as SyntaxNode, Point};
@ -5,7 +7,7 @@ use crate::SourcePosition;
use super::rw_lock_error::RwLockError;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum SyntaxError {
/// Invalid user input.
InvalidSource {
@ -57,3 +59,9 @@ impl From<RwLockError> for SyntaxError {
SyntaxError::RwLock(error)
}
}
impl Display for SyntaxError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}

View File

@ -1,10 +1,12 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::{Identifier, SourcePosition, Type, Value};
use super::rw_lock_error::RwLockError;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ValidationError {
/// The 'assert' macro did not resolve successfully.
AssertEqualFailed {
@ -80,3 +82,9 @@ impl From<RwLockError> for ValidationError {
ValidationError::RwLock(RwLockError)
}
}
impl Display for ValidationError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}

View File

@ -139,7 +139,7 @@ impl Interpreter {
let abstract_tree = Root::from_syntax(syntax_tree.root_node(), source, &self.context)?;
abstract_tree.check_type(source, &self.context)?;
abstract_tree.validate(source, &self.context)?;
Ok(abstract_tree)
}