Run addition and subtration operations
This commit is contained in:
parent
589d66a90f
commit
adbd69b17c
199
src/interface.rs
199
src/interface.rs
@ -2,9 +2,9 @@
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
use tree_sitter::{Parser, TreeCursor};
|
||||
use tree_sitter::{Node, Parser, Tree, TreeCursor};
|
||||
|
||||
use crate::{language, token, tree, Error, Result, Value, VariableMap};
|
||||
use crate::{language, Error, Result, Value, VariableMap};
|
||||
|
||||
/// Evaluate the given expression string.
|
||||
///
|
||||
@ -34,51 +34,103 @@ pub fn eval(source: &str) -> Result<Value> {
|
||||
/// context.set_value("three".into(), 3.into()).unwrap(); // Do proper error handling here
|
||||
/// assert_eq!(eval_with_context("one + two + three", &mut context), Ok(Value::from(6)));
|
||||
/// ```
|
||||
pub fn eval_with_context(input: &str, context: &mut VariableMap) -> Result<Value> {
|
||||
pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Result<Value> {
|
||||
let mut parser = Parser::new();
|
||||
|
||||
parser.set_language(language()).unwrap();
|
||||
|
||||
let tree = parser.parse(input, None).unwrap();
|
||||
let tree = parser.parse(source, None).unwrap();
|
||||
let sexp = tree.root_node().to_sexp();
|
||||
|
||||
println!("{sexp}");
|
||||
|
||||
let evaluator = Evaluator::new(tree.clone(), source).unwrap();
|
||||
let mut cursor = tree.walk();
|
||||
|
||||
cursor.goto_first_child();
|
||||
let results = evaluator.run(context, &mut cursor, source);
|
||||
|
||||
let statement = Statement::from_cursor(cursor);
|
||||
|
||||
println!("{statement:?}");
|
||||
println!("{evaluator:?}");
|
||||
println!("{results:?}");
|
||||
|
||||
Ok(Value::Empty)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EvalTree {
|
||||
root: Source,
|
||||
struct Evaluator {
|
||||
items: Vec<Item>,
|
||||
}
|
||||
|
||||
impl Evaluator {
|
||||
fn new(tree: Tree, source: &str) -> Result<Self> {
|
||||
let mut cursor = tree.walk();
|
||||
let root_node = cursor.node();
|
||||
let mut items = Vec::new();
|
||||
|
||||
for node in root_node.children(&mut cursor) {
|
||||
let item = Item::new(node, source)?;
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
Ok(Evaluator { items })
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &mut VariableMap,
|
||||
mut cursor: &mut TreeCursor,
|
||||
source: &str,
|
||||
) -> Vec<Result<Value>> {
|
||||
let mut results = Vec::with_capacity(self.items.len());
|
||||
|
||||
for root in &self.items {
|
||||
match root {
|
||||
Item::Comment(comment) => results.push(Ok(Value::String(comment.clone()))),
|
||||
Item::Statement(statement) => {
|
||||
results.push(statement.run(context, &mut cursor, source))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Source {
|
||||
enum Item {
|
||||
Comment(String),
|
||||
Statement(Statement),
|
||||
}
|
||||
|
||||
impl Item {
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
if node.kind() == "comment" {
|
||||
let byte_range = node.byte_range();
|
||||
let value_string = &source[byte_range];
|
||||
|
||||
Ok(Item::Comment(value_string.to_string()))
|
||||
} else if node.kind() == "statement" {
|
||||
Ok(Item::Statement(Statement::new(node, source)?))
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "comment or statement",
|
||||
actual: node.kind(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Statement {
|
||||
Closed(Expression),
|
||||
}
|
||||
|
||||
impl Statement {
|
||||
fn from_cursor(mut cursor: TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
|
||||
cursor.goto_first_child();
|
||||
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
if node.kind() == "statement" {
|
||||
Ok(Statement::Closed(Expression::from_cursor(cursor)?))
|
||||
Ok(Statement::Closed(Expression::new(
|
||||
node.child(0).unwrap(),
|
||||
source,
|
||||
)?))
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "statement",
|
||||
@ -86,42 +138,117 @@ impl Statement {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &mut VariableMap,
|
||||
mut cursor: &mut TreeCursor,
|
||||
source: &str,
|
||||
) -> Result<Value> {
|
||||
match self {
|
||||
Statement::Closed(expression) => expression.run(context, &mut cursor, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Expression {
|
||||
Identifier(&'static str),
|
||||
Value(Range<usize>),
|
||||
Value(Value),
|
||||
Operation(Operation),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn from_cursor(mut cursor: TreeCursor) -> Result<Self> {
|
||||
let parent = cursor.node();
|
||||
|
||||
cursor.goto_first_child();
|
||||
|
||||
let child = cursor.node();
|
||||
|
||||
if parent.kind() == "expression" {
|
||||
if child.kind() == "identifier" {
|
||||
if let Some(name) = cursor.field_name() {
|
||||
Ok(Expression::Identifier(name))
|
||||
} else {
|
||||
Err(Error::ExpectedFieldName)
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
if node.kind() != "expression" {
|
||||
return Err(Error::UnexpectedSourceNode {
|
||||
expected: "expression",
|
||||
actual: node.kind(),
|
||||
});
|
||||
}
|
||||
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
if child.kind() == "identifier" {
|
||||
todo!()
|
||||
} else if child.kind() == "value" {
|
||||
Ok(Self::Value(child.byte_range()))
|
||||
Ok(Expression::Value(Value::new(child, source)?))
|
||||
} else if child.kind() == "operation" {
|
||||
Ok(Expression::Operation(Operation::new(child, source)?))
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "identifier or value",
|
||||
expected: "identifier, operation or value",
|
||||
actual: child.kind(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &mut VariableMap,
|
||||
mut cursor: &mut TreeCursor,
|
||||
source: &str,
|
||||
) -> Result<Value> {
|
||||
match self {
|
||||
Expression::Identifier(identifier) => {
|
||||
let value = context.get_value(&identifier)?;
|
||||
|
||||
if let Some(value) = value {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "expression",
|
||||
actual: parent.kind(),
|
||||
Ok(Value::Empty)
|
||||
}
|
||||
}
|
||||
Expression::Value(value) => Ok(value.clone()),
|
||||
Expression::Operation(operation) => operation.run(context, &mut cursor, source),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Operation {
|
||||
left: Box<Expression>,
|
||||
operator: &'static str,
|
||||
right: Box<Expression>,
|
||||
}
|
||||
|
||||
impl Operation {
|
||||
fn new(node: Node, source: &str) -> Result<Self> {
|
||||
let first_child = node.child(0).unwrap();
|
||||
let second_child = node.child(1).unwrap();
|
||||
let third_child = node.child(2).unwrap();
|
||||
let left = { Box::new(Expression::new(first_child, source)?) };
|
||||
let operator = { second_child.child(0).unwrap().kind() };
|
||||
let right = { Box::new(Expression::new(third_child, source)?) };
|
||||
|
||||
Ok(Operation {
|
||||
left,
|
||||
operator,
|
||||
right,
|
||||
})
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
context: &mut VariableMap,
|
||||
mut cursor: &mut TreeCursor,
|
||||
source: &str,
|
||||
) -> Result<Value> {
|
||||
let left = self.left.run(context, &mut cursor, source)?;
|
||||
let right = self.right.run(context, &mut cursor, source)?;
|
||||
|
||||
match self.operator {
|
||||
"+" => {
|
||||
let integer_result = left.as_int()? + right.as_int()?;
|
||||
|
||||
Ok(Value::Integer(integer_result))
|
||||
}
|
||||
"-" => {
|
||||
let integer_result = left.as_int()? - right.as_int()?;
|
||||
|
||||
Ok(Value::Integer(integer_result))
|
||||
}
|
||||
_ => Ok(Value::Empty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use serde::{
|
||||
ser::SerializeTuple,
|
||||
Deserialize, Serialize, Serializer,
|
||||
};
|
||||
use tree_sitter::{Node, TreeCursor};
|
||||
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
@ -46,6 +47,31 @@ pub enum Value {
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn new(node: Node, source: &str) -> Result<Self> {
|
||||
let child = node.child(0).unwrap();
|
||||
|
||||
if node.kind() != "value" {
|
||||
return Err(Error::UnexpectedSourceNode {
|
||||
expected: "value",
|
||||
actual: node.kind(),
|
||||
});
|
||||
}
|
||||
|
||||
let value_snippet = &source[child.byte_range()];
|
||||
|
||||
match child.kind() {
|
||||
"integer" => {
|
||||
let raw = value_snippet.parse::<i64>().unwrap_or_default();
|
||||
|
||||
Ok(Value::Integer(raw))
|
||||
}
|
||||
_ => Err(Error::UnexpectedSourceNode {
|
||||
expected: "raw value",
|
||||
actual: child.kind(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
ValueType::from(self)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user