Begin As implementation for AbstractTree; Add tests

This commit is contained in:
Jeff 2024-02-13 10:26:26 -05:00
parent e9bc16af0d
commit 18508fa217
5 changed files with 137 additions and 6 deletions

107
src/abstract_tree/as.rs Normal file
View File

@ -0,0 +1,107 @@
use serde::{Deserialize, Serialize};
use tree_sitter::Node;
use crate::{
error::{RuntimeError, SyntaxError, ValidationError},
AbstractTree, Context, Expression, Format, List, SourcePosition, Type, Value,
};
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct As {
expression: Expression,
r#type: Type,
position: SourcePosition,
}
impl AbstractTree for As {
fn from_syntax(node: Node, source: &str, context: &Context) -> Result<Self, SyntaxError> {
SyntaxError::expect_syntax_node(source, "as", node)?;
let expression_node = node.child(0).unwrap();
let expression = Expression::from_syntax(expression_node, source, context)?;
let type_node = node.child(2).unwrap();
let r#type = Type::from_syntax(type_node, source, context)?;
Ok(As {
expression,
r#type,
position: SourcePosition::from(node.range()),
})
}
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(self.r#type.clone())
}
fn validate(&self, source: &str, context: &Context) -> Result<(), ValidationError> {
let expected_type = self.expression.expected_type(context)?;
if let Type::List(item_type) = &self.r#type {
match &expected_type {
Type::List(expected_item_type) => {
if !item_type.accepts(&expected_item_type) {
return Err(ValidationError::TypeCheck {
expected: self.r#type.clone(),
actual: expected_type.clone(),
position: self.position,
});
}
}
Type::Any => todo!(),
Type::Boolean => todo!(),
Type::Collection => todo!(),
Type::Custom(_) => todo!(),
Type::Float => todo!(),
Type::Function {
parameter_types,
return_type,
} => todo!(),
Type::Integer => todo!(),
Type::Map(_) => todo!(),
Type::None => todo!(),
Type::Number => todo!(),
Type::String => todo!(),
Type::Range => todo!(),
Type::Option(_) => todo!(),
}
}
Ok(())
}
fn run(&self, source: &str, context: &Context) -> Result<Value, RuntimeError> {
let value = self.expression.run(source, context)?;
let converted_value = if let Type::List(_) = self.r#type {
match value {
Value::List(list) => Value::List(list),
Value::String(string) => {
let chars = string
.chars()
.map(|char| Value::String(char.to_string()))
.collect();
Value::List(List::with_items(chars))
}
Value::Map(_) => todo!(),
Value::Function(_) => todo!(),
Value::Float(_) => todo!(),
Value::Integer(_) => todo!(),
Value::Boolean(_) => todo!(),
Value::Range(_) => todo!(),
Value::Option(_) => todo!(),
Value::Structure(_) => todo!(),
}
} else {
todo!()
};
Ok(converted_value)
}
}
impl Format for As {
fn format(&self, output: &mut String, indent_level: u8) {
todo!()
}
}

View File

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
error::{RuntimeError, SyntaxError, ValidationError}, error::{RuntimeError, SyntaxError, ValidationError},
value_node::ValueNode, value_node::ValueNode,
AbstractTree, Command, Context, Format, FunctionCall, Identifier, Index, Logic, Math, New, AbstractTree, As, Command, Context, Format, FunctionCall, Identifier, Index, Logic, Math, New,
SyntaxNode, Type, Value, SyntaxNode, Type, Value,
}; };
@ -22,6 +22,7 @@ pub enum Expression {
FunctionCall(Box<FunctionCall>), FunctionCall(Box<FunctionCall>),
New(New), New(New),
Command(Command), Command(Command),
As(Box<As>),
} }
impl AbstractTree for Expression { impl AbstractTree for Expression {
@ -39,6 +40,7 @@ impl AbstractTree for Expression {
}; };
let expression = match child.kind() { let expression = match child.kind() {
"as" => Expression::As(Box::new(As::from_syntax(child, source, _context)?)),
"value" => Expression::Value(ValueNode::from_syntax(child, source, _context)?), "value" => Expression::Value(ValueNode::from_syntax(child, source, _context)?),
"identifier" => { "identifier" => {
Expression::Identifier(Identifier::from_syntax(child, source, _context)?) Expression::Identifier(Identifier::from_syntax(child, source, _context)?)
@ -54,7 +56,7 @@ impl AbstractTree for Expression {
_ => { _ => {
return Err(SyntaxError::UnexpectedSyntaxNode { return Err(SyntaxError::UnexpectedSyntaxNode {
expected: expected:
"value, identifier, index, math, logic, function call, new or command" "value, identifier, index, math, logic, function call, new, as or command"
.to_string(), .to_string(),
actual: child.kind().to_string(), actual: child.kind().to_string(),
location: child.start_position(), location: child.start_position(),
@ -76,6 +78,7 @@ impl AbstractTree for Expression {
Expression::Index(index) => index.expected_type(_context), Expression::Index(index) => index.expected_type(_context),
Expression::New(new) => new.expected_type(_context), Expression::New(new) => new.expected_type(_context),
Expression::Command(command) => command.expected_type(_context), Expression::Command(command) => command.expected_type(_context),
Expression::As(r#as) => r#as.expected_type(_context),
} }
} }
@ -89,6 +92,7 @@ impl AbstractTree for Expression {
Expression::Index(index) => index.validate(_source, _context), Expression::Index(index) => index.validate(_source, _context),
Expression::New(new) => new.validate(_source, _context), Expression::New(new) => new.validate(_source, _context),
Expression::Command(command) => command.validate(_source, _context), Expression::Command(command) => command.validate(_source, _context),
Expression::As(r#as) => r#as.validate(_source, _context),
} }
} }
@ -102,6 +106,7 @@ impl AbstractTree for Expression {
Expression::Index(index) => index.run(_source, _context), Expression::Index(index) => index.run(_source, _context),
Expression::New(new) => new.run(_source, _context), Expression::New(new) => new.run(_source, _context),
Expression::Command(command) => command.run(_source, _context), Expression::Command(command) => command.run(_source, _context),
Expression::As(r#as) => r#as.run(_source, _context),
} }
} }
} }
@ -117,6 +122,7 @@ impl Format for Expression {
Expression::Index(index) => index.format(_output, _indent_level), Expression::Index(index) => index.format(_output, _indent_level),
Expression::New(new) => new.format(_output, _indent_level), Expression::New(new) => new.format(_output, _indent_level),
Expression::Command(command) => command.format(_output, _indent_level), Expression::Command(command) => command.format(_output, _indent_level),
Expression::As(r#as) => r#as.format(_output, _indent_level),
} }
} }
} }

View File

@ -6,6 +6,7 @@
//! syntax nodes. Then add a new AbstractTree type using the existing types as //! syntax nodes. Then add a new AbstractTree type using the existing types as
//! examples. //! examples.
pub mod r#as;
pub mod assignment; pub mod assignment;
pub mod assignment_operator; pub mod assignment_operator;
pub mod block; pub mod block;
@ -37,8 +38,8 @@ pub use {
assignment::*, assignment_operator::*, block::*, built_in_value::*, command::*, expression::*, assignment::*, assignment_operator::*, block::*, built_in_value::*, command::*, expression::*,
function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*, function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*,
index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*, index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*,
math::*, math_operator::*, new::*, r#for::*, r#match::*, r#type::*, r#while::*, statement::*, math::*, math_operator::*, new::*, r#as::*, r#for::*, r#match::*, r#type::*, r#while::*,
type_specification::*, value_node::*, statement::*, type_specification::*, value_node::*,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

16
tests/as.rs Normal file
View File

@ -0,0 +1,16 @@
use dust_lang::*;
#[test]
fn string_as_list() {
assert_eq!(
interpret("'foobar' as [str]"),
Ok(Value::List(List::with_items(vec![
Value::String("f".to_string()),
Value::String("o".to_string()),
Value::String("o".to_string()),
Value::String("b".to_string()),
Value::String("a".to_string()),
Value::String("r".to_string()),
])))
)
}

View File

@ -37,7 +37,7 @@ foo as (int) -> int
As List in For Loop As List in For Loop
================================================================================ ================================================================================
for i in foobar as list {} for i in foobar as [string] {}
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -50,5 +50,6 @@ for i in foobar as list {}
(expression (expression
(identifier)) (identifier))
(type (type
(identifier)))) (type
(identifier)))))
(block)))) (block))))