Rename AbstractTree; Add new AbstractTree type

This commit is contained in:
Jeff 2024-03-20 00:28:28 -04:00
parent d46a592f87
commit 896a0855e0
22 changed files with 150 additions and 91 deletions

View File

@ -4,7 +4,7 @@ use crate::{
Context, Value,
};
use super::{AbstractTree, Action, Identifier, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Identifier, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment {
@ -37,7 +37,7 @@ impl Assignment {
}
}
impl AbstractTree for Assignment {
impl AbstractNode for Assignment {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}

View File

@ -3,7 +3,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block {
@ -20,7 +20,7 @@ impl Block {
}
}
impl AbstractTree for Block {
impl AbstractNode for Block {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
if let Some(statement) = self.statements.last() {
statement.node.expected_type(_context)

View File

@ -4,7 +4,7 @@ use crate::{
};
use super::{
AbstractTree, Action, FunctionCall, Identifier, ListIndex, Logic, MapIndex, Math, Type,
AbstractNode, Action, FunctionCall, Identifier, ListIndex, Logic, MapIndex, Math, Type,
ValueNode,
};
@ -19,7 +19,7 @@ pub enum Expression {
Value(ValueNode),
}
impl AbstractTree for Expression {
impl AbstractNode for Expression {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.expected_type(_context),

View File

@ -4,7 +4,7 @@ use crate::{
value::ValueInner,
};
use super::{AbstractTree, Action, Expression, Type, WithPosition};
use super::{AbstractNode, Action, Expression, Type, WithPosition};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall {
@ -24,7 +24,7 @@ impl FunctionCall {
}
}
impl AbstractTree for FunctionCall {
impl AbstractNode for FunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let function_node_type = self.function.node.expected_type(_context)?;

View File

@ -8,7 +8,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Type};
use super::{AbstractNode, Action, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(Arc<String>);
@ -23,7 +23,7 @@ impl Identifier {
}
}
impl AbstractTree for Identifier {
impl AbstractNode for Identifier {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
if let Some(r#type) = context.get_type(self)? {
Ok(r#type)

View File

@ -4,7 +4,7 @@ use crate::{
value::ValueInner,
};
use super::{AbstractTree, Action, Block, Expression, Type, WithPosition};
use super::{AbstractNode, Action, Block, Expression, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse {
@ -27,7 +27,7 @@ impl IfElse {
}
}
impl AbstractTree for IfElse {
impl AbstractNode for IfElse {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
self.if_block.expected_type(_context)
}

View File

@ -3,7 +3,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Expression, Type, ValueNode, WithPosition};
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ListIndex {
@ -17,7 +17,7 @@ impl ListIndex {
}
}
impl AbstractTree for ListIndex {
impl AbstractNode for ListIndex {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let left_type = self.left.node.expected_type(_context)?;

View File

@ -5,7 +5,7 @@ use crate::{
Value,
};
use super::{AbstractTree, Action, Expression, Type, WithPosition};
use super::{AbstractNode, Action, Expression, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Logic {
@ -20,7 +20,7 @@ pub enum Logic {
Not(WithPosition<Expression>),
}
impl AbstractTree for Logic {
impl AbstractNode for Logic {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::Boolean)
}

View File

@ -5,7 +5,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
#[derive(Clone, Debug)]
pub struct Loop {
@ -18,7 +18,7 @@ impl Loop {
}
}
impl AbstractTree for Loop {
impl AbstractNode for Loop {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}

View File

@ -4,7 +4,7 @@ use crate::{
value::ValueInner,
};
use super::{AbstractTree, Action, Expression, Type, ValueNode, WithPosition};
use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MapIndex {
@ -18,7 +18,7 @@ impl MapIndex {
}
}
impl AbstractTree for MapIndex {
impl AbstractNode for MapIndex {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
let left_type = self.left.node.expected_type(context)?;

View File

@ -5,7 +5,7 @@ use crate::{
Value,
};
use super::{AbstractTree, Action, Expression, SourcePosition, Type, WithPosition};
use super::{AbstractNode, Action, Expression, SourcePosition, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Math {
@ -16,7 +16,7 @@ pub enum Math {
Modulo(WithPosition<Expression>, WithPosition<Expression>),
}
impl AbstractTree for Math {
impl AbstractNode for Math {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Math::Add(left, _)

View File

@ -15,6 +15,8 @@ pub mod r#type;
pub mod value_node;
pub mod r#while;
use std::ops::Index;
use chumsky::span::{SimpleSpan, Span};
pub use self::{
@ -38,7 +40,7 @@ pub use self::{
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
error::{Error, RuntimeError, ValidationError},
Value,
};
@ -63,7 +65,94 @@ impl From<(usize, usize)> for SourcePosition {
}
}
pub trait AbstractTree: Sized {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum Action {
Return(Value),
Break,
None,
}
pub struct AbstractTree(Vec<WithPosition<Statement>>);
impl AbstractTree {
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
AbstractTree(statements)
}
pub fn run(self, context: &Context) -> Result<Option<Value>, Vec<Error>> {
let mut valid_statements = Vec::with_capacity(self.0.len());
let mut errors = Vec::new();
for statement in self.0 {
let validation = statement.node.validate(context);
if let Statement::StructureDefinition(_) = statement.node {
match validation {
Ok(_) => {
let run_result = statement.node.run(context);
match run_result {
Ok(_) => {}
Err(runtime_error) => {
return Err(vec![Error::Runtime {
error: runtime_error,
position: statement.position,
}]);
}
}
}
Err(validation_error) => errors.push(Error::Validation {
error: validation_error,
position: statement.position,
}),
}
} else {
match validation {
Ok(_) => valid_statements.push(statement),
Err(validation_error) => errors.push(Error::Validation {
error: validation_error,
position: statement.position,
}),
}
}
}
if !errors.is_empty() {
return Err(errors);
}
let mut previous = None;
for statement in valid_statements {
let run_result = statement.node.run(context);
match run_result {
Ok(action) => match action {
Action::Return(value) => previous = Some(value),
_ => {}
},
Err(runtime_error) => {
return Err(vec![Error::Runtime {
error: runtime_error,
position: statement.position,
}]);
}
}
}
Ok(previous)
}
}
impl Index<usize> for AbstractTree {
type Output = WithPosition<Statement>;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
pub trait AbstractNode: Sized {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
@ -75,10 +164,3 @@ pub trait AbstractTree: Sized {
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum Action {
Return(Value),
Break,
None,
}

View File

@ -4,7 +4,7 @@ use crate::{
};
use super::{
AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type,
AbstractNode, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type,
While,
};
@ -20,7 +20,16 @@ pub enum Statement {
While(While),
}
impl AbstractTree for Statement {
impl Statement {
pub fn kind(&self) -> u8 {
match self {
Statement::StructureDefinition(_) => 0,
_ => 1,
}
}
}
impl AbstractNode for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.expected_type(_context),

View File

@ -3,7 +3,7 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Identifier, Type, WithPosition};
use super::{AbstractNode, Action, Identifier, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructureDefinition {
@ -17,14 +17,12 @@ impl StructureDefinition {
}
}
impl AbstractTree for StructureDefinition {
impl AbstractNode for StructureDefinition {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
context.set_type(self.name.clone(), Type::Named(self.name.clone()))?;
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
Ok(())
}

View File

@ -6,7 +6,7 @@ use crate::{
error::{RuntimeError, TypeConflict, ValidationError},
};
use super::{AbstractTree, Action, WithPosition};
use super::{AbstractNode, Action, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Type {
@ -88,7 +88,7 @@ impl Type {
}
}
impl AbstractTree for Type {
impl AbstractNode for Type {
fn expected_type(&self, _: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}

View File

@ -6,7 +6,7 @@ use crate::{
Value,
};
use super::{AbstractTree, Action, Block, Expression, Identifier, Type, WithPosition};
use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPosition};
#[derive(Clone, Debug, PartialEq)]
pub enum ValueNode {
@ -34,7 +34,7 @@ pub enum ValueNode {
},
}
impl AbstractTree for ValueNode {
impl AbstractNode for ValueNode {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let r#type = match self {
ValueNode::Boolean(_) => Type::Boolean,

View File

@ -5,7 +5,7 @@ use crate::{
Value,
};
use super::{AbstractTree, Action, Expression, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Expression, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct While {
@ -25,7 +25,7 @@ impl While {
}
}
impl AbstractTree for While {
impl AbstractNode for While {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
Ok(Type::None)
}

View File

@ -32,10 +32,8 @@ impl Context {
let mut self_data = self.inner.write()?;
for (identifier, value_data) in other.inner.read()?.iter() {
if let ValueData::Type(r#type) = value_data {
if let Type::Function { .. } = r#type {
self_data.insert(identifier.clone(), value_data.clone());
}
if let ValueData::Type(Type::Function { .. }) = value_data {
self_data.insert(identifier.clone(), value_data.clone());
}
}

View File

@ -5,7 +5,6 @@ pub mod lexer;
pub mod parser;
pub mod value;
use abstract_tree::{AbstractTree, Action, WithPosition};
use context::Context;
use error::Error;
use lexer::lex;
@ -30,41 +29,9 @@ impl Interpreter {
pub fn run(&mut self, source: &str) -> Result<Option<Value>, Vec<Error>> {
let tokens = lex(source)?;
let statements = parse(&tokens)?;
let errors = statements
.iter()
.filter_map(|WithPosition { node, position }| {
node.validate(&self.context)
.err()
.map(|error| Error::Validation {
error,
position: position.clone(),
})
})
.collect::<Vec<Error>>();
let abstract_tree = parse(&tokens)?;
let value_option = abstract_tree.run(&self.context)?;
if !errors.is_empty() {
return Err(errors);
}
let mut value = None;
for statement in statements {
value = match statement.node.run(&self.context) {
Ok(action) => match action {
Action::Break => None,
Action::Return(value) => Some(value),
Action::None => continue,
},
Err(runtime_error) => {
return Err(vec![Error::Runtime {
error: runtime_error,
position: statement.position,
}])
}
}
}
Ok(value)
Ok(value_option)
}
}

View File

@ -11,13 +11,18 @@ use crate::{
pub type ParserInput<'src> =
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
pub fn parse<'src>(
tokens: &'src [(Token<'src>, SimpleSpan)],
) -> Result<Vec<WithPosition<Statement>>, Vec<Error>> {
parser()
pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result<AbstractTree, Vec<Error>> {
let statements = parser()
.parse(tokens.spanned((tokens.len()..tokens.len()).into()))
.into_result()
.map_err(|errors| errors.into_iter().map(|error| error.into()).collect())
.map_err(|errors| {
errors
.into_iter()
.map(|error| Error::from(error))
.collect::<Vec<Error>>()
})?;
Ok(AbstractTree::new(statements))
}
pub fn parser<'src>() -> impl Parser<

View File

@ -15,7 +15,7 @@ use stanza::{
};
use crate::{
abstract_tree::{AbstractTree, Action, Block, Identifier, Type, WithPosition},
abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPosition},
context::Context,
error::{RuntimeError, ValidationError},
};

View File

@ -1,5 +1,5 @@
use dust_lang::{
abstract_tree::{AbstractTree, Block, Expression, Identifier, Statement, Type},
abstract_tree::{AbstractNode, Block, Expression, Identifier, Statement, Type},
error::{Error, TypeConflict, ValidationError},
*,
};