Improve AST construction and errors
This commit is contained in:
parent
9994919127
commit
c9c7eb3173
44
src/error.rs
44
src/error.rs
@ -2,6 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! To deal with errors from dependencies, either create a new error variant
|
//! To deal with errors from dependencies, either create a new error variant
|
||||||
//! or use the MacroFailure variant if the error can only occur inside a macro.
|
//! or use the MacroFailure variant if the error can only occur inside a macro.
|
||||||
|
|
||||||
use crate::{value::value_type::ValueType, value::Value, ToolInfo};
|
use crate::{value::value_type::ValueType, value::Value, ToolInfo};
|
||||||
|
|
||||||
use std::{fmt, io, time::SystemTimeError};
|
use std::{fmt, io, time::SystemTimeError};
|
||||||
@ -18,6 +19,10 @@ pub enum Error {
|
|||||||
|
|
||||||
ExpectedFieldName,
|
ExpectedFieldName,
|
||||||
|
|
||||||
|
ExpectedChildNode {
|
||||||
|
empty_node_sexp: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// Dust's internal type checking failed to identify a type mismatch. This should never happen, /// the error prompts the user to report the bug.
|
/// Dust's internal type checking failed to identify a type mismatch. This should never happen, /// the error prompts the user to report the bug.
|
||||||
TypeCheckFailure {
|
TypeCheckFailure {
|
||||||
tool_info: ToolInfo<'static>,
|
tool_info: ToolInfo<'static>,
|
||||||
@ -290,14 +295,6 @@ impl From<toml::de::Error> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub(crate) fn expect_operator_argument_amount(actual: usize, expected: usize) -> Result<()> {
|
|
||||||
if actual == expected {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::ExpectedOperatorArgumentAmount { expected, actual })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn expect_function_argument_amount(
|
pub(crate) fn expect_function_argument_amount(
|
||||||
identifier: &str,
|
identifier: &str,
|
||||||
actual: usize,
|
actual: usize,
|
||||||
@ -389,36 +386,6 @@ impl Error {
|
|||||||
Error::ExpectedCollection { actual }
|
Error::ExpectedCollection { actual }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn addition_error(augend: Value, addend: Value) -> Self {
|
|
||||||
Error::AdditionError { augend, addend }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn subtraction_error(minuend: Value, subtrahend: Value) -> Self {
|
|
||||||
Error::SubtractionError {
|
|
||||||
minuend,
|
|
||||||
subtrahend,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn negation_error(argument: Value) -> Self {
|
|
||||||
Error::NegationError { argument }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn multiplication_error(multiplicand: Value, multiplier: Value) -> Self {
|
|
||||||
Error::MultiplicationError {
|
|
||||||
multiplicand,
|
|
||||||
multiplier,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn division_error(dividend: Value, divisor: Value) -> Self {
|
|
||||||
Error::DivisionError { dividend, divisor }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn modulation_error(dividend: Value, divisor: Value) -> Self {
|
|
||||||
Error::ModulationError { dividend, divisor }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs `EvalexprError::InvalidRegex(regex)`
|
/// Constructs `EvalexprError::InvalidRegex(regex)`
|
||||||
pub fn invalid_regex(regex: String, message: String) -> Self {
|
pub fn invalid_regex(regex: String, message: String) -> Self {
|
||||||
Error::InvalidRegex { regex, message }
|
Error::InvalidRegex { regex, message }
|
||||||
@ -588,6 +555,7 @@ impl fmt::Display for Error {
|
|||||||
UnexpectedSourceNode { expected, actual } => write!(f, "Unexpected source node. Expected {expected}, but found {actual}."),
|
UnexpectedSourceNode { expected, actual } => write!(f, "Unexpected source node. Expected {expected}, but found {actual}."),
|
||||||
ExpectedFieldName => write!(f, "Expected a field name for this node, but none was found."),
|
ExpectedFieldName => write!(f, "Expected a field name for this node, but none was found."),
|
||||||
WrongTypeCombination { expected, actual } => write!(f, "Wrong type combination. Expected {expected}, found {actual}."),
|
WrongTypeCombination { expected, actual } => write!(f, "Wrong type combination. Expected {expected}, found {actual}."),
|
||||||
|
ExpectedChildNode { empty_node_sexp } => write!(f, "Expected this node to have a child, {empty_node_sexp}."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! The top level of Dust's API with functions to interpret Dust code.
|
//! The top level of Dust's API with functions to interpret Dust code.
|
||||||
|
|
||||||
|
use egui::util::id_type_map;
|
||||||
use tree_sitter::{Node, Parser, Tree, TreeCursor};
|
use tree_sitter::{Node, Parser, Tree, TreeCursor};
|
||||||
|
|
||||||
use crate::{language, Error, Result, Value, VariableMap};
|
use crate::{language, Error, Result, Value, VariableMap};
|
||||||
@ -33,11 +34,11 @@ pub fn eval(source: &str) -> Vec<Result<Value>> {
|
|||||||
/// context.set_value("two".into(), 2.into()).unwrap(); // Do proper error handling here
|
/// context.set_value("two".into(), 2.into()).unwrap(); // Do proper error handling here
|
||||||
/// context.set_value("three".into(), 3.into()).unwrap(); // Do proper error handling here
|
/// context.set_value("three".into(), 3.into()).unwrap(); // Do proper error handling here
|
||||||
///
|
///
|
||||||
/// let dust_code = "one + two + three; one - two - three;";
|
/// let dust_code = "four = 4; one + two + three + four;";
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// eval_with_context(dust_code, &mut context),
|
/// eval_with_context(dust_code, &mut context),
|
||||||
/// vec![Ok(Value::from(6)), Ok(Value::from(-4))]
|
/// vec![Ok(Value::Empty), Ok(Value::from(10))]
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<Value>> {
|
pub fn eval_with_context(source: &str, context: &mut VariableMap) -> Vec<Result<Value>> {
|
||||||
@ -74,10 +75,18 @@ struct Evaluator {
|
|||||||
impl Evaluator {
|
impl Evaluator {
|
||||||
fn new(tree: Tree, source: &str) -> Result<Self> {
|
fn new(tree: Tree, source: &str) -> Result<Self> {
|
||||||
let root_node = tree.root_node();
|
let root_node = tree.root_node();
|
||||||
|
let mut cursor = tree.walk();
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
let item = Item::new(root_node, source)?;
|
for (index, node) in root_node.children(&mut cursor).enumerate() {
|
||||||
items.push(item);
|
let item = Item::new(node, source)?;
|
||||||
|
|
||||||
|
items.push(item);
|
||||||
|
|
||||||
|
if index == root_node.child_count() - 1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Evaluator { items })
|
Ok(Evaluator { items })
|
||||||
}
|
}
|
||||||
@ -150,9 +159,14 @@ enum Statement {
|
|||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(node: Node, source: &str) -> Result<Self> {
|
||||||
|
let node = if node.kind() == "statement" {
|
||||||
|
node.child(0).unwrap()
|
||||||
|
} else {
|
||||||
|
node
|
||||||
|
};
|
||||||
let child = node.child(0).unwrap();
|
let child = node.child(0).unwrap();
|
||||||
|
|
||||||
match child.kind() {
|
match node.kind() {
|
||||||
"closed_statement" => Ok(Statement::Closed(Expression::new(child, source)?)),
|
"closed_statement" => Ok(Statement::Closed(Expression::new(child, source)?)),
|
||||||
"open_statement" => Ok(Self::Open(Expression::new(child, source)?)),
|
"open_statement" => Ok(Self::Open(Expression::new(child, source)?)),
|
||||||
_ => Err(Error::UnexpectedSourceNode {
|
_ => Err(Error::UnexpectedSourceNode {
|
||||||
@ -189,31 +203,31 @@ enum Expression {
|
|||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
fn new(node: Node, source: &str) -> Result<Self> {
|
fn new(node: Node, source: &str) -> Result<Self> {
|
||||||
let mut child = node.child(0).unwrap();
|
let node = if node.kind() == "expression" {
|
||||||
|
node.child(0).unwrap()
|
||||||
|
} else {
|
||||||
|
node
|
||||||
|
};
|
||||||
|
|
||||||
if child.kind() == "expression" {
|
if node.kind() == "identifier" {
|
||||||
child = child.child(0).unwrap();
|
let byte_range = node.byte_range();
|
||||||
}
|
|
||||||
|
|
||||||
if child.kind() == "identifier" {
|
|
||||||
let byte_range = child.byte_range();
|
|
||||||
let identifier = &source[byte_range];
|
let identifier = &source[byte_range];
|
||||||
|
|
||||||
Ok(Self::Identifier(identifier.to_string()))
|
Ok(Self::Identifier(identifier.to_string()))
|
||||||
} else if child.kind() == "value" {
|
} else if node.kind() == "value" {
|
||||||
Ok(Expression::Value(Value::new(child, source)?))
|
Ok(Expression::Value(Value::new(node, source)?))
|
||||||
} else if child.kind() == "operation" {
|
} else if node.kind() == "operation" {
|
||||||
Ok(Expression::Operation(Box::new(Operation::new(
|
Ok(Expression::Operation(Box::new(Operation::new(
|
||||||
child, source,
|
node, source,
|
||||||
)?)))
|
)?)))
|
||||||
} else if child.kind() == "control_flow" {
|
} else if node.kind() == "control_flow" {
|
||||||
Ok(Expression::ControlFlow(Box::new(ControlFlow::new(
|
Ok(Expression::ControlFlow(Box::new(ControlFlow::new(
|
||||||
child, source,
|
node, source,
|
||||||
)?)))
|
)?)))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::UnexpectedSourceNode {
|
Err(Error::UnexpectedSourceNode {
|
||||||
expected: "identifier, operation, control_flow or value",
|
expected: "identifier, operation, control_flow or value",
|
||||||
actual: child.kind(),
|
actual: node.kind(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +314,7 @@ impl Sub for Value {
|
|||||||
|
|
||||||
Ok(Value::Float(addition))
|
Ok(Value::Float(addition))
|
||||||
}
|
}
|
||||||
(Value::Float(_), other) | (other, Value::Float(_)) => Err(Error::ExpectedFloat {
|
(Value::Float(_), other) | (other, Value::Float(_)) => Err(Error::ExpectedNumber {
|
||||||
actual: other.clone(),
|
actual: other.clone(),
|
||||||
}),
|
}),
|
||||||
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)),
|
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)),
|
||||||
|
Loading…
Reference in New Issue
Block a user