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::{
|
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
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
|
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))))
|
||||||
|
Loading…
Reference in New Issue
Block a user