Rename AbstractTree; Add new AbstractTree type
This commit is contained in:
parent
d46a592f87
commit
896a0855e0
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
||||
|
@ -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, _)
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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(())
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -32,12 +32,10 @@ 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 {
|
||||
if let ValueData::Type(Type::Function { .. }) = value_data {
|
||||
self_data.insert(identifier.clone(), value_data.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
39
src/lib.rs
39
src/lib.rs
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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<
|
||||
|
@ -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},
|
||||
};
|
||||
|
@ -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},
|
||||
*,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user