Begin As implementation for AbstractTree; Add tests
This commit is contained in:
parent
e9bc16af0d
commit
18508fa217
107
src/abstract_tree/as.rs
Normal file
107
src/abstract_tree/as.rs
Normal 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!()
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
error::{RuntimeError, SyntaxError, ValidationError},
|
||||
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,
|
||||
};
|
||||
|
||||
@ -22,6 +22,7 @@ pub enum Expression {
|
||||
FunctionCall(Box<FunctionCall>),
|
||||
New(New),
|
||||
Command(Command),
|
||||
As(Box<As>),
|
||||
}
|
||||
|
||||
impl AbstractTree for Expression {
|
||||
@ -39,6 +40,7 @@ impl AbstractTree for Expression {
|
||||
};
|
||||
|
||||
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)?),
|
||||
"identifier" => {
|
||||
Expression::Identifier(Identifier::from_syntax(child, source, _context)?)
|
||||
@ -54,7 +56,7 @@ impl AbstractTree for Expression {
|
||||
_ => {
|
||||
return Err(SyntaxError::UnexpectedSyntaxNode {
|
||||
expected:
|
||||
"value, identifier, index, math, logic, function call, new or command"
|
||||
"value, identifier, index, math, logic, function call, new, as or command"
|
||||
.to_string(),
|
||||
actual: child.kind().to_string(),
|
||||
location: child.start_position(),
|
||||
@ -76,6 +78,7 @@ impl AbstractTree for Expression {
|
||||
Expression::Index(index) => index.expected_type(_context),
|
||||
Expression::New(new) => new.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::New(new) => new.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::New(new) => new.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::New(new) => new.format(_output, _indent_level),
|
||||
Expression::Command(command) => command.format(_output, _indent_level),
|
||||
Expression::As(r#as) => r#as.format(_output, _indent_level),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
//! syntax nodes. Then add a new AbstractTree type using the existing types as
|
||||
//! examples.
|
||||
|
||||
pub mod r#as;
|
||||
pub mod assignment;
|
||||
pub mod assignment_operator;
|
||||
pub mod block;
|
||||
@ -37,8 +38,8 @@ pub use {
|
||||
assignment::*, assignment_operator::*, block::*, built_in_value::*, command::*, expression::*,
|
||||
function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*,
|
||||
index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*,
|
||||
math::*, math_operator::*, new::*, r#for::*, r#match::*, r#type::*, r#while::*, statement::*,
|
||||
type_specification::*, value_node::*,
|
||||
math::*, math_operator::*, new::*, r#as::*, r#for::*, r#match::*, r#type::*, r#while::*,
|
||||
statement::*, type_specification::*, value_node::*,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
16
tests/as.rs
Normal file
16
tests/as.rs
Normal 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()),
|
||||
])))
|
||||
)
|
||||
}
|
@ -37,7 +37,7 @@ foo as (int) -> int
|
||||
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
|
||||
(identifier))
|
||||
(type
|
||||
(identifier))))
|
||||
(type
|
||||
(identifier)))))
|
||||
(block))))
|
||||
|
Loading…
Reference in New Issue
Block a user