Implement formatting
This commit is contained in:
parent
731bf1cb98
commit
8737175df0
@ -1,10 +1,8 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, Identifier, Map, Result, Statement, SyntaxNode, SyntaxPosition, Type,
|
AbstractTree, AssignmentOperator, Error, Format, Identifier, Map, Result, Statement,
|
||||||
TypeDefinition, Value,
|
SyntaxNode, SyntaxPosition, Type, TypeDefinition, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -34,24 +32,8 @@ impl AbstractTree for Assignment {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let operator_node = syntax_node
|
let operator_node = syntax_node.child(child_count - 2).unwrap();
|
||||||
.child(child_count - 2)
|
let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?;
|
||||||
.unwrap()
|
|
||||||
.child(0)
|
|
||||||
.unwrap();
|
|
||||||
let operator = match operator_node.kind() {
|
|
||||||
"=" => AssignmentOperator::Equal,
|
|
||||||
"+=" => AssignmentOperator::PlusEqual,
|
|
||||||
"-=" => AssignmentOperator::MinusEqual,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "=, += or -=".to_string(),
|
|
||||||
actual: operator_node.kind().to_string(),
|
|
||||||
location: operator_node.start_position(),
|
|
||||||
relevant_source: source[operator_node.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let statement_node = syntax_node.child(child_count - 1).unwrap();
|
let statement_node = syntax_node.child(child_count - 1).unwrap();
|
||||||
let statement = Statement::from_syntax_node(source, statement_node, context)?;
|
let statement = Statement::from_syntax_node(source, statement_node, context)?;
|
||||||
@ -159,8 +141,8 @@ impl AbstractTree for Assignment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Assignment {
|
impl Format for Assignment {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let Assignment {
|
let Assignment {
|
||||||
identifier,
|
identifier,
|
||||||
type_definition,
|
type_definition,
|
||||||
@ -169,29 +151,16 @@ impl Display for Assignment {
|
|||||||
syntax_position: _,
|
syntax_position: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
write!(f, "{identifier}")?;
|
self.identifier.format(output, indent_level);
|
||||||
|
|
||||||
if let Some(type_definition) = type_definition {
|
if let Some(type_definition) = type_definition {
|
||||||
write!(f, " {type_definition}")?;
|
type_definition.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, " {operator} {statement}")
|
output.push_str(" ");
|
||||||
}
|
self.operator.format(output, indent_level);
|
||||||
}
|
output.push_str(" ");
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
self.statement.format(output, indent_level);
|
||||||
pub enum AssignmentOperator {
|
|
||||||
Equal,
|
|
||||||
PlusEqual,
|
|
||||||
MinusEqual,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for AssignmentOperator {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
AssignmentOperator::Equal => write!(f, "="),
|
|
||||||
AssignmentOperator::PlusEqual => write!(f, "-="),
|
|
||||||
AssignmentOperator::MinusEqual => write!(f, "+="),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
55
src/abstract_tree/assignment_operator.rs
Normal file
55
src/abstract_tree/assignment_operator.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum AssignmentOperator {
|
||||||
|
Equal,
|
||||||
|
PlusEqual,
|
||||||
|
MinusEqual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for AssignmentOperator {
|
||||||
|
fn from_syntax_node(
|
||||||
|
source: &str,
|
||||||
|
node: tree_sitter::Node,
|
||||||
|
context: &crate::Map,
|
||||||
|
) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "assignment_operator", node)?;
|
||||||
|
|
||||||
|
let operator_node = node.child(0).unwrap();
|
||||||
|
let operator = match operator_node.kind() {
|
||||||
|
"=" => AssignmentOperator::Equal,
|
||||||
|
"+=" => AssignmentOperator::PlusEqual,
|
||||||
|
"-=" => AssignmentOperator::MinusEqual,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "=, += or -=".to_string(),
|
||||||
|
actual: operator_node.kind().to_string(),
|
||||||
|
location: operator_node.start_position(),
|
||||||
|
relevant_source: source[operator_node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, source: &str, context: &Map) -> Result<Value> {
|
||||||
|
Ok(Value::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||||
|
Ok(Type::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format for AssignmentOperator {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
|
match self {
|
||||||
|
AssignmentOperator::Equal => output.push('='),
|
||||||
|
AssignmentOperator::PlusEqual => output.push_str("+="),
|
||||||
|
AssignmentOperator::MinusEqual => output.push_str("-="),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,10 @@
|
|||||||
use std::{
|
use std::sync::RwLock;
|
||||||
fmt::{self, Display, Formatter},
|
|
||||||
sync::RwLock,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Map, Result, Statement, Type, Value};
|
use crate::{AbstractTree, Error, Format, Map, Result, Statement, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a block.
|
/// Abstract representation of a block.
|
||||||
///
|
///
|
||||||
@ -131,18 +128,22 @@ impl AbstractTree for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Block {
|
impl Format for Block {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
if self.is_async {
|
if self.is_async {
|
||||||
writeln!(f, "async {{")?;
|
output.push_str("async {");
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, "{{")?;
|
output.push('{');
|
||||||
}
|
}
|
||||||
|
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
writeln!(f, " {statement}")?;
|
for _ in 0..=indent_level {
|
||||||
|
output.push_str(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
statement.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(f, "}}")
|
output.push('}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
use std::{
|
use std::{env::args, sync::OnceLock};
|
||||||
env::args,
|
|
||||||
fmt::{self, Display, Formatter},
|
|
||||||
sync::OnceLock,
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, List, Map,
|
built_in_functions::string_functions, AbstractTree, BuiltInFunction, Format, Function, List,
|
||||||
Result, Type, Value,
|
Map, Result, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
static ARGS: OnceLock<Value> = OnceLock::new();
|
static ARGS: OnceLock<Value> = OnceLock::new();
|
||||||
@ -31,6 +27,19 @@ pub enum BuiltInValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltInValue {
|
impl BuiltInValue {
|
||||||
|
pub fn name(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
BuiltInValue::Args => "args",
|
||||||
|
BuiltInValue::AssertEqual => "assert_equal",
|
||||||
|
BuiltInValue::Fs => "fs",
|
||||||
|
BuiltInValue::Json => "json",
|
||||||
|
BuiltInValue::Length => "length",
|
||||||
|
BuiltInValue::Output => "output",
|
||||||
|
BuiltInValue::Random => "random",
|
||||||
|
BuiltInValue::String => "string",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn r#type(&self) -> Type {
|
fn r#type(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
BuiltInValue::Args => Type::list(Type::String),
|
BuiltInValue::Args => Type::list(Type::String),
|
||||||
@ -72,7 +81,7 @@ impl BuiltInValue {
|
|||||||
|
|
||||||
json_context
|
json_context
|
||||||
.set(
|
.set(
|
||||||
"parse".to_string(),
|
BuiltInFunction::JsonParse.name().to_string(),
|
||||||
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
|
Value::Function(Function::BuiltIn(BuiltInFunction::JsonParse)),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@ -153,8 +162,8 @@ impl AbstractTree for BuiltInValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for BuiltInValue {
|
impl Format for BuiltInValue {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
write!(f, "{}", self.get())
|
output.push_str(&self.get().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
value_node::ValueNode, AbstractTree, Error, Identifier, Index, Map, Result, Type, Value, Yield,
|
value_node::ValueNode, AbstractTree, Error, Format, Identifier, Index, Map, Result, Type,
|
||||||
|
Value, Yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
use super::{function_call::FunctionCall, logic::Logic, math::Math};
|
||||||
@ -104,16 +103,16 @@ impl AbstractTree for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Expression {
|
impl Format for Expression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
match self {
|
match self {
|
||||||
Expression::Value(value_node) => write!(f, "{value_node}"),
|
Expression::Value(value_node) => value_node.format(output, indent_level),
|
||||||
Expression::Identifier(identifier) => write!(f, "{identifier}"),
|
Expression::Identifier(identifier) => identifier.format(output, indent_level),
|
||||||
Expression::Math(math) => write!(f, "{math}"),
|
Expression::Math(math) => math.format(output, indent_level),
|
||||||
Expression::Logic(logic) => write!(f, "{logic}"),
|
Expression::Logic(logic) => logic.format(output, indent_level),
|
||||||
Expression::FunctionCall(function_call) => write!(f, "{function_call}"),
|
Expression::FunctionCall(function_call) => function_call.format(output, indent_level),
|
||||||
Expression::Index(index) => write!(f, "{index}"),
|
Expression::Index(index) => index.format(output, indent_level),
|
||||||
Expression::Yield(r#yield) => write!(f, "{}", r#yield),
|
Expression::Yield(r#yield) => r#yield.format(output, indent_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::Write;
|
||||||
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value};
|
use crate::{AbstractTree, Block, Error, Expression, Format, Identifier, Map, Result, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a for loop statement.
|
/// Abstract representation of a for loop statement.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -81,21 +81,18 @@ impl AbstractTree for For {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for For {
|
impl Format for For {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let For {
|
if self.is_async {
|
||||||
is_async,
|
output.write_str("async for ");
|
||||||
item_id,
|
|
||||||
collection,
|
|
||||||
block,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
if *is_async {
|
|
||||||
write!(f, "async for ")?;
|
|
||||||
} else {
|
} else {
|
||||||
write!(f, "for ")?;
|
output.write_str("for ");
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{item_id} in {collection}, {{{block}}}")
|
self.item_id.format(output, indent_level);
|
||||||
|
output.push_str(" in ");
|
||||||
|
self.collection.format(output, indent_level);
|
||||||
|
output.push_str(" ");
|
||||||
|
self.block.format(output, indent_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, Expression, FunctionExpression, Map, Result, SyntaxPosition, Type, Value,
|
AbstractTree, Error, Expression, Format, FunctionExpression, Map, Result, SyntaxPosition, Type,
|
||||||
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -162,20 +161,15 @@ impl AbstractTree for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FunctionCall {
|
impl Format for FunctionCall {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let FunctionCall {
|
self.function_expression.format(output, indent_level);
|
||||||
function_expression,
|
output.push('(');
|
||||||
arguments,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
write!(f, "{function_expression}(")?;
|
for expression in &self.arguments {
|
||||||
|
expression.format(output, indent_level);
|
||||||
for expression in arguments {
|
|
||||||
write!(f, "{expression}")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ")")
|
output.push(')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type, Value, ValueNode,
|
AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map, Result, Type, Value,
|
||||||
Yield,
|
ValueNode, Yield,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -77,14 +75,16 @@ impl AbstractTree for FunctionExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FunctionExpression {
|
impl Format for FunctionExpression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
match self {
|
match self {
|
||||||
FunctionExpression::Value(value_node) => write!(f, "{value_node}"),
|
FunctionExpression::Value(value_node) => value_node.format(output, indent_level),
|
||||||
FunctionExpression::Identifier(identifier) => write!(f, "{identifier}"),
|
FunctionExpression::Identifier(identifier) => identifier.format(output, indent_level),
|
||||||
FunctionExpression::FunctionCall(function_call) => write!(f, "{function_call}"),
|
FunctionExpression::FunctionCall(function_call) => {
|
||||||
FunctionExpression::Index(index) => write!(f, "{index}"),
|
function_call.format(output, indent_level)
|
||||||
FunctionExpression::Yield(r#yield) => write!(f, "{}", r#yield),
|
}
|
||||||
|
FunctionExpression::Index(index) => index.format(output, indent_level),
|
||||||
|
FunctionExpression::Yield(r#yield) => r#yield.format(output, indent_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Block, Error, Function, Identifier, Map, Result, SyntaxPosition, Type,
|
AbstractTree, Block, Error, Format, Function, Identifier, Map, Result, SyntaxPosition, Type,
|
||||||
TypeDefinition, Value,
|
TypeDefinition, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -146,31 +146,39 @@ impl AbstractTree for FunctionNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FunctionNode {
|
impl Format for FunctionNode {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let FunctionNode {
|
|
||||||
parameters,
|
|
||||||
body,
|
|
||||||
r#type,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
let (parameter_types, return_type) = if let Type::Function {
|
let (parameter_types, return_type) = if let Type::Function {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
return_type,
|
return_type,
|
||||||
} = r#type
|
} = &self.r#type
|
||||||
{
|
{
|
||||||
(parameter_types, return_type)
|
(parameter_types, return_type)
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "(")?;
|
output.push('(');
|
||||||
|
|
||||||
for (identifier, r#type) in parameters.iter().zip(parameter_types.iter()) {
|
for (identifier, r#type) in self.parameters.iter().zip(parameter_types.iter()) {
|
||||||
write!(f, "{identifier} <{}>", r#type)?;
|
identifier.format(output, indent_level);
|
||||||
|
output.push('<');
|
||||||
|
r#type.format(output, indent_level);
|
||||||
|
output.push('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ") <{return_type}> {body}")
|
output.push_str(") <");
|
||||||
|
return_type.format(output, indent_level);
|
||||||
|
output.push_str("> ");
|
||||||
|
self.body.format(output, indent_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for FunctionNode {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let mut string = String::new();
|
||||||
|
|
||||||
|
self.format(&mut string, 0);
|
||||||
|
f.write_str(&string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Map, Result, Type, Value};
|
use crate::{AbstractTree, Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
/// A string by which a variable is known to a context.
|
/// A string by which a variable is known to a context.
|
||||||
///
|
///
|
||||||
@ -13,8 +13,8 @@ use crate::{AbstractTree, Error, Map, Result, Type, Value};
|
|||||||
pub struct Identifier(String);
|
pub struct Identifier(String);
|
||||||
|
|
||||||
impl Identifier {
|
impl Identifier {
|
||||||
pub fn new(inner: String) -> Self {
|
pub fn new<T: Into<String>>(inner: T) -> Self {
|
||||||
Identifier(inner)
|
Identifier(inner.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_inner(self) -> String {
|
pub fn take_inner(self) -> String {
|
||||||
@ -56,6 +56,12 @@ impl AbstractTree for Identifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Format for Identifier {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
|
output.push_str(&self.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Identifier {
|
impl Display for Identifier {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Block, Expression, Map, Result, Type, Value};
|
use crate::{AbstractTree, Block, Expression, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct IfElse {
|
pub struct IfElse {
|
||||||
@ -88,26 +86,28 @@ impl AbstractTree for IfElse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IfElse {
|
impl Format for IfElse {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let IfElse {
|
output.push_str("if ");
|
||||||
if_expression,
|
self.if_expression.format(output, indent_level);
|
||||||
if_block,
|
output.push(' ');
|
||||||
else_if_expressions,
|
self.if_block.format(output, indent_level);
|
||||||
else_if_blocks,
|
|
||||||
else_block,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
write!(f, "if {if_expression} {{{if_block}}}")?;
|
let else_ifs = self
|
||||||
|
.else_if_expressions
|
||||||
|
.iter()
|
||||||
|
.zip(self.else_if_blocks.iter());
|
||||||
|
|
||||||
for (expression, block) in else_if_expressions.iter().zip(else_if_blocks.iter()) {
|
for (expression, block) in else_ifs {
|
||||||
write!(f, "else if {expression} {{{block}}}")?;
|
output.push_str("else if ");
|
||||||
|
expression.format(output, indent_level);
|
||||||
|
output.push(' ');
|
||||||
|
block.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(block) = else_block {
|
if let Some(block) = &self.else_block {
|
||||||
write!(f, "else {{{block}}}")?;
|
output.push_str("else ");
|
||||||
|
block.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, IndexExpression, List, Map, Result, Type, Value};
|
use crate::{AbstractTree, Error, Format, IndexExpression, List, Map, Result, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of an index expression.
|
/// Abstract representation of an index expression.
|
||||||
///
|
///
|
||||||
@ -101,20 +99,15 @@ impl AbstractTree for Index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Index {
|
impl Format for Index {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let Index {
|
self.collection.format(output, indent_level);
|
||||||
collection,
|
output.push(':');
|
||||||
index,
|
self.index.format(output, indent_level);
|
||||||
index_end,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
write!(f, "{collection}:{index}")?;
|
if let Some(expression) = &self.index_end {
|
||||||
|
output.push_str("..");
|
||||||
if let Some(expression) = index_end {
|
expression.format(output, indent_level);
|
||||||
write!(f, "..{expression}")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, AssignmentOperator, Error, Index, IndexExpression, Map, Result, Statement, Type,
|
AbstractTree, AssignmentOperator, Error, Format, Index, IndexExpression, Map, Result,
|
||||||
Value,
|
Statement, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -22,20 +20,8 @@ impl AbstractTree for IndexAssignment {
|
|||||||
let index_node = node.child(0).unwrap();
|
let index_node = node.child(0).unwrap();
|
||||||
let index = Index::from_syntax_node(source, index_node, context)?;
|
let index = Index::from_syntax_node(source, index_node, context)?;
|
||||||
|
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let operator_node = node.child(1).unwrap();
|
||||||
let operator = match operator_node.kind() {
|
let operator = AssignmentOperator::from_syntax_node(source, operator_node, context)?;
|
||||||
"=" => AssignmentOperator::Equal,
|
|
||||||
"+=" => AssignmentOperator::PlusEqual,
|
|
||||||
"-=" => AssignmentOperator::MinusEqual,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "=, += or -=".to_string(),
|
|
||||||
actual: operator_node.kind().to_string(),
|
|
||||||
location: operator_node.start_position(),
|
|
||||||
relevant_source: source[operator_node.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let statement_node = node.child(2).unwrap();
|
let statement_node = node.child(2).unwrap();
|
||||||
let statement = Statement::from_syntax_node(source, statement_node, context)?;
|
let statement = Statement::from_syntax_node(source, statement_node, context)?;
|
||||||
@ -94,14 +80,12 @@ impl AbstractTree for IndexAssignment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IndexAssignment {
|
impl Format for IndexAssignment {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let IndexAssignment {
|
self.index.format(output, indent_level);
|
||||||
index,
|
output.push(' ');
|
||||||
operator,
|
self.operator.format(output, indent_level);
|
||||||
statement,
|
output.push(' ');
|
||||||
} = self;
|
self.statement.format(output, indent_level);
|
||||||
|
|
||||||
write!(f, "{index} {operator} {statement}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
value_node::ValueNode, AbstractTree, Error, FunctionCall, Identifier, Index, Map, Result, Type,
|
value_node::ValueNode, AbstractTree, Error, Format, FunctionCall, Identifier, Index, Map,
|
||||||
Value,
|
Result, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -69,13 +67,21 @@ impl AbstractTree for IndexExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IndexExpression {
|
impl Format for IndexExpression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
match self {
|
match self {
|
||||||
IndexExpression::Value(value_node) => write!(f, "{value_node}"),
|
IndexExpression::Value(value_node) => {
|
||||||
IndexExpression::Identifier(identifier) => write!(f, "{identifier}"),
|
if let ValueNode::BuiltInValue(built_in_value) = value_node {
|
||||||
IndexExpression::FunctionCall(function_call) => write!(f, "{function_call}"),
|
output.push_str(built_in_value.name());
|
||||||
IndexExpression::Index(index) => write!(f, "{index}"),
|
} else {
|
||||||
|
value_node.format(output, indent_level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IndexExpression::Identifier(identifier) => identifier.format(output, indent_level),
|
||||||
|
IndexExpression::FunctionCall(function_call) => {
|
||||||
|
function_call.format(output, indent_level)
|
||||||
|
}
|
||||||
|
IndexExpression::Index(index) => index.format(output, indent_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value};
|
use crate::{AbstractTree, Error, Expression, Format, LogicOperator, Map, Result, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a logic expression.
|
/// Abstract representation of a logic expression.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -20,38 +18,17 @@ impl AbstractTree for Logic {
|
|||||||
let first_node = node.child(0).unwrap();
|
let first_node = node.child(0).unwrap();
|
||||||
let (left_node, operator_node, right_node) = {
|
let (left_node, operator_node, right_node) = {
|
||||||
if first_node.is_named() {
|
if first_node.is_named() {
|
||||||
(
|
(first_node, node.child(1).unwrap(), node.child(2).unwrap())
|
||||||
first_node,
|
|
||||||
node.child(1).unwrap().child(0).unwrap(),
|
|
||||||
node.child(2).unwrap(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
node.child(1).unwrap(),
|
node.child(1).unwrap(),
|
||||||
node.child(2).unwrap().child(0).unwrap(),
|
node.child(2).unwrap(),
|
||||||
node.child(3).unwrap(),
|
node.child(3).unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let left = Expression::from_syntax_node(source, left_node, context)?;
|
let left = Expression::from_syntax_node(source, left_node, context)?;
|
||||||
let operator = match operator_node.kind() {
|
let operator = LogicOperator::from_syntax_node(source, operator_node, context)?;
|
||||||
"==" => LogicOperator::Equal,
|
|
||||||
"!=" => LogicOperator::NotEqual,
|
|
||||||
"&&" => LogicOperator::And,
|
|
||||||
"||" => LogicOperator::Or,
|
|
||||||
">" => LogicOperator::Greater,
|
|
||||||
"<" => LogicOperator::Less,
|
|
||||||
">=" => LogicOperator::GreaterOrEqual,
|
|
||||||
"<=" => LogicOperator::LessOrEqual,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "==, !=, &&, ||, >, <, >= or <=".to_string(),
|
|
||||||
actual: operator_node.kind().to_string(),
|
|
||||||
location: operator_node.start_position(),
|
|
||||||
relevant_source: source[operator_node.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let right = Expression::from_syntax_node(source, right_node, context)?;
|
let right = Expression::from_syntax_node(source, right_node, context)?;
|
||||||
|
|
||||||
Ok(Logic {
|
Ok(Logic {
|
||||||
@ -95,41 +72,12 @@ impl AbstractTree for Logic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Logic {
|
impl Format for Logic {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let Logic {
|
self.left.format(output, indent_level);
|
||||||
left,
|
output.push(' ');
|
||||||
operator,
|
self.operator.format(output, indent_level);
|
||||||
right,
|
output.push(' ');
|
||||||
} = self;
|
self.right.format(output, indent_level);
|
||||||
|
|
||||||
write!(f, "{left} {operator} {right}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum LogicOperator {
|
|
||||||
Equal,
|
|
||||||
NotEqual,
|
|
||||||
And,
|
|
||||||
Or,
|
|
||||||
Greater,
|
|
||||||
Less,
|
|
||||||
GreaterOrEqual,
|
|
||||||
LessOrEqual,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for LogicOperator {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
LogicOperator::Equal => write!(f, "="),
|
|
||||||
LogicOperator::NotEqual => write!(f, "!="),
|
|
||||||
LogicOperator::And => write!(f, "&&"),
|
|
||||||
LogicOperator::Or => write!(f, "||"),
|
|
||||||
LogicOperator::Greater => write!(f, ">"),
|
|
||||||
LogicOperator::Less => write!(f, "<"),
|
|
||||||
LogicOperator::GreaterOrEqual => write!(f, ">="),
|
|
||||||
LogicOperator::LessOrEqual => write!(f, "<="),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
70
src/abstract_tree/logic_operator.rs
Normal file
70
src/abstract_tree/logic_operator.rs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum LogicOperator {
|
||||||
|
Equal,
|
||||||
|
NotEqual,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Greater,
|
||||||
|
Less,
|
||||||
|
GreaterOrEqual,
|
||||||
|
LessOrEqual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for LogicOperator {
|
||||||
|
fn from_syntax_node(
|
||||||
|
source: &str,
|
||||||
|
node: tree_sitter::Node,
|
||||||
|
_context: &crate::Map,
|
||||||
|
) -> crate::Result<Self> {
|
||||||
|
Error::expect_syntax_node(source, "logic_operator", node)?;
|
||||||
|
|
||||||
|
let operator_node = node.child(0).unwrap();
|
||||||
|
let operator = match operator_node.kind() {
|
||||||
|
"==" => LogicOperator::Equal,
|
||||||
|
"!=" => LogicOperator::NotEqual,
|
||||||
|
"&&" => LogicOperator::And,
|
||||||
|
"||" => LogicOperator::Or,
|
||||||
|
">" => LogicOperator::Greater,
|
||||||
|
"<" => LogicOperator::Less,
|
||||||
|
">=" => LogicOperator::GreaterOrEqual,
|
||||||
|
"<=" => LogicOperator::LessOrEqual,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "==, !=, &&, ||, >, <, >= or <=".to_string(),
|
||||||
|
actual: operator_node.kind().to_string(),
|
||||||
|
location: operator_node.start_position(),
|
||||||
|
relevant_source: source[operator_node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||||
|
Ok(Value::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
Ok(Type::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format for LogicOperator {
|
||||||
|
fn format(&self, output: &mut String, _indent_level: u8) {
|
||||||
|
match self {
|
||||||
|
LogicOperator::Equal => output.push('='),
|
||||||
|
LogicOperator::NotEqual => output.push_str("!="),
|
||||||
|
LogicOperator::And => output.push_str("&&"),
|
||||||
|
LogicOperator::Or => output.push_str("||"),
|
||||||
|
LogicOperator::Greater => output.push('>'),
|
||||||
|
LogicOperator::Less => output.push('<'),
|
||||||
|
LogicOperator::GreaterOrEqual => output.push_str(">="),
|
||||||
|
LogicOperator::LessOrEqual => output.push_str("<="),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,10 @@
|
|||||||
//!
|
//!
|
||||||
//! Note that this module is called "match" but is escaped as "r#match" because
|
//! Note that this module is called "match" but is escaped as "r#match" because
|
||||||
//! "match" is a keyword in Rust.
|
//! "match" is a keyword in Rust.
|
||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Expression, Map, Result, Statement, Type, Value};
|
use crate::{AbstractTree, Error, Expression, Format, Map, Result, Statement, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a match statement.
|
/// Abstract representation of a match statement.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -85,24 +82,23 @@ impl AbstractTree for Match {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Match {
|
impl Format for Match {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let Match {
|
output.push_str("match ");
|
||||||
matcher,
|
self.matcher.format(output, indent_level);
|
||||||
options,
|
output.push_str(" {");
|
||||||
fallback,
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
write!(f, "match {matcher} {{")?;
|
for (expression, statement) in &self.options {
|
||||||
|
expression.format(output, indent_level);
|
||||||
for (expression, statement) in options {
|
output.push_str(" => ");
|
||||||
write!(f, "{expression} => {statement}")?;
|
statement.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(statement) = fallback {
|
if let Some(statement) = &self.fallback {
|
||||||
write!(f, "* => {statement}")?;
|
output.push_str("* => ");
|
||||||
|
statement.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "}}")
|
output.push('}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Expression, Map, Result, Type, Value};
|
use crate::{AbstractTree, Error, Expression, Format, Map, MathOperator, Result, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a math operation.
|
/// Abstract representation of a math operation.
|
||||||
///
|
///
|
||||||
@ -23,22 +21,8 @@ impl AbstractTree for Math {
|
|||||||
let left_node = node.child(0).unwrap();
|
let left_node = node.child(0).unwrap();
|
||||||
let left = Expression::from_syntax_node(source, left_node, context)?;
|
let left = Expression::from_syntax_node(source, left_node, context)?;
|
||||||
|
|
||||||
let operator_node = node.child(1).unwrap().child(0).unwrap();
|
let operator_node = node.child(1).unwrap();
|
||||||
let operator = match operator_node.kind() {
|
let operator = MathOperator::from_syntax_node(source, operator_node, context)?;
|
||||||
"+" => MathOperator::Add,
|
|
||||||
"-" => MathOperator::Subtract,
|
|
||||||
"*" => MathOperator::Multiply,
|
|
||||||
"/" => MathOperator::Divide,
|
|
||||||
"%" => MathOperator::Modulo,
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "+, -, *, / or %".to_string(),
|
|
||||||
actual: operator_node.kind().to_string(),
|
|
||||||
location: operator_node.start_position(),
|
|
||||||
relevant_source: source[operator_node.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let right_node = node.child(2).unwrap();
|
let right_node = node.child(2).unwrap();
|
||||||
let right = Expression::from_syntax_node(source, right_node, context)?;
|
let right = Expression::from_syntax_node(source, right_node, context)?;
|
||||||
@ -69,35 +53,12 @@ impl AbstractTree for Math {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Math {
|
impl Format for Math {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let Math {
|
self.left.format(output, indent_level);
|
||||||
left,
|
output.push(' ');
|
||||||
operator,
|
self.operator.format(output, indent_level);
|
||||||
right,
|
output.push(' ');
|
||||||
} = self;
|
self.right.format(output, indent_level);
|
||||||
|
|
||||||
write!(f, "{left} {operator} {right}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum MathOperator {
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
Multiply,
|
|
||||||
Divide,
|
|
||||||
Modulo,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for MathOperator {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
MathOperator::Add => write!(f, "+"),
|
|
||||||
MathOperator::Subtract => write!(f, "-"),
|
|
||||||
MathOperator::Multiply => write!(f, "*"),
|
|
||||||
MathOperator::Divide => write!(f, "/"),
|
|
||||||
MathOperator::Modulo => write!(f, "%"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
57
src/abstract_tree/math_operator.rs
Normal file
57
src/abstract_tree/math_operator.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum MathOperator {
|
||||||
|
Add,
|
||||||
|
Subtract,
|
||||||
|
Multiply,
|
||||||
|
Divide,
|
||||||
|
Modulo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for MathOperator {
|
||||||
|
fn from_syntax_node(source: &str, node: tree_sitter::Node, context: &Map) -> Result<Self> {
|
||||||
|
let operator_node = node.child(0).unwrap();
|
||||||
|
let operator = match operator_node.kind() {
|
||||||
|
"+" => MathOperator::Add,
|
||||||
|
"-" => MathOperator::Subtract,
|
||||||
|
"*" => MathOperator::Multiply,
|
||||||
|
"/" => MathOperator::Divide,
|
||||||
|
"%" => MathOperator::Modulo,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "+, -, *, / or %".to_string(),
|
||||||
|
actual: operator_node.kind().to_string(),
|
||||||
|
location: operator_node.start_position(),
|
||||||
|
relevant_source: source[operator_node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(operator)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||||
|
Ok(Value::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
Ok(Type::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format for MathOperator {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
|
let char = match self {
|
||||||
|
MathOperator::Add => '+',
|
||||||
|
MathOperator::Subtract => '-',
|
||||||
|
MathOperator::Multiply => '*',
|
||||||
|
MathOperator::Divide => '/',
|
||||||
|
MathOperator::Modulo => '%',
|
||||||
|
};
|
||||||
|
|
||||||
|
output.push(char);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
//! examples.
|
//! examples.
|
||||||
|
|
||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
|
pub mod assignment_operator;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod built_in_value;
|
pub mod built_in_value;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
@ -20,23 +21,25 @@ pub mod index;
|
|||||||
pub mod index_assignment;
|
pub mod index_assignment;
|
||||||
pub mod index_expression;
|
pub mod index_expression;
|
||||||
pub mod logic;
|
pub mod logic;
|
||||||
|
pub mod logic_operator;
|
||||||
pub mod r#match;
|
pub mod r#match;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
pub mod math_operator;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
|
pub mod r#type;
|
||||||
pub mod type_definition;
|
pub mod type_definition;
|
||||||
pub mod value_node;
|
pub mod value_node;
|
||||||
pub mod r#while;
|
pub mod r#while;
|
||||||
pub mod r#yield;
|
pub mod r#yield;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
assignment::*, block::*, built_in_value::*, expression::*, function_call::*,
|
assignment::*, assignment_operator::*, block::*, built_in_value::*, expression::*,
|
||||||
function_expression::*, function_node::*, identifier::*, if_else::*, index::*,
|
function_call::*, function_expression::*, function_node::*, identifier::*, if_else::*,
|
||||||
index_assignment::IndexAssignment, index_expression::*, logic::*, math::*, r#for::*,
|
index::*, index_assignment::IndexAssignment, index_expression::*, logic::*, logic_operator::*,
|
||||||
r#match::*, r#while::*, r#yield::*, statement::*, type_definition::*, value_node::*,
|
math::*, math_operator::*, r#for::*, r#match::*, r#type::*, r#while::*, r#yield::*,
|
||||||
|
statement::*, type_definition::*, value_node::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
@ -118,19 +121,17 @@ impl AbstractTree for Root {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Root {
|
impl Format for Root {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
write!(f, "{statement}")?;
|
statement.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait is implemented by the Evaluator's internal types to form an
|
/// This trait is implemented by the Evaluator's internal types to form an
|
||||||
/// executable tree that resolves to a single value.
|
/// executable tree that resolves to a single value.
|
||||||
pub trait AbstractTree: Sized {
|
pub trait AbstractTree: Sized + Format {
|
||||||
/// Interpret the syntax tree at the given node and return the abstraction.
|
/// Interpret the syntax tree at the given node and return the abstraction.
|
||||||
///
|
///
|
||||||
/// This function is used to convert nodes in the Tree Sitter concrete
|
/// This function is used to convert nodes in the Tree Sitter concrete
|
||||||
@ -152,3 +153,7 @@ pub trait AbstractTree: Sized {
|
|||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type>;
|
fn expected_type(&self, context: &Map) -> Result<Type>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Format {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8);
|
||||||
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, Assignment, Block, Error, Expression, For, IfElse, IndexAssignment, Map, Match,
|
AbstractTree, Assignment, Block, Error, Expression, For, Format, IfElse, IndexAssignment, Map,
|
||||||
Result, Type, Value, While,
|
Match, Result, Type, Value, While,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract representation of a statement.
|
/// Abstract representation of a statement.
|
||||||
@ -113,18 +111,20 @@ impl AbstractTree for Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Statement {
|
impl Format for Statement {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => write!(f, "{assignment}"),
|
Statement::Assignment(assignment) => assignment.format(output, indent_level),
|
||||||
Statement::Expression(expression) => write!(f, "{expression}"),
|
Statement::Expression(expression) => expression.format(output, indent_level),
|
||||||
Statement::IfElse(if_else) => write!(f, "{if_else}"),
|
Statement::IfElse(if_else) => if_else.format(output, indent_level),
|
||||||
Statement::Match(r#match) => write!(f, "{}", r#match),
|
Statement::Match(r#match) => r#match.format(output, indent_level),
|
||||||
Statement::While(r#while) => write!(f, "{}", r#while),
|
Statement::While(r#while) => r#while.format(output, indent_level),
|
||||||
Statement::Block(block) => write!(f, "{block}"),
|
Statement::Block(block) => block.format(output, indent_level),
|
||||||
Statement::For(r#for) => write!(f, "{}", r#for),
|
Statement::For(r#for) => r#for.format(output, indent_level),
|
||||||
Statement::IndexAssignment(index_assignment) => write!(f, "{index_assignment}"),
|
Statement::IndexAssignment(index_assignment) => {
|
||||||
Statement::Return(statement) => write!(f, "{statement}"),
|
index_assignment.format(output, indent_level)
|
||||||
|
}
|
||||||
|
Statement::Return(statement) => statement.format(output, indent_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
290
src/abstract_tree/type.rs
Normal file
290
src/abstract_tree/type.rs
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tree_sitter::Node;
|
||||||
|
|
||||||
|
use crate::{AbstractTree, Error, Format, Map, Result, Structure, Value};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
|
pub enum Type {
|
||||||
|
Any,
|
||||||
|
Boolean,
|
||||||
|
Collection,
|
||||||
|
Float,
|
||||||
|
Function {
|
||||||
|
parameter_types: Vec<Type>,
|
||||||
|
return_type: Box<Type>,
|
||||||
|
},
|
||||||
|
Integer,
|
||||||
|
List(Box<Type>),
|
||||||
|
Map(Option<Structure>),
|
||||||
|
None,
|
||||||
|
Number,
|
||||||
|
String,
|
||||||
|
Option(Box<Type>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn list(item_type: Type) -> Self {
|
||||||
|
Type::List(Box::new(item_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function(parameter_types: Vec<Type>, return_type: Type) -> Self {
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: Box::new(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn option(optional_type: Type) -> Self {
|
||||||
|
Type::Option(Box::new(optional_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(&self, other: &Type) -> Result<()> {
|
||||||
|
match (self, other) {
|
||||||
|
(Type::Any, _)
|
||||||
|
| (_, Type::Any)
|
||||||
|
| (Type::Boolean, Type::Boolean)
|
||||||
|
| (Type::Collection, Type::Collection)
|
||||||
|
| (Type::Collection, Type::List(_))
|
||||||
|
| (Type::List(_), Type::Collection)
|
||||||
|
| (Type::Collection, Type::Map(_))
|
||||||
|
| (Type::Map(_), Type::Collection)
|
||||||
|
| (Type::Collection, Type::String)
|
||||||
|
| (Type::String, Type::Collection)
|
||||||
|
| (Type::Float, Type::Float)
|
||||||
|
| (Type::Integer, Type::Integer)
|
||||||
|
| (Type::Map(_), Type::Map(_))
|
||||||
|
| (Type::Number, Type::Number)
|
||||||
|
| (Type::Number, Type::Integer)
|
||||||
|
| (Type::Number, Type::Float)
|
||||||
|
| (Type::Integer, Type::Number)
|
||||||
|
| (Type::Float, Type::Number)
|
||||||
|
| (Type::None, Type::None)
|
||||||
|
| (Type::String, Type::String) => Ok(()),
|
||||||
|
(Type::Option(left), Type::Option(right)) => {
|
||||||
|
if left == right {
|
||||||
|
Ok(())
|
||||||
|
} else if let Type::Any = left.as_ref() {
|
||||||
|
Ok(())
|
||||||
|
} else if let Type::Any = right.as_ref() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Type::Option(_), Type::None) | (Type::None, Type::Option(_)) => Ok(()),
|
||||||
|
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
||||||
|
if self_item_type.check(other_item_type).is_err() {
|
||||||
|
Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(
|
||||||
|
Type::Function {
|
||||||
|
parameter_types: self_parameter_types,
|
||||||
|
return_type: self_return_type,
|
||||||
|
},
|
||||||
|
Type::Function {
|
||||||
|
parameter_types: other_parameter_types,
|
||||||
|
return_type: other_return_type,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let parameter_type_pairs = self_parameter_types
|
||||||
|
.iter()
|
||||||
|
.zip(other_parameter_types.iter());
|
||||||
|
|
||||||
|
for (self_parameter_type, other_parameter_type) in parameter_type_pairs {
|
||||||
|
if self_parameter_type.check(other_parameter_type).is_err() {
|
||||||
|
return Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self_return_type.check(other_return_type).is_err() {
|
||||||
|
Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(Error::TypeCheck {
|
||||||
|
expected: self.clone(),
|
||||||
|
actual: other.clone(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbstractTree for Type {
|
||||||
|
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> {
|
||||||
|
Error::expect_syntax_node(_source, "type", node)?;
|
||||||
|
|
||||||
|
let type_node = node.child(0).unwrap();
|
||||||
|
|
||||||
|
let r#type = match type_node.kind() {
|
||||||
|
"[" => {
|
||||||
|
let item_type_node = node.child(1).unwrap();
|
||||||
|
let item_type = Type::from_syntax_node(_source, item_type_node, _context)?;
|
||||||
|
|
||||||
|
Type::List(Box::new(item_type))
|
||||||
|
}
|
||||||
|
"any" => Type::Any,
|
||||||
|
"bool" => Type::Boolean,
|
||||||
|
"collection" => Type::Collection,
|
||||||
|
"float" => Type::Float,
|
||||||
|
"(" => {
|
||||||
|
let child_count = node.child_count();
|
||||||
|
let mut parameter_types = Vec::new();
|
||||||
|
|
||||||
|
for index in 1..child_count - 2 {
|
||||||
|
let child = node.child(index).unwrap();
|
||||||
|
|
||||||
|
if child.is_named() {
|
||||||
|
let parameter_type = Type::from_syntax_node(_source, child, _context)?;
|
||||||
|
|
||||||
|
parameter_types.push(parameter_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let final_node = node.child(child_count - 1).unwrap();
|
||||||
|
let return_type = if final_node.is_named() {
|
||||||
|
Type::from_syntax_node(_source, final_node, _context)?
|
||||||
|
} else {
|
||||||
|
Type::None
|
||||||
|
};
|
||||||
|
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: Box::new(return_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"int" => Type::Integer,
|
||||||
|
"map" => Type::Map(None),
|
||||||
|
"num" => Type::Number,
|
||||||
|
"none" => Type::None,
|
||||||
|
"str" => Type::String,
|
||||||
|
"option" => {
|
||||||
|
let inner_type_node = node.child(2).unwrap();
|
||||||
|
let inner_type = Type::from_syntax_node(_source, inner_type_node, _context)?;
|
||||||
|
|
||||||
|
Type::Option(Box::new(inner_type))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::UnexpectedSyntaxNode {
|
||||||
|
expected: "any, bool, float, int, num, str, option, (, [ or {".to_string(),
|
||||||
|
actual: type_node.kind().to_string(),
|
||||||
|
location: type_node.start_position(),
|
||||||
|
relevant_source: _source[type_node.byte_range()].to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(r#type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
||||||
|
Ok(Value::none())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
||||||
|
Ok(Type::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format for Type {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
|
match self {
|
||||||
|
Type::Any => output.push_str("any"),
|
||||||
|
Type::Boolean => output.push_str("bool"),
|
||||||
|
Type::Collection => output.push_str("collection"),
|
||||||
|
Type::Float => output.push_str("float"),
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type,
|
||||||
|
} => {
|
||||||
|
output.push('(');
|
||||||
|
|
||||||
|
for (index, parameter_type) in parameter_types.iter().enumerate() {
|
||||||
|
parameter_type.format(output, indent_level);
|
||||||
|
|
||||||
|
if index != parameter_types.len() - 1 {
|
||||||
|
output.push(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push_str(") -> ");
|
||||||
|
return_type.format(output, indent_level);
|
||||||
|
}
|
||||||
|
Type::Integer => output.push_str("int"),
|
||||||
|
Type::List(item_type) => {
|
||||||
|
output.push('[');
|
||||||
|
item_type.format(output, indent_level);
|
||||||
|
output.push(']');
|
||||||
|
}
|
||||||
|
Type::Map(structure_option) => {
|
||||||
|
if let Some(structure) = structure_option {
|
||||||
|
output.push_str(&structure.to_string());
|
||||||
|
} else {
|
||||||
|
output.push_str("map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::None => output.push_str("none"),
|
||||||
|
Type::Number => output.push_str("number"),
|
||||||
|
Type::String => output.push_str("str"),
|
||||||
|
Type::Option(optional_type) => {
|
||||||
|
output.push_str("option(");
|
||||||
|
optional_type.format(output, indent_level);
|
||||||
|
output.push(')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Type {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Type::Any => write!(f, "any"),
|
||||||
|
Type::Boolean => write!(f, "bool"),
|
||||||
|
Type::Collection => write!(f, "collection"),
|
||||||
|
Type::Float => write!(f, "float"),
|
||||||
|
Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type,
|
||||||
|
} => {
|
||||||
|
write!(f, "(")?;
|
||||||
|
|
||||||
|
for (index, parameter_type) in parameter_types.iter().enumerate() {
|
||||||
|
write!(f, "{parameter_type}")?;
|
||||||
|
|
||||||
|
if index != parameter_types.len() - 1 {
|
||||||
|
write!(f, " ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, ")")?;
|
||||||
|
write!(f, " -> {return_type}")
|
||||||
|
}
|
||||||
|
Type::Integer => write!(f, "int"),
|
||||||
|
Type::List(item_type) => write!(f, "[{item_type}]"),
|
||||||
|
Type::Map(_) => write!(f, "map"),
|
||||||
|
Type::Number => write!(f, "num"),
|
||||||
|
Type::None => write!(f, "none"),
|
||||||
|
Type::String => write!(f, "str"),
|
||||||
|
Type::Option(inner_type) => {
|
||||||
|
write!(f, "option({})", inner_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Error, Map, Result, Structure, Value};
|
use crate::{AbstractTree, Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct TypeDefinition {
|
pub struct TypeDefinition {
|
||||||
@ -43,243 +41,10 @@ impl AbstractTree for TypeDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TypeDefinition {
|
impl Format for TypeDefinition {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
write!(f, "<{}>", self.r#type)
|
output.push('<');
|
||||||
}
|
self.r#type.format(output, indent_level);
|
||||||
}
|
output.push('>');
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
|
||||||
pub enum Type {
|
|
||||||
Any,
|
|
||||||
Boolean,
|
|
||||||
Collection,
|
|
||||||
Float,
|
|
||||||
Function {
|
|
||||||
parameter_types: Vec<Type>,
|
|
||||||
return_type: Box<Type>,
|
|
||||||
},
|
|
||||||
Integer,
|
|
||||||
List(Box<Type>),
|
|
||||||
Map(Option<Structure>),
|
|
||||||
None,
|
|
||||||
Number,
|
|
||||||
String,
|
|
||||||
Option(Box<Type>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
pub fn list(item_type: Type) -> Self {
|
|
||||||
Type::List(Box::new(item_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn function(parameter_types: Vec<Type>, return_type: Type) -> Self {
|
|
||||||
Type::Function {
|
|
||||||
parameter_types,
|
|
||||||
return_type: Box::new(return_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn option(optional_type: Type) -> Self {
|
|
||||||
Type::Option(Box::new(optional_type))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check(&self, other: &Type) -> Result<()> {
|
|
||||||
match (self, other) {
|
|
||||||
(Type::Any, _)
|
|
||||||
| (_, Type::Any)
|
|
||||||
| (Type::Boolean, Type::Boolean)
|
|
||||||
| (Type::Collection, Type::Collection)
|
|
||||||
| (Type::Collection, Type::List(_))
|
|
||||||
| (Type::List(_), Type::Collection)
|
|
||||||
| (Type::Collection, Type::Map(_))
|
|
||||||
| (Type::Map(_), Type::Collection)
|
|
||||||
| (Type::Collection, Type::String)
|
|
||||||
| (Type::String, Type::Collection)
|
|
||||||
| (Type::Float, Type::Float)
|
|
||||||
| (Type::Integer, Type::Integer)
|
|
||||||
| (Type::Map(_), Type::Map(_))
|
|
||||||
| (Type::Number, Type::Number)
|
|
||||||
| (Type::Number, Type::Integer)
|
|
||||||
| (Type::Number, Type::Float)
|
|
||||||
| (Type::Integer, Type::Number)
|
|
||||||
| (Type::Float, Type::Number)
|
|
||||||
| (Type::None, Type::None)
|
|
||||||
| (Type::String, Type::String) => Ok(()),
|
|
||||||
(Type::Option(left), Type::Option(right)) => {
|
|
||||||
if left == right {
|
|
||||||
Ok(())
|
|
||||||
} else if let Type::Any = left.as_ref() {
|
|
||||||
Ok(())
|
|
||||||
} else if let Type::Any = right.as_ref() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::TypeCheck {
|
|
||||||
expected: self.clone(),
|
|
||||||
actual: other.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Type::Option(_), Type::None) | (Type::None, Type::Option(_)) => Ok(()),
|
|
||||||
(Type::List(self_item_type), Type::List(other_item_type)) => {
|
|
||||||
if self_item_type.check(other_item_type).is_err() {
|
|
||||||
Err(Error::TypeCheck {
|
|
||||||
expected: self.clone(),
|
|
||||||
actual: other.clone(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(
|
|
||||||
Type::Function {
|
|
||||||
parameter_types: self_parameter_types,
|
|
||||||
return_type: self_return_type,
|
|
||||||
},
|
|
||||||
Type::Function {
|
|
||||||
parameter_types: other_parameter_types,
|
|
||||||
return_type: other_return_type,
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
let parameter_type_pairs = self_parameter_types
|
|
||||||
.iter()
|
|
||||||
.zip(other_parameter_types.iter());
|
|
||||||
|
|
||||||
for (self_parameter_type, other_parameter_type) in parameter_type_pairs {
|
|
||||||
if self_parameter_type.check(other_parameter_type).is_err() {
|
|
||||||
return Err(Error::TypeCheck {
|
|
||||||
expected: self.clone(),
|
|
||||||
actual: other.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if self_return_type.check(other_return_type).is_err() {
|
|
||||||
Err(Error::TypeCheck {
|
|
||||||
expected: self.clone(),
|
|
||||||
actual: other.clone(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Err(Error::TypeCheck {
|
|
||||||
expected: self.clone(),
|
|
||||||
actual: other.clone(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AbstractTree for Type {
|
|
||||||
fn from_syntax_node(_source: &str, node: Node, _context: &Map) -> Result<Self> {
|
|
||||||
Error::expect_syntax_node(_source, "type", node)?;
|
|
||||||
|
|
||||||
let type_node = node.child(0).unwrap();
|
|
||||||
|
|
||||||
let r#type = match type_node.kind() {
|
|
||||||
"[" => {
|
|
||||||
let item_type_node = node.child(1).unwrap();
|
|
||||||
let item_type = Type::from_syntax_node(_source, item_type_node, _context)?;
|
|
||||||
|
|
||||||
Type::List(Box::new(item_type))
|
|
||||||
}
|
|
||||||
"any" => Type::Any,
|
|
||||||
"bool" => Type::Boolean,
|
|
||||||
"collection" => Type::Collection,
|
|
||||||
"float" => Type::Float,
|
|
||||||
"(" => {
|
|
||||||
let child_count = node.child_count();
|
|
||||||
let mut parameter_types = Vec::new();
|
|
||||||
|
|
||||||
for index in 1..child_count - 2 {
|
|
||||||
let child = node.child(index).unwrap();
|
|
||||||
|
|
||||||
if child.is_named() {
|
|
||||||
let parameter_type = Type::from_syntax_node(_source, child, _context)?;
|
|
||||||
|
|
||||||
parameter_types.push(parameter_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let final_node = node.child(child_count - 1).unwrap();
|
|
||||||
let return_type = if final_node.is_named() {
|
|
||||||
Type::from_syntax_node(_source, final_node, _context)?
|
|
||||||
} else {
|
|
||||||
Type::None
|
|
||||||
};
|
|
||||||
|
|
||||||
Type::Function {
|
|
||||||
parameter_types,
|
|
||||||
return_type: Box::new(return_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"int" => Type::Integer,
|
|
||||||
"map" => Type::Map(None),
|
|
||||||
"num" => Type::Number,
|
|
||||||
"none" => Type::None,
|
|
||||||
"str" => Type::String,
|
|
||||||
"option" => {
|
|
||||||
let inner_type_node = node.child(2).unwrap();
|
|
||||||
let inner_type = Type::from_syntax_node(_source, inner_type_node, _context)?;
|
|
||||||
|
|
||||||
Type::Option(Box::new(inner_type))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(Error::UnexpectedSyntaxNode {
|
|
||||||
expected: "any, bool, float, int, num, str, option, (, [ or {".to_string(),
|
|
||||||
actual: type_node.kind().to_string(),
|
|
||||||
location: type_node.start_position(),
|
|
||||||
relevant_source: _source[type_node.byte_range()].to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(r#type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
|
||||||
Ok(Value::none())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
|
||||||
Ok(Type::None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Type {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Type::Any => write!(f, "any"),
|
|
||||||
Type::Boolean => write!(f, "bool"),
|
|
||||||
Type::Collection => write!(f, "collection"),
|
|
||||||
Type::Float => write!(f, "float"),
|
|
||||||
Type::Function {
|
|
||||||
parameter_types,
|
|
||||||
return_type,
|
|
||||||
} => {
|
|
||||||
write!(f, "(")?;
|
|
||||||
|
|
||||||
for (index, parameter_type) in parameter_types.iter().enumerate() {
|
|
||||||
write!(f, "{parameter_type}")?;
|
|
||||||
|
|
||||||
if index != parameter_types.len() - 1 {
|
|
||||||
write!(f, " ")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, ")")?;
|
|
||||||
write!(f, " -> {return_type}")
|
|
||||||
}
|
|
||||||
Type::Integer => write!(f, "int"),
|
|
||||||
Type::List(item_type) => write!(f, "[{item_type}]"),
|
|
||||||
Type::Map(_) => write!(f, "map"),
|
|
||||||
Type::Number => write!(f, "num"),
|
|
||||||
Type::None => write!(f, "none"),
|
|
||||||
Type::String => write!(f, "str"),
|
|
||||||
Type::Option(inner_type) => {
|
|
||||||
write!(f, "option({})", inner_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
use std::{
|
use std::{collections::BTreeMap, fmt::Write};
|
||||||
collections::BTreeMap,
|
|
||||||
fmt::{self, Display, Formatter},
|
|
||||||
};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AbstractTree, BuiltInValue, Error, Expression, Function, Identifier, List, Map, Result,
|
AbstractTree, BuiltInValue, Error, Expression, Format, Function, FunctionNode, Identifier,
|
||||||
Statement, Structure, Type, TypeDefinition, Value,
|
List, Map, Result, Statement, Structure, Type, TypeDefinition, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
@ -33,7 +30,11 @@ impl AbstractTree for ValueNode {
|
|||||||
let value_node = match child.kind() {
|
let value_node = match child.kind() {
|
||||||
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
|
"boolean" => ValueNode::Boolean(source[child.byte_range()].to_string()),
|
||||||
"float" => ValueNode::Float(source[child.byte_range()].to_string()),
|
"float" => ValueNode::Float(source[child.byte_range()].to_string()),
|
||||||
"function" => ValueNode::Function(Function::from_syntax_node(source, child, context)?),
|
"function" => {
|
||||||
|
let function_node = FunctionNode::from_syntax_node(source, child, context)?;
|
||||||
|
|
||||||
|
ValueNode::Function(Function::ContextDefined(function_node))
|
||||||
|
}
|
||||||
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
||||||
"string" => {
|
"string" => {
|
||||||
let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
|
let without_quotes = child.start_byte() + 1..child.end_byte() - 1;
|
||||||
@ -300,53 +301,75 @@ impl AbstractTree for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for ValueNode {
|
impl Format for ValueNode {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
match self {
|
match self {
|
||||||
ValueNode::Boolean(source)
|
ValueNode::Boolean(source)
|
||||||
| ValueNode::Float(source)
|
| ValueNode::Float(source)
|
||||||
| ValueNode::Integer(source)
|
| ValueNode::Integer(source)
|
||||||
| ValueNode::String(source) => write!(f, "{source}"),
|
| ValueNode::String(source) => output.push_str(source),
|
||||||
ValueNode::Function(function) => write!(f, "{function}"),
|
ValueNode::Function(function) => function.format(output, indent_level),
|
||||||
ValueNode::List(expressions) => {
|
ValueNode::List(expressions) => {
|
||||||
|
output.push('[');
|
||||||
|
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
write!(f, "{expression}")?;
|
expression.format(output, indent_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
output.push(']');
|
||||||
}
|
}
|
||||||
ValueNode::Option(option) => {
|
ValueNode::Option(option) => {
|
||||||
if let Some(expression) = option {
|
if let Some(expression) = option {
|
||||||
write!(f, "some({})", expression)
|
output.push_str("some(");
|
||||||
|
expression.format(output, indent_level);
|
||||||
|
output.push(')');
|
||||||
} else {
|
} else {
|
||||||
write!(f, "none")
|
output.push_str("none");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ValueNode::Map(nodes) => {
|
ValueNode::Map(nodes) => {
|
||||||
writeln!(f, "{{")?;
|
output.push('{');
|
||||||
|
|
||||||
for (key, (statement, type_option)) in nodes {
|
for (key, (statement, type_option)) in nodes {
|
||||||
if let Some(r#type) = type_option {
|
if let Some(r#type) = type_option {
|
||||||
writeln!(f, " {key} <{}> = {statement}", r#type)?;
|
output.push_str(" ");
|
||||||
|
output.push_str(key);
|
||||||
|
output.push_str(" <");
|
||||||
|
r#type.format(output, indent_level);
|
||||||
|
output.push_str("> = ");
|
||||||
|
statement.format(output, indent_level);
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, " {key} = {statement}")?;
|
output.push_str(" ");
|
||||||
|
output.push_str(key);
|
||||||
|
output.push_str(" = ");
|
||||||
|
statement.format(output, indent_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(f, "}}")
|
|
||||||
|
output.push('}');
|
||||||
}
|
}
|
||||||
ValueNode::BuiltInValue(built_in_value) => write!(f, "{built_in_value}"),
|
ValueNode::BuiltInValue(built_in_value) => built_in_value.format(output, indent_level),
|
||||||
ValueNode::Structure(nodes) => {
|
ValueNode::Structure(nodes) => {
|
||||||
writeln!(f, "{{")?;
|
output.push('{');
|
||||||
|
|
||||||
for (key, (value_option, r#type)) in nodes {
|
for (key, (value_option, r#type)) in nodes {
|
||||||
if let Some(value) = value_option {
|
if let Some(value) = value_option {
|
||||||
writeln!(f, " {key} <{}> = {value}", r#type)?;
|
output.push_str(" ");
|
||||||
|
output.push_str(key);
|
||||||
|
output.push_str(" <");
|
||||||
|
r#type.format(output, indent_level);
|
||||||
|
output.push_str("> = ");
|
||||||
|
value.format(output, indent_level);
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, " {key} <{}>", r#type)?;
|
output.push_str(" ");
|
||||||
|
output.push_str(key);
|
||||||
|
output.push_str(" <");
|
||||||
|
r#type.format(output, indent_level);
|
||||||
|
output.push('>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "}}")
|
output.push('}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{AbstractTree, Block, Error, Expression, Map, Result, Type, Value};
|
use crate::{AbstractTree, Block, Error, Expression, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
/// Abstract representation of a while loop.
|
/// Abstract representation of a while loop.
|
||||||
///
|
///
|
||||||
@ -40,10 +38,11 @@ impl AbstractTree for While {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for While {
|
impl Format for While {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let While { expression, block } = self;
|
output.push_str("while ");
|
||||||
|
self.expression.format(output, indent_level);
|
||||||
write!(f, "while {expression} {{{block}}}")
|
output.push(' ');
|
||||||
|
self.expression.format(output, indent_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
use tree_sitter::Node;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
function_expression::FunctionExpression, AbstractTree, Error, Expression, FunctionCall, Map,
|
function_expression::FunctionExpression, AbstractTree, Error, Expression, Format, FunctionCall,
|
||||||
Result, Type, Value,
|
Map, Result, Type, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstract representation of a yield expression.
|
/// Abstract representation of a yield expression.
|
||||||
@ -55,8 +53,8 @@ impl AbstractTree for Yield {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Yield {
|
impl Format for Yield {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
write!(f, "{}", self.call)
|
self.call.format(output, indent_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
mod string;
|
mod string;
|
||||||
|
|
||||||
use std::fs::read_to_string;
|
use std::{
|
||||||
|
fmt::{self, Display, Formatter},
|
||||||
|
fs::read_to_string,
|
||||||
|
};
|
||||||
|
|
||||||
use rand::{random, thread_rng, Rng};
|
use rand::{random, thread_rng, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{Error, Map, Result, Type, Value};
|
use crate::{Error, Format, Map, Result, Type, Value};
|
||||||
|
|
||||||
pub use string::{string_functions, StringFunction};
|
pub use string::{string_functions, StringFunction};
|
||||||
|
|
||||||
@ -148,3 +151,15 @@ impl BuiltInFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Format for BuiltInFunction {
|
||||||
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
|
output.push_str(self.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for BuiltInFunction {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//! functions or by constructing your own Evaluator.
|
//! functions or by constructing your own Evaluator.
|
||||||
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
use tree_sitter::{Node, Parser, Tree as TSTree, TreeCursor};
|
||||||
|
|
||||||
use crate::{language, AbstractTree, Error, Map, Result, Root, Value};
|
use crate::{language, AbstractTree, Error, Format, Map, Result, Root, Value};
|
||||||
|
|
||||||
/// Interpret the given source code.
|
/// Interpret the given source code.
|
||||||
///
|
///
|
||||||
@ -132,7 +132,11 @@ impl Interpreter {
|
|||||||
|
|
||||||
pub fn format(&self) -> String {
|
pub fn format(&self) -> String {
|
||||||
if let Some(root_node) = &self.abstract_tree {
|
if let Some(root_node) = &self.abstract_tree {
|
||||||
root_node.to_string()
|
let mut formatted_source = String::new();
|
||||||
|
|
||||||
|
root_node.format(&mut formatted_source, 0);
|
||||||
|
|
||||||
|
formatted_source
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tree_sitter::Node;
|
|
||||||
|
|
||||||
use crate::{AbstractTree, BuiltInFunction, FunctionNode, Map, Result, Type, Value};
|
use crate::{BuiltInFunction, Format, FunctionNode, Map, Result, Type, Value};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum Function {
|
pub enum Function {
|
||||||
@ -11,17 +10,6 @@ pub enum Function {
|
|||||||
ContextDefined(FunctionNode),
|
ContextDefined(FunctionNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Function {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Function::BuiltIn(built_in_function) => write!(f, "{}", built_in_function.r#type()),
|
|
||||||
Function::ContextDefined(function_node) => {
|
|
||||||
write!(f, "{}", function_node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn call(
|
pub fn call(
|
||||||
&self,
|
&self,
|
||||||
@ -50,30 +38,20 @@ impl Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Function {
|
impl Format for Function {
|
||||||
fn from_syntax_node(_source: &str, _node: Node, _context: &Map) -> Result<Self> {
|
fn format(&self, output: &mut String, indent_level: u8) {
|
||||||
let inner_function = FunctionNode::from_syntax_node(_source, _node, _context)?;
|
|
||||||
|
|
||||||
Ok(Function::ContextDefined(inner_function))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
|
|
||||||
match self {
|
match self {
|
||||||
Function::BuiltIn(_) => Ok(()),
|
Function::BuiltIn(built_in_function) => built_in_function.format(output, indent_level),
|
||||||
Function::ContextDefined(defined_function) => {
|
Function::ContextDefined(function_node) => function_node.format(output, indent_level),
|
||||||
defined_function.check_type(_source, _context)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
impl Display for Function {
|
||||||
fn run(&self, _source: &str, _context: &Map) -> Result<Value> {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
Ok(Value::Function(self.clone()))
|
match self {
|
||||||
}
|
Function::BuiltIn(built_in_function) => write!(f, "{built_in_function}"),
|
||||||
|
Function::ContextDefined(function_node) => write!(f, "{function_node}"),
|
||||||
fn expected_type(&self, _context: &Map) -> Result<Type> {
|
|
||||||
match self {
|
|
||||||
Function::BuiltIn(built_in) => Ok(built_in.r#type()),
|
|
||||||
Function::ContextDefined(context_defined) => Ok(context_defined.r#type().clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +527,7 @@ impl Serialize for Value {
|
|||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::String(string) => write!(f, "{}", string.read().unwrap()),
|
Value::String(string) => write!(f, "'{}'", string.read().unwrap()),
|
||||||
Value::Float(float) => write!(f, "{float}"),
|
Value::Float(float) => write!(f, "{float}"),
|
||||||
Value::Integer(int) => write!(f, "{int}"),
|
Value::Integer(int) => write!(f, "{int}"),
|
||||||
Value::Boolean(boolean) => write!(f, "{boolean}"),
|
Value::Boolean(boolean) => write!(f, "{boolean}"),
|
||||||
|
Loading…
Reference in New Issue
Block a user