1
0

Overhaul AST

This commit is contained in:
Jeff 2024-03-25 00:16:55 -04:00
parent 4b460c0e68
commit e50b231958
29 changed files with 1406 additions and 1060 deletions

View File

@ -1,17 +1,18 @@
use crate::{
error::{RuntimeError, ValidationError},
identifier::Identifier,
value::ValueInner,
Context, Value,
};
use super::{AbstractNode, Action, Identifier, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment {
identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>,
operator: AssignmentOperator,
statement: Box<WithPosition<Statement>>,
statement: Box<Statement>,
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
@ -26,7 +27,7 @@ impl Assignment {
identifier: WithPosition<Identifier>,
r#type: Option<WithPosition<Type>>,
operator: AssignmentOperator,
statement: WithPosition<Statement>,
statement: Statement,
) -> Self {
Self {
identifier,
@ -43,7 +44,7 @@ impl AbstractNode for Assignment {
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
let statement_type = self.statement.node.expected_type(context)?;
let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition {
node: expected_type,
@ -53,7 +54,7 @@ impl AbstractNode for Assignment {
expected_type.check(&statement_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: self.statement.position,
actual_position: self.statement.position(),
expected_position: expected_position.clone(),
}
})?;
@ -63,14 +64,13 @@ impl AbstractNode for Assignment {
context.set_type(self.identifier.node.clone(), statement_type)?;
}
self.identifier.node.validate(context)?;
self.statement.node.validate(context)?;
self.statement.validate(context)?;
Ok(())
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let action = self.statement.node.run(context)?;
let action = self.statement.run(context)?;
let right = match action {
Action::Return(value) => value,
r#break => return Ok(r#break),
@ -112,7 +112,10 @@ impl AbstractNode for Assignment {
context.set_value(self.identifier.node, new_value)?;
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound(self.identifier.node),
ValidationError::VariableNotFound {
identifier: self.identifier.node,
position: self.identifier.position,
},
));
}
}
@ -148,7 +151,10 @@ impl AbstractNode for Assignment {
context.set_value(self.identifier.node, new_value)?;
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound(self.identifier.node),
ValidationError::VariableNotFound {
identifier: self.identifier.node,
position: self.identifier.position,
},
));
}
}
@ -175,7 +181,9 @@ mod tests {
Identifier::new("foobar").with_position((0, 0)),
None,
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(ValueNode::Integer(42))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)),
)),
)
.run(&context)
.unwrap();
@ -198,7 +206,9 @@ mod tests {
Identifier::new("foobar").with_position((0, 0)),
None,
AssignmentOperator::AddAssign,
Statement::Expression(Expression::Value(ValueNode::Integer(41))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::Integer(41).with_position((0, 0)),
)),
)
.run(&context)
.unwrap();
@ -221,7 +231,9 @@ mod tests {
Identifier::new("foobar").with_position((0, 0)),
None,
AssignmentOperator::SubAssign,
Statement::Expression(Expression::Value(ValueNode::Integer(1))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)),
)),
)
.run(&context)
.unwrap();
@ -241,7 +253,9 @@ mod tests {
position: (0, 0).into(),
}),
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(ValueNode::Integer(42))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)),
)),
)
.validate(&Context::new());

View File

@ -7,27 +7,27 @@ use crate::{
error::{RuntimeError, RwLockPoisonError, ValidationError},
};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct AsyncBlock {
statements: Vec<WithPosition<Statement>>,
statements: Vec<Statement>,
}
impl AsyncBlock {
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
pub fn new(statements: Vec<Statement>) -> Self {
Self { statements }
}
}
impl AbstractNode for AsyncBlock {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
self.statements.last().unwrap().node.expected_type(_context)
self.statements.last().unwrap().expected_type(_context)
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.node.validate(_context)?;
statement.validate(_context)?;
}
Ok(())
@ -41,7 +41,7 @@ impl AbstractNode for AsyncBlock {
.into_par_iter()
.enumerate()
.find_map_first(|(index, statement)| {
let result = statement.node.run(_context);
let result = statement.run(_context);
if index == statement_count - 1 {
let get_write_lock = final_result.write();

View File

@ -3,19 +3,19 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block {
statements: Vec<WithPosition<Statement>>,
statements: Vec<Statement>,
}
impl Block {
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
pub fn new(statements: Vec<Statement>) -> Self {
Self { statements }
}
pub fn last_statement(&self) -> &WithPosition<Statement> {
pub fn last_statement(&self) -> &Statement {
self.statements.last().unwrap()
}
}
@ -23,7 +23,7 @@ impl 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)
statement.expected_type(_context)
} else {
Ok(Type::None)
}
@ -31,7 +31,7 @@ impl AbstractNode for Block {
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.node.validate(_context)?;
statement.validate(_context)?;
}
Ok(())
@ -41,7 +41,7 @@ impl AbstractNode for Block {
let mut previous = Action::None;
for statement in self.statements {
previous = statement.node.run(_context)?;
previous = statement.run(_context)?;
}
Ok(previous)
@ -60,9 +60,15 @@ mod tests {
#[test]
fn run_returns_value_of_final_statement() {
let block = Block::new(vec![
Statement::Expression(Expression::Value(ValueNode::Integer(1))).with_position((0, 0)),
Statement::Expression(Expression::Value(ValueNode::Integer(2))).with_position((0, 0)),
Statement::Expression(Expression::Value(ValueNode::Integer(42))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)),
)),
Statement::Expression(Expression::Value(
ValueNode::Integer(2).with_position((0, 0)),
)),
Statement::Expression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)),
)),
]);
assert_eq!(
@ -74,9 +80,12 @@ mod tests {
#[test]
fn expected_type_returns_type_of_final_statement() {
let block = Block::new(vec![
Statement::Expression(Expression::Value(ValueNode::String("42".to_string())))
.with_position((0, 0)),
Statement::Expression(Expression::Value(ValueNode::Integer(42))).with_position((0, 0)),
Statement::Expression(Expression::Value(
ValueNode::String("42".to_string()).with_position((0, 0)),
)),
Statement::Expression(Expression::Value(
ValueNode::Integer(42).with_position((0, 0)),
)),
]);
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))

View File

@ -1,58 +1,102 @@
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
use super::{
AbstractNode, Action, FunctionCall, Identifier, ListIndex, Logic, MapIndex, Math, Type,
ValueNode,
AbstractNode, Action, FunctionCall, ListIndex, Logic, MapIndex, Math, SourcePosition, Type,
ValueNode, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Expression {
FunctionCall(FunctionCall),
Identifier(Identifier),
MapIndex(Box<MapIndex>),
ListIndex(Box<ListIndex>),
Logic(Box<Logic>),
Math(Box<Math>),
Value(ValueNode),
FunctionCall(WithPosition<FunctionCall>),
Identifier(WithPosition<Identifier>),
MapIndex(WithPosition<Box<MapIndex>>),
ListIndex(WithPosition<Box<ListIndex>>),
Logic(WithPosition<Box<Logic>>),
Math(WithPosition<Box<Math>>),
Value(WithPosition<ValueNode>),
}
impl Expression {
pub fn position(&self) -> SourcePosition {
match self {
Expression::FunctionCall(inner) => inner.position,
Expression::Identifier(inner) => inner.position,
Expression::MapIndex(inner) => inner.position,
Expression::ListIndex(inner) => inner.position,
Expression::Logic(inner) => inner.position,
Expression::Math(inner) => inner.position,
Expression::Value(inner) => inner.position,
}
}
}
impl AbstractNode for Expression {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.expected_type(_context),
Expression::Identifier(identifier) => identifier.expected_type(_context),
Expression::MapIndex(map_index) => map_index.expected_type(_context),
Expression::ListIndex(list_index) => list_index.expected_type(_context),
Expression::Logic(logic) => logic.expected_type(_context),
Expression::Math(math) => math.expected_type(_context),
Expression::Value(value_node) => value_node.expected_type(_context),
Expression::FunctionCall(function_call) => function_call.node.expected_type(_context),
Expression::Identifier(identifier) => {
if let Some(r#type) = _context.get_type(&identifier.node)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.node.expected_type(_context),
Expression::ListIndex(list_index) => list_index.node.expected_type(_context),
Expression::Logic(logic) => logic.node.expected_type(_context),
Expression::Math(math) => math.node.expected_type(_context),
Expression::Value(value_node) => value_node.node.expected_type(_context),
}
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
match self {
Expression::FunctionCall(function_call) => function_call.validate(_context),
Expression::Identifier(identifier) => identifier.validate(_context),
Expression::MapIndex(map_index) => map_index.validate(_context),
Expression::ListIndex(list_index) => list_index.validate(_context),
Expression::Logic(logic) => logic.validate(_context),
Expression::Math(math) => math.validate(_context),
Expression::Value(value_node) => value_node.validate(_context),
Expression::FunctionCall(function_call) => function_call.node.validate(context),
Expression::Identifier(identifier) => {
if context.contains(&identifier.node)? {
Ok(())
} else {
Err(ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
})
}
}
Expression::MapIndex(map_index) => map_index.node.validate(context),
Expression::ListIndex(list_index) => list_index.node.validate(context),
Expression::Logic(logic) => logic.node.validate(context),
Expression::Math(math) => math.node.validate(context),
Expression::Value(value_node) => value_node.node.validate(context),
}
}
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
match self {
Expression::FunctionCall(function_call) => function_call.run(_context),
Expression::Identifier(identifier) => identifier.run(_context),
Expression::MapIndex(map_index) => map_index.run(_context),
Expression::ListIndex(list_index) => list_index.run(_context),
Expression::Logic(logic) => logic.run(_context),
Expression::Math(math) => math.run(_context),
Expression::Value(value_node) => value_node.run(_context),
Expression::FunctionCall(function_call) => function_call.node.run(_context),
Expression::Identifier(identifier) => {
if let Some(value) = _context.get_value(&identifier.node)? {
Ok(Action::Return(value))
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound {
identifier: identifier.node.clone(),
position: identifier.position,
},
))
}
}
Expression::MapIndex(map_index) => map_index.node.run(_context),
Expression::ListIndex(list_index) => list_index.node.run(_context),
Expression::Logic(logic) => logic.node.run(_context),
Expression::Math(math) => math.node.run(_context),
Expression::Value(value_node) => value_node.node.run(_context),
}
}
}

View File

@ -8,16 +8,16 @@ use super::{AbstractNode, Action, Expression, Type, WithPosition};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub struct FunctionCall {
function: Box<WithPosition<Expression>>,
function: Box<Expression>,
type_arguments: Vec<WithPosition<Type>>,
arguments: Vec<WithPosition<Expression>>,
arguments: Vec<Expression>,
}
impl FunctionCall {
pub fn new(
function: WithPosition<Expression>,
function: Expression,
type_arguments: Vec<WithPosition<Type>>,
arguments: Vec<WithPosition<Expression>>,
arguments: Vec<Expression>,
) -> Self {
FunctionCall {
function: Box::new(function),
@ -29,24 +29,24 @@ impl FunctionCall {
impl AbstractNode for FunctionCall {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let function_node_type = self.function.node.expected_type(_context)?;
let function_node_type = self.function.expected_type(_context)?;
if let Type::Function { return_type, .. } = function_node_type {
Ok(return_type.node)
} else {
Err(ValidationError::ExpectedFunction {
actual: function_node_type,
position: self.function.position,
position: self.function.position(),
})
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
for expression in &self.arguments {
expression.node.validate(context)?;
expression.validate(context)?;
}
let function_node_type = self.function.node.expected_type(context)?;
let function_node_type = self.function.expected_type(context)?;
if let Type::Function {
parameter_types,
@ -67,12 +67,12 @@ impl AbstractNode for FunctionCall {
}
for (type_parameter, expression) in parameter_types.iter().zip(self.arguments.iter()) {
let actual = expression.node.expected_type(context)?;
let actual = expression.expected_type(context)?;
type_parameter.node.check(&actual).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position,
actual_position: expression.position(),
expected_position: type_parameter.position,
}
})?;
@ -82,18 +82,19 @@ impl AbstractNode for FunctionCall {
} else {
Err(ValidationError::ExpectedFunction {
actual: function_node_type,
position: self.function.position,
position: self.function.position(),
})
}
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let action = self.function.node.run(context)?;
let function_position = self.function.position();
let action = self.function.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.function.position),
ValidationError::InterpreterExpectedReturn(function_position),
));
};
let function = if let ValueInner::Function(function) = value.inner().as_ref() {
@ -102,19 +103,20 @@ impl AbstractNode for FunctionCall {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedFunction {
actual: value.r#type(context)?,
position: self.function.position,
position: function_position,
},
));
};
let mut arguments = Vec::with_capacity(self.arguments.len());
for expression in self.arguments {
let action = expression.node.run(context)?;
let expression_position = expression.position();
let action = expression.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
ValidationError::InterpreterExpectedReturn(expression_position),
));
};

View File

@ -1,60 +0,0 @@
use std::{
fmt::{self, Display, Formatter},
sync::Arc,
};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
};
use super::{AbstractNode, Action, Type};
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(Arc<String>);
impl Identifier {
pub fn new<T: ToString>(string: T) -> Self {
Identifier(Arc::new(string.to_string()))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
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)
} else {
Err(ValidationError::VariableNotFound(self.clone()))
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
if context.contains(self)? {
Ok(())
} else {
Err(ValidationError::VariableNotFound(self.clone()))
}
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let return_action = context.get_value(&self)?.map(|value| Action::Return(value));
if let Some(action) = return_action {
Ok(action)
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::VariableNotFound(self.clone()),
))
}
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -4,24 +4,27 @@ use crate::{
value::ValueInner,
};
use super::{AbstractNode, Action, Block, Expression, Type, WithPosition};
use super::{AbstractNode, Action, Block, Expression, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse {
if_expression: WithPosition<Expression>,
if_expression: Expression,
if_block: Block,
else_ifs: Option<Vec<(Expression, Block)>>,
else_block: Option<Block>,
}
impl IfElse {
pub fn new(
if_expression: WithPosition<Expression>,
if_expression: Expression,
if_block: Block,
else_ifs: Option<Vec<(Expression, Block)>>,
else_block: Option<Block>,
) -> Self {
Self {
if_expression,
if_block,
else_ifs,
else_block,
}
}
@ -33,10 +36,10 @@ impl AbstractNode for IfElse {
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
self.if_expression.node.validate(context)?;
self.if_expression.validate(context)?;
self.if_block.validate(context)?;
let if_expression_type = self.if_expression.node.expected_type(context)?;
let if_expression_type = self.if_expression.expected_type(context)?;
if let Type::Boolean = if_expression_type {
if let Some(else_block) = &self.else_block {
@ -49,8 +52,8 @@ impl AbstractNode for IfElse {
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.last_statement().position,
expected_position: self.if_expression.position,
actual_position: self.if_block.last_statement().position(),
expected_position: self.if_expression.position(),
})?;
}
@ -58,18 +61,19 @@ impl AbstractNode for IfElse {
} else {
Err(ValidationError::ExpectedBoolean {
actual: if_expression_type,
position: self.if_expression.position,
position: self.if_expression.position(),
})
}
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let action = self.if_expression.node.run(context)?;
let if_position = self.if_expression.position();
let action = self.if_expression.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.if_expression.position),
ValidationError::InterpreterExpectedReturn(if_position),
));
};
@ -85,7 +89,7 @@ impl AbstractNode for IfElse {
Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedBoolean {
actual: value.r#type(context)?,
position: self.if_expression.position,
position: if_position,
},
))
}
@ -105,11 +109,11 @@ mod tests {
fn simple_if() {
assert_eq!(
IfElse::new(
Expression::Value(ValueNode::Boolean(true)).with_position((0, 0)),
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string())
))
.with_position((0, 0))]),
ValueNode::String("foo".to_string()).with_position((0, 0))
))]),
None,
None
)
.run(&Context::new())
@ -117,24 +121,4 @@ mod tests {
Action::Return(Value::string("foo".to_string()))
)
}
#[test]
fn simple_if_else() {
assert_eq!(
IfElse::new(
Expression::Value(ValueNode::Boolean(false)).with_position((0, 0)),
Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string())
))
.with_position((0, 0))]),
Some(Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("bar".to_string())
))
.with_position((0, 0))]))
)
.run(&Context::new())
.unwrap(),
Action::Return(Value::string("bar".to_string()))
)
}
}

View File

@ -7,24 +7,30 @@ use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ListIndex {
left: WithPosition<Expression>,
right: WithPosition<Expression>,
left: Expression,
right: Expression,
}
impl ListIndex {
pub fn new(left: WithPosition<Expression>, right: WithPosition<Expression>) -> Self {
pub fn new(left: Expression, right: Expression) -> Self {
Self { left, right }
}
}
impl AbstractNode for ListIndex {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
let left_type = self.left.node.expected_type(_context)?;
let left_type = self.left.expected_type(_context)?;
if let (
Expression::Value(ValueNode::List(expression_list)),
Expression::Value(ValueNode::Integer(index)),
) = (&self.left.node, &self.right.node)
Expression::Value(WithPosition {
node: ValueNode::List(expression_list),
..
}),
Expression::Value(WithPosition {
node: ValueNode::Integer(index),
..
}),
) = (&self.left, &self.right)
{
let expression = if let Some(expression) = expression_list.get(*index as usize) {
expression
@ -32,57 +38,59 @@ impl AbstractNode for ListIndex {
return Ok(Type::None);
};
expression.node.expected_type(_context)
expression.expected_type(_context)
} else {
Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position,
position: self.left.position(),
})
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
let left_type = self.left.node.expected_type(context)?;
let left_type = self.left.expected_type(context)?;
match left_type {
Type::List => todo!(),
Type::ListOf(_) => todo!(),
Type::ListExact(_) => {
let right_type = self.right.node.expected_type(context)?;
let right_type = self.right.expected_type(context)?;
if let Type::Integer = right_type {
Ok(())
} else {
Err(ValidationError::CannotIndexWith {
collection_type: left_type,
collection_position: self.left.position,
collection_position: self.left.position(),
index_type: right_type,
index_position: self.right.position,
index_position: self.right.position(),
})
}
}
_ => Err(ValidationError::CannotIndex {
r#type: left_type,
position: self.left.position,
position: self.left.position(),
}),
}
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let left_action = self.left.node.run(context)?;
let left_position = self.left.position();
let left_action = self.left.run(context)?;
let left_value = if let Action::Return(value) = left_action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.left.position),
ValidationError::InterpreterExpectedReturn(left_position),
));
};
let right_action = self.right.node.run(context)?;
let right_position = self.right.position();
let right_action = self.right.run(context)?;
let right_value = if let Action::Return(value) = right_action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.left.position),
ValidationError::InterpreterExpectedReturn(right_position),
));
};
@ -98,9 +106,9 @@ impl AbstractNode for ListIndex {
Err(RuntimeError::ValidationFailure(
ValidationError::CannotIndexWith {
collection_type: left_value.r#type(context)?,
collection_position: self.left.position,
collection_position: left_position,
index_type: right_value.r#type(context)?,
index_position: self.right.position,
index_position: right_position,
},
))
}

View File

@ -5,19 +5,19 @@ use crate::{
Value,
};
use super::{AbstractNode, Action, Expression, Type, WithPosition};
use super::{AbstractNode, Action, Expression, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Logic {
Equal(WithPosition<Expression>, WithPosition<Expression>),
NotEqual(WithPosition<Expression>, WithPosition<Expression>),
Greater(WithPosition<Expression>, WithPosition<Expression>),
Less(WithPosition<Expression>, WithPosition<Expression>),
GreaterOrEqual(WithPosition<Expression>, WithPosition<Expression>),
LessOrEqual(WithPosition<Expression>, WithPosition<Expression>),
And(WithPosition<Expression>, WithPosition<Expression>),
Or(WithPosition<Expression>, WithPosition<Expression>),
Not(WithPosition<Expression>),
Equal(Expression, Expression),
NotEqual(Expression, Expression),
Greater(Expression, Expression),
Less(Expression, Expression),
GreaterOrEqual(Expression, Expression),
LessOrEqual(Expression, Expression),
And(Expression, Expression),
Or(Expression, Expression),
Not(Expression),
}
impl AbstractNode for Logic {
@ -33,28 +33,28 @@ impl AbstractNode for Logic {
| Logic::Less(left, right)
| Logic::GreaterOrEqual(left, right)
| Logic::LessOrEqual(left, right) => {
let left_type = left.node.expected_type(context)?;
let right_type = right.node.expected_type(context)?;
let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?;
left_type
.check(&right_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: left.position,
expected_position: right.position,
actual_position: left.position(),
expected_position: right.position(),
})?;
Ok(())
}
Logic::And(left, right) | Logic::Or(left, right) => {
let left_type = left.node.expected_type(context)?;
let right_type = right.node.expected_type(context)?;
let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?;
if let Type::Boolean = left_type {
} else {
return Err(ValidationError::ExpectedBoolean {
actual: left_type,
position: left.position,
position: left.position(),
});
}
@ -62,21 +62,21 @@ impl AbstractNode for Logic {
} else {
return Err(ValidationError::ExpectedBoolean {
actual: right_type,
position: right.position,
position: right.position(),
});
}
Ok(())
}
Logic::Not(expression) => {
let expression_type = expression.node.expected_type(context)?;
let expression_type = expression.expected_type(context)?;
if let Type::Boolean = expression_type {
Ok(())
} else {
Err(ValidationError::ExpectedBoolean {
actual: expression_type,
position: expression.position,
position: expression.position(),
})
}
}
@ -84,43 +84,43 @@ impl AbstractNode for Logic {
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let run_and_expect_value =
|expression: WithPosition<Expression>| -> Result<Value, RuntimeError> {
let action = expression.node.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
));
};
Ok(value)
let run_and_expect_value = |expression: Expression| -> Result<Value, RuntimeError> {
let expression_position = expression.position();
let action = expression.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
let run_and_expect_boolean =
|expression: WithPosition<Expression>| -> Result<bool, RuntimeError> {
let action = expression.node.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
));
};
Ok(value)
};
if let ValueInner::Boolean(boolean) = value.inner().as_ref() {
Ok(*boolean)
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedBoolean {
actual: value.r#type(context)?,
position: expression.position,
},
));
}
let run_and_expect_boolean = |expression: Expression| -> Result<bool, RuntimeError> {
let expression_position = expression.position();
let action = expression.run(context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
if let ValueInner::Boolean(boolean) = value.inner().as_ref() {
Ok(*boolean)
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedBoolean {
actual: value.r#type(context)?,
position: expression_position,
},
));
}
};
let boolean = match self {
Logic::Equal(left, right) => {
let (left_value, right_value) =
@ -195,8 +195,8 @@ mod tests {
fn equal() {
assert_eq!(
Logic::Equal(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -207,8 +207,8 @@ mod tests {
fn not_equal() {
assert_eq!(
Logic::NotEqual(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(43)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -219,8 +219,8 @@ mod tests {
fn greater() {
assert_eq!(
Logic::Greater(
Expression::Value(ValueNode::Integer(43)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(43).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0)))
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -231,8 +231,8 @@ mod tests {
fn less() {
assert_eq!(
Logic::Less(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(43)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(43).with_position((0, 0)))
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -243,8 +243,8 @@ mod tests {
fn greater_or_equal() {
assert_eq!(
Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(41)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(41).with_position((0, 0)))
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -252,8 +252,8 @@ mod tests {
assert_eq!(
Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -264,8 +264,8 @@ mod tests {
fn less_or_equal() {
assert_eq!(
Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(41)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(41).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -273,8 +273,8 @@ mod tests {
assert_eq!(
Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42)).with_position((0, 0)),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
Expression::Value(ValueNode::Integer(42).with_position((0, 0))),
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -285,8 +285,8 @@ mod tests {
fn and() {
assert_eq!(
Logic::And(
Expression::Value(ValueNode::Boolean(true)).with_position((0, 0)),
Expression::Value(ValueNode::Boolean(true)).with_position((0, 0)),
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -297,8 +297,8 @@ mod tests {
fn or() {
assert_eq!(
Logic::Or(
Expression::Value(ValueNode::Boolean(true)).with_position((0, 0)),
Expression::Value(ValueNode::Boolean(false)).with_position((0, 0)),
Expression::Value(ValueNode::Boolean(true).with_position((0, 0))),
Expression::Value(ValueNode::Boolean(false).with_position((0, 0))),
)
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
@ -308,8 +308,10 @@ mod tests {
#[test]
fn not() {
assert_eq!(
Logic::Not(Expression::Value(ValueNode::Boolean(false)).with_position((0, 0)),)
.run(&Context::new()),
Logic::Not(Expression::Value(
ValueNode::Boolean(false).with_position((0, 0))
))
.run(&Context::new()),
Ok(Action::Return(Value::boolean(true)))
)
}

View File

@ -5,15 +5,15 @@ use crate::{
error::{RuntimeError, ValidationError},
};
use super::{AbstractNode, Action, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Statement, Type};
#[derive(Clone, Debug)]
pub struct Loop {
statements: Vec<WithPosition<Statement>>,
statements: Vec<Statement>,
}
impl Loop {
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
pub fn new(statements: Vec<Statement>) -> Self {
Self { statements }
}
}
@ -25,7 +25,7 @@ impl AbstractNode for Loop {
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.node.validate(_context)?;
statement.validate(_context)?;
}
Ok(())
@ -34,7 +34,7 @@ impl AbstractNode for Loop {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
loop {
for statement in &self.statements {
let action = statement.node.clone().run(_context)?;
let action = statement.clone().run(_context)?;
match action {
Action::Return(_) => {}
@ -70,9 +70,9 @@ impl Ord for Loop {
mod tests {
use crate::{
abstract_tree::{
Assignment, AssignmentOperator, Block, Expression, Identifier, IfElse, Logic,
ValueNode, WithPos,
Assignment, AssignmentOperator, Block, Expression, IfElse, Logic, ValueNode, WithPos,
},
identifier::Identifier,
Value,
};
@ -80,7 +80,7 @@ mod tests {
#[test]
fn basic_loop() {
let action = Loop::new(vec![Statement::Break.with_position((0, 0))])
let action = Loop::new(vec![Statement::Break(().with_position((0, 0)))])
.run(&Context::new())
.unwrap();
@ -90,34 +90,48 @@ mod tests {
#[test]
fn complex_loop() {
let action = Block::new(vec![
Statement::Assignment(Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
.with_position((0, 0)),
))
.with_position((0, 0)),
Statement::Loop(Loop::new(vec![Statement::IfElse(IfElse::new(
Expression::Logic(Box::new(Logic::Greater(
Expression::Identifier(Identifier::new("i")).with_position((0, 0)),
Expression::Value(ValueNode::Integer(2)).with_position((0, 0)),
)))
.with_position((0, 0)),
Block::new(vec![Statement::Break.with_position((0, 0))]),
Some(Block::new(vec![Statement::Assignment(Assignment::new(
Statement::Assignment(
Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::AddAssign,
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
.with_position((0, 0)),
))
.with_position((0, 0))])),
))
.with_position((0, 0))]))
.with_position((0, 0)),
Statement::Expression(Expression::Identifier(Identifier::new("i")))
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)),
)),
)
.with_position((0, 0)),
),
Statement::Loop(
Loop::new(vec![Statement::IfElse(
IfElse::new(
Expression::Logic(
Box::new(Logic::Greater(
Expression::Identifier(Identifier::new("i").with_position((0, 0))),
Expression::Value(ValueNode::Integer(2).with_position((0, 0))),
))
.with_position((0, 0)),
),
Block::new(vec![Statement::Break(().with_position((0, 0)))]),
None,
Some(Block::new(vec![Statement::Assignment(
Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::AddAssign,
Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)),
)),
)
.with_position((0, 0)),
)])),
)
.with_position((0, 0)),
)])
.with_position((0, 0)),
),
Statement::Expression(Expression::Identifier(
Identifier::new("i").with_position((0, 0)),
)),
])
.run(&Context::new())
.unwrap();

View File

@ -8,12 +8,12 @@ use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MapIndex {
left: WithPosition<Expression>,
right: WithPosition<Expression>,
left: Expression,
right: Expression,
}
impl MapIndex {
pub fn new(left: WithPosition<Expression>, right: WithPosition<Expression>) -> Self {
pub fn new(left: Expression, right: Expression) -> Self {
Self { left, right }
}
}
@ -23,40 +23,47 @@ impl AbstractNode for MapIndex {
if let (
Expression::Identifier(collection_identifier),
Expression::Identifier(index_identifier),
) = (&self.left.node, &self.right.node)
) = (&self.left, &self.right)
{
let collection = if let Some(collection) = context.get_value(collection_identifier)? {
collection
} else {
return Err(ValidationError::VariableNotFound(
collection_identifier.clone(),
));
};
let collection =
if let Some(collection) = context.get_value(&collection_identifier.node)? {
collection
} else {
return Err(ValidationError::VariableNotFound {
identifier: collection_identifier.node.clone(),
position: collection_identifier.position,
});
};
if let ValueInner::Map(map) = collection.inner().as_ref() {
return if let Some(value) = map.get(index_identifier) {
return if let Some(value) = map.get(&index_identifier.node) {
Ok(value.r#type(context)?)
} else {
Err(ValidationError::PropertyNotFound {
identifier: index_identifier.clone(),
position: self.right.position,
identifier: index_identifier.node.clone(),
position: self.right.position(),
})
};
};
}
if let (Expression::Value(ValueNode::Map(properties)), Expression::Identifier(identifier)) =
(&self.left.node, &self.right.node)
if let (
Expression::Value(WithPosition {
node: ValueNode::Map(properties),
..
}),
Expression::Identifier(identifier),
) = (&self.left, &self.right)
{
return if let Some(type_result) =
properties
.iter()
.find_map(|(property, type_option, expression)| {
if property == identifier {
if property == &identifier.node {
if let Some(r#type) = type_option {
Some(r#type.node.expected_type(context))
} else {
Some(expression.node.expected_type(context))
Some(expression.expected_type(context))
}
} else {
None
@ -70,13 +77,16 @@ impl AbstractNode for MapIndex {
}
if let (
Expression::Value(ValueNode::Structure { fields, .. }),
Expression::Value(WithPosition {
node: ValueNode::Structure { fields, .. },
..
}),
Expression::Identifier(identifier),
) = (&self.left.node, &self.right.node)
) = (&self.left, &self.right)
{
return if let Some(type_result) = fields.iter().find_map(|(property, expression)| {
if property == identifier {
Some(expression.node.expected_type(context))
if property == &identifier.node {
Some(expression.expected_type(context))
} else {
None
}
@ -88,49 +98,55 @@ impl AbstractNode for MapIndex {
}
Err(ValidationError::CannotIndexWith {
collection_type: self.left.node.expected_type(context)?,
collection_position: self.left.position,
index_type: self.right.node.expected_type(context)?,
index_position: self.right.position,
collection_type: self.left.expected_type(context)?,
collection_position: self.left.position(),
index_type: self.right.expected_type(context)?,
index_position: self.right.position(),
})
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
let left_type = self.left.node.expected_type(context)?;
let left_type = self.left.expected_type(context)?;
if let (Expression::Value(ValueNode::Map(_)), Expression::Identifier(_)) =
(&self.left.node, &self.right.node)
if let (
Expression::Value(WithPosition {
node: ValueNode::Map(_),
..
}),
Expression::Identifier(_),
) = (&self.left, &self.right)
{
Ok(())
} else if let (Expression::Identifier(_), Expression::Identifier(_)) =
(&self.left.node, &self.right.node)
(&self.left, &self.right)
{
Ok(())
} else {
Err(ValidationError::CannotIndexWith {
collection_type: left_type,
collection_position: self.left.position,
index_type: self.right.node.expected_type(context)?,
index_position: self.right.position,
collection_position: self.left.position(),
index_type: self.right.expected_type(context)?,
index_position: self.right.position(),
})
}
}
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let action = self.left.node.run(context)?;
let collection_position = self.left.position();
let action = self.left.run(context)?;
let collection = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.left.position),
ValidationError::InterpreterExpectedReturn(collection_position),
));
};
if let (ValueInner::Map(map), Expression::Identifier(identifier)) =
(collection.inner().as_ref(), &self.right.node)
(collection.inner().as_ref(), &self.right)
{
let action = map
.get(identifier)
.get(&identifier.node)
.map(|value| Action::Return(value.clone()))
.unwrap_or(Action::None);
@ -139,9 +155,9 @@ impl AbstractNode for MapIndex {
Err(RuntimeError::ValidationFailure(
ValidationError::CannotIndexWith {
collection_type: collection.r#type(context)?,
collection_position: self.left.position,
index_type: self.right.node.expected_type(context)?,
index_position: self.right.position,
collection_position,
index_type: self.right.expected_type(context)?,
index_position: self.right.position(),
},
))
}

View File

@ -5,15 +5,15 @@ use crate::{
Value,
};
use super::{AbstractNode, Action, Expression, SourcePosition, Type, WithPosition};
use super::{AbstractNode, Action, Expression, SourcePosition, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Math {
Add(WithPosition<Expression>, WithPosition<Expression>),
Subtract(WithPosition<Expression>, WithPosition<Expression>),
Multiply(WithPosition<Expression>, WithPosition<Expression>),
Divide(WithPosition<Expression>, WithPosition<Expression>),
Modulo(WithPosition<Expression>, WithPosition<Expression>),
Add(Expression, Expression),
Subtract(Expression, Expression),
Multiply(Expression, Expression),
Divide(Expression, Expression),
Modulo(Expression, Expression),
}
impl AbstractNode for Math {
@ -24,8 +24,8 @@ impl AbstractNode for Math {
| Math::Multiply(left, right)
| Math::Divide(left, right)
| Math::Modulo(left, right) => {
let left_type = left.node.expected_type(_context)?;
let right_type = right.node.expected_type(_context)?;
let left_type = left.expected_type(_context)?;
let right_type = right.expected_type(_context)?;
if let Type::Float = left_type {
return Ok(Type::Float);
@ -43,22 +43,25 @@ impl AbstractNode for Math {
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
match self {
Math::Add(left, right) => {
let left_type = left.node.expected_type(context)?;
let right_type = right.node.expected_type(context)?;
let left_position = left.position();
let left_type = left.expected_type(context)?;
if let Type::Integer | Type::Float | Type::String = left_type {
let right_position = right.position();
let right_type = right.expected_type(context)?;
if let Type::Integer | Type::Float | Type::String = right_type {
Ok(())
} else {
Err(ValidationError::ExpectedIntegerFloatOrString {
actual: right_type,
position: right.position,
position: right_position,
})
}
} else {
Err(ValidationError::ExpectedIntegerFloatOrString {
actual: left_type,
position: left.position,
position: left_position,
})
}
}
@ -66,17 +69,20 @@ impl AbstractNode for Math {
| Math::Multiply(left, right)
| Math::Divide(left, right)
| Math::Modulo(left, right) => {
let left_type = left.node.expected_type(context)?;
let right_type = right.node.expected_type(context)?;
let left_position = left.position();
let left_type = left.expected_type(context)?;
if let Type::Integer | Type::Float = left_type {
let right_position = right.position();
let right_type = right.expected_type(context)?;
if let Type::Integer | Type::Float = right_type {
Ok(())
} else {
Err(ValidationError::ExpectedIntegerOrFloat(right.position))
Err(ValidationError::ExpectedIntegerOrFloat(right_position))
}
} else {
Err(ValidationError::ExpectedIntegerOrFloat(left.position))
Err(ValidationError::ExpectedIntegerOrFloat(left_position))
}
}
}
@ -84,7 +90,7 @@ impl AbstractNode for Math {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let run_and_expect_value =
|expression: Expression, position: SourcePosition| -> Result<Value, RuntimeError> {
|position: SourcePosition, expression: Expression| -> Result<Value, RuntimeError> {
let action = expression.run(_context)?;
let value = if let Action::Return(value) = action {
value
@ -99,8 +105,10 @@ impl AbstractNode for Math {
let value = match self {
Math::Add(left, right) => {
let left_value = run_and_expect_value(left.node, left.position)?;
let right_value = run_and_expect_value(right.node, right.position)?;
let left_position = left.position();
let left_value = run_and_expect_value(left_position, left)?;
let right_position = right.position();
let right_value = run_and_expect_value(right_position, right)?;
match (left_value.inner().as_ref(), right_value.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
@ -132,19 +140,21 @@ impl AbstractNode for Math {
}
(ValueInner::Integer(_) | ValueInner::Float(_), _) => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(right.position),
ValidationError::ExpectedIntegerOrFloat(right_position),
))
}
_ => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(left.position),
ValidationError::ExpectedIntegerOrFloat(left_position),
))
}
}
}
Math::Subtract(left, right) => {
let left_value = run_and_expect_value(left.node, left.position)?;
let right_value = run_and_expect_value(right.node, right.position)?;
let left_position = left.position();
let left_value = run_and_expect_value(left_position, left)?;
let right_position = right.position();
let right_value = run_and_expect_value(right_position, right)?;
match (left_value.inner().as_ref(), right_value.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
@ -169,19 +179,21 @@ impl AbstractNode for Math {
}
(ValueInner::Integer(_) | ValueInner::Float(_), _) => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(right.position),
ValidationError::ExpectedIntegerOrFloat(right_position),
))
}
_ => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(left.position),
ValidationError::ExpectedIntegerOrFloat(left_position),
))
}
}
}
Math::Multiply(left, right) => {
let left_value = run_and_expect_value(left.node, left.position)?;
let right_value = run_and_expect_value(right.node, right.position)?;
let left_position = left.position();
let left_value = run_and_expect_value(left_position, left)?;
let right_position = right.position();
let right_value = run_and_expect_value(right_position, right)?;
match (left_value.inner().as_ref(), right_value.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
@ -206,19 +218,21 @@ impl AbstractNode for Math {
}
(ValueInner::Integer(_) | ValueInner::Float(_), _) => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(right.position).into(),
ValidationError::ExpectedIntegerOrFloat(right_position).into(),
))
}
_ => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(left.position),
ValidationError::ExpectedIntegerOrFloat(left_position),
))
}
}
}
Math::Divide(left, right) => {
let left_value = run_and_expect_value(left.node, left.position)?;
let right_value = run_and_expect_value(right.node, right.position)?;
let left_position = left.position();
let left_value = run_and_expect_value(left_position, left)?;
let right_position = right.position();
let right_value = run_and_expect_value(right_position, right)?;
match (left_value.inner().as_ref(), right_value.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
@ -243,19 +257,21 @@ impl AbstractNode for Math {
}
(ValueInner::Integer(_) | ValueInner::Float(_), _) => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(right.position).into(),
ValidationError::ExpectedIntegerOrFloat(right_position).into(),
))
}
_ => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(left.position),
ValidationError::ExpectedIntegerOrFloat(left_position),
))
}
}
}
Math::Modulo(left, right) => {
let left_value = run_and_expect_value(left.node, left.position)?;
let right_value = run_and_expect_value(right.node, right.position)?;
let left_position = left.position();
let left_value = run_and_expect_value(left_position, left)?;
let right_position = right.position();
let right_value = run_and_expect_value(right_position, right)?;
match (left_value.inner().as_ref(), right_value.inner().as_ref()) {
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
@ -280,12 +296,12 @@ impl AbstractNode for Math {
}
(ValueInner::Integer(_) | ValueInner::Float(_), _) => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(right.position).into(),
ValidationError::ExpectedIntegerOrFloat(right_position).into(),
))
}
_ => {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedIntegerOrFloat(left.position),
ValidationError::ExpectedIntegerOrFloat(left_position),
))
}
}

View File

@ -3,7 +3,6 @@ pub mod async_block;
pub mod block;
pub mod expression;
pub mod function_call;
pub mod identifier;
pub mod if_else;
pub mod list_index;
pub mod logic;
@ -26,7 +25,6 @@ pub use self::{
block::Block,
expression::Expression,
function_call::FunctionCall,
identifier::Identifier,
if_else::IfElse,
list_index::ListIndex,
logic::Logic,
@ -85,11 +83,11 @@ pub enum Action {
None,
}
pub struct AbstractTree(Vec<WithPosition<Statement>>);
pub struct AbstractTree(Vec<Statement>);
impl AbstractTree {
pub fn new(mut statements: Vec<WithPosition<Statement>>) -> Self {
statements.sort_by(|left, right| match (&left.node, &right.node) {
pub fn new(mut statements: Vec<Statement>) -> Self {
statements.sort_by(|left, right| match (&left, &right) {
(Statement::StructureDefinition(_), _) => Ordering::Less,
(_, Statement::StructureDefinition(_)) => Ordering::Greater,
(_, _) => Ordering::Equal,
@ -103,7 +101,8 @@ impl AbstractTree {
let mut previous_value = None;
for statement in valid_statements {
let run = statement.node.run(context);
let position = statement.position();
let run = statement.run(context);
match run {
Ok(action) => match action {
@ -113,7 +112,7 @@ impl AbstractTree {
Err(runtime_error) => {
return Err(vec![Error::Runtime {
error: runtime_error,
position: statement.position,
position,
}]);
}
}
@ -122,29 +121,27 @@ impl AbstractTree {
Ok(previous_value)
}
fn run_type_definitions(
self,
context: &Context,
) -> Result<Vec<WithPosition<Statement>>, Vec<Error>> {
fn run_type_definitions(self, context: &Context) -> Result<Vec<Statement>, Vec<Error>> {
let mut errors = Vec::new();
let mut valid_statements = Vec::new();
for statement in self.0 {
let validation = statement.node.validate(context);
let validation = statement.validate(context);
if let Err(validation_error) = validation {
errors.push(Error::Validation {
error: validation_error,
position: statement.position,
position: statement.position(),
})
} else if errors.is_empty() {
if let Statement::StructureDefinition(_) = statement.node {
let run = statement.node.run(context);
if let Statement::StructureDefinition(_) = statement {
let position = statement.position();
let run = statement.run(context);
if let Err(runtime_error) = run {
errors.push(Error::Runtime {
error: runtime_error,
position: statement.position,
position,
});
return Err(errors);
@ -164,7 +161,7 @@ impl AbstractTree {
}
impl Index<usize> for AbstractTree {
type Output = WithPosition<Statement>;
type Output = Statement;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]

View File

@ -4,28 +4,35 @@ use crate::{
};
use super::{
AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop,
StructureDefinition, Type, While,
AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop, SourcePosition,
StructureDefinition, Type, While, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Statement {
Assignment(Assignment),
AsyncBlock(AsyncBlock),
Block(Block),
Break,
Assignment(WithPosition<Assignment>),
AsyncBlock(WithPosition<AsyncBlock>),
Block(WithPosition<Block>),
Break(WithPosition<()>),
Expression(Expression),
IfElse(IfElse),
Loop(Loop),
StructureDefinition(StructureDefinition),
While(While),
IfElse(WithPosition<IfElse>),
Loop(WithPosition<Loop>),
StructureDefinition(WithPosition<StructureDefinition>),
While(WithPosition<While>),
}
impl Statement {
pub fn kind(&self) -> u8 {
pub fn position(&self) -> SourcePosition {
match self {
Statement::StructureDefinition(_) => 0,
_ => 1,
Statement::Assignment(inner) => inner.position,
Statement::AsyncBlock(inner) => inner.position,
Statement::Block(inner) => inner.position,
Statement::Break(inner) => inner.position,
Statement::Expression(expression) => expression.position(),
Statement::IfElse(inner) => inner.position,
Statement::Loop(inner) => inner.position,
Statement::StructureDefinition(inner) => inner.position,
Statement::While(inner) => inner.position,
}
}
}
@ -33,48 +40,48 @@ impl Statement {
impl AbstractNode for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.expected_type(_context),
Statement::Block(block) => block.expected_type(_context),
Statement::Break => Ok(Type::None),
Statement::Assignment(assignment) => assignment.node.expected_type(_context),
Statement::AsyncBlock(async_block) => async_block.node.expected_type(_context),
Statement::Block(block) => block.node.expected_type(_context),
Statement::Break(_) => Ok(Type::None),
Statement::Expression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.expected_type(_context),
Statement::Loop(r#loop) => r#loop.expected_type(_context),
Statement::While(r#while) => r#while.expected_type(_context),
Statement::IfElse(if_else) => if_else.node.expected_type(_context),
Statement::Loop(r#loop) => r#loop.node.expected_type(_context),
Statement::While(r#while) => r#while.node.expected_type(_context),
Statement::StructureDefinition(structure_definition) => {
structure_definition.expected_type(_context)
structure_definition.node.expected_type(_context)
}
}
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
match self {
Statement::Assignment(assignment) => assignment.validate(_context),
Statement::AsyncBlock(async_block) => async_block.validate(_context),
Statement::Block(block) => block.validate(_context),
Statement::Break => Ok(()),
Statement::Assignment(assignment) => assignment.node.validate(_context),
Statement::AsyncBlock(async_block) => async_block.node.validate(_context),
Statement::Block(block) => block.node.validate(_context),
Statement::Break(_) => Ok(()),
Statement::Expression(expression) => expression.validate(_context),
Statement::IfElse(if_else) => if_else.validate(_context),
Statement::Loop(r#loop) => r#loop.validate(_context),
Statement::While(r#while) => r#while.validate(_context),
Statement::IfElse(if_else) => if_else.node.validate(_context),
Statement::Loop(r#loop) => r#loop.node.validate(_context),
Statement::While(r#while) => r#while.node.validate(_context),
Statement::StructureDefinition(structure_definition) => {
structure_definition.validate(_context)
structure_definition.node.validate(_context)
}
}
}
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
match self {
Statement::Assignment(assignment) => assignment.run(_context),
Statement::AsyncBlock(async_block) => async_block.run(_context),
Statement::Block(block) => block.run(_context),
Statement::Break => Ok(Action::Break),
Statement::Assignment(assignment) => assignment.node.run(_context),
Statement::AsyncBlock(async_block) => async_block.node.run(_context),
Statement::Block(block) => block.node.run(_context),
Statement::Break(_) => Ok(Action::Break),
Statement::Expression(expression) => expression.run(_context),
Statement::IfElse(if_else) => if_else.run(_context),
Statement::Loop(r#loop) => r#loop.run(_context),
Statement::While(r#while) => r#while.run(_context),
Statement::IfElse(if_else) => if_else.node.run(_context),
Statement::Loop(r#loop) => r#loop.node.run(_context),
Statement::While(r#while) => r#while.node.run(_context),
Statement::StructureDefinition(structure_definition) => {
structure_definition.run(_context)
structure_definition.node.run(_context)
}
}
}

View File

@ -1,9 +1,10 @@
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
use super::{AbstractNode, Action, Identifier, Type, WithPosition};
use super::{AbstractNode, Action, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct StructureDefinition {

View File

@ -3,9 +3,9 @@ use std::fmt::{self, Display, Formatter};
use clap::error::Result;
use crate::{
abstract_tree::Identifier,
context::Context,
error::{RuntimeError, TypeConflict, ValidationError},
identifier::Identifier,
};
use super::{AbstractNode, Action, WithPosition};

View File

@ -4,10 +4,11 @@ use crate::{
built_in_functions::BuiltInFunction,
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
Value,
};
use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPos, WithPosition};
use super::{AbstractNode, Action, Block, Expression, Type, WithPos, WithPosition};
#[derive(Clone, Debug, PartialEq)]
pub enum ValueNode {
@ -15,19 +16,13 @@ pub enum ValueNode {
BuiltInFunction(BuiltInFunction),
Float(f64),
Integer(i64),
List(Vec<WithPosition<Expression>>),
Map(
Vec<(
Identifier,
Option<WithPosition<Type>>,
WithPosition<Expression>,
)>,
),
List(Vec<Expression>),
Map(Vec<(Identifier, Option<WithPosition<Type>>, Expression)>),
Range(Range<i64>),
String(String),
Structure {
name: Identifier,
fields: Vec<(Identifier, WithPosition<Expression>)>,
name: WithPosition<Identifier>,
fields: Vec<(Identifier, Expression)>,
},
ParsedFunction {
type_arguments: Vec<WithPosition<Type>>,
@ -49,9 +44,8 @@ impl AbstractNode for ValueNode {
for expression in items {
item_types.push(
expression
.node
.expected_type(context)?
.with_position(expression.position),
.with_position(expression.position()),
);
}
@ -78,19 +72,19 @@ impl AbstractNode for ValueNode {
let mut types = Vec::with_capacity(expressions.len());
for (identifier, expression) in expressions {
let r#type = expression.node.expected_type(context)?;
let r#type = expression.expected_type(context)?;
types.push((
identifier.clone(),
WithPosition {
node: r#type,
position: expression.position,
position: expression.position(),
},
));
}
Type::Structure {
name: name.clone(),
name: name.node.clone(),
fields: types,
}
}
@ -104,12 +98,12 @@ impl AbstractNode for ValueNode {
if let ValueNode::Map(map_assignments) = self {
for (_identifier, r#type, expression) in map_assignments {
if let Some(expected_type) = r#type {
let actual_type = expression.node.expected_type(context)?;
let actual_type = expression.expected_type(context)?;
expected_type.node.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position,
actual_position: expression.position(),
expected_position: expected_type.position,
}
})?;
@ -161,18 +155,18 @@ impl AbstractNode for ValueNode {
fields: expressions,
} = self
{
if let Type::Structure {
if let Some(Type::Structure {
name: _,
fields: types,
} = name.expected_type(context)?
}) = context.get_type(&name.node)?
{
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) {
let actual_type = expression.node.expected_type(context)?;
let actual_type = expression.expected_type(context)?;
expected_type.node.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position,
actual_position: expression.position(),
expected_position: expected_type.position,
}
})?
@ -192,15 +186,16 @@ impl AbstractNode for ValueNode {
let mut value_list = Vec::with_capacity(expression_list.len());
for expression in expression_list {
let action = expression.node.run(_context)?;
let expression_position = expression.position();
let action = expression.run(_context)?;
let value = if let Action::Return(value) = action {
WithPosition {
node: value,
position: expression.position,
position: expression_position,
}
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
@ -213,12 +208,13 @@ impl AbstractNode for ValueNode {
let mut property_map = BTreeMap::new();
for (identifier, _type, expression) in property_list {
let action = expression.node.run(_context)?;
let expression_position = expression.position();
let action = expression.run(_context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
@ -242,12 +238,13 @@ impl AbstractNode for ValueNode {
let mut fields = Vec::with_capacity(expressions.len());
for (identifier, expression) in expressions {
let action = expression.node.run(_context)?;
let expression_position = expression.position();
let action = expression.run(_context)?;
let value = if let Action::Return(value) = action {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(expression.position),
ValidationError::InterpreterExpectedReturn(expression_position),
));
};

View File

@ -5,19 +5,16 @@ use crate::{
Value,
};
use super::{AbstractNode, Action, Expression, Statement, Type, WithPosition};
use super::{AbstractNode, Action, Expression, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct While {
expression: WithPosition<Expression>,
statements: Vec<WithPosition<Statement>>,
expression: Expression,
statements: Vec<Statement>,
}
impl While {
pub fn new(
expression: WithPosition<Expression>,
statements: Vec<WithPosition<Statement>>,
) -> Self {
pub fn new(expression: Expression, statements: Vec<Statement>) -> Self {
Self {
expression,
statements,
@ -31,10 +28,10 @@ impl AbstractNode for While {
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
self.expression.node.validate(_context)?;
self.expression.validate(_context)?;
for statement in &self.statements {
statement.node.validate(_context)?;
statement.validate(_context)?;
}
Ok(())
@ -42,13 +39,14 @@ impl AbstractNode for While {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let get_boolean = || -> Result<Value, RuntimeError> {
let action = self.expression.node.run(_context)?;
let expression_position = self.expression.position();
let action = self.expression.run(_context)?;
if let Action::Return(value) = action {
Ok(value)
} else {
Err(RuntimeError::ValidationFailure(
ValidationError::InterpreterExpectedReturn(self.expression.position),
ValidationError::InterpreterExpectedReturn(expression_position),
))
}
};
@ -56,7 +54,7 @@ impl AbstractNode for While {
if let ValueInner::Boolean(boolean) = get_boolean()?.inner().as_ref() {
while *boolean {
for statement in &self.statements {
let action = statement.node.clone().run(_context)?;
let action = statement.clone().run(_context)?;
match action {
Action::Return(_) => {}
@ -73,42 +71,57 @@ impl AbstractNode for While {
#[cfg(test)]
mod tests {
use crate::abstract_tree::{
Assignment, AssignmentOperator, Block, Identifier, Logic, ValueNode, WithPos,
use crate::{
abstract_tree::{Assignment, AssignmentOperator, Block, Logic, ValueNode, WithPos},
identifier::Identifier,
};
use super::*;
#[test]
fn simple_while_loop() {
let action = Statement::Block(Block::new(vec![
Statement::Assignment(Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(ValueNode::Integer(3)))
let action = Statement::Block(
Block::new(vec![
Statement::Assignment(
Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::Assign,
Statement::Expression(Expression::Value(
ValueNode::Integer(3).with_position((0, 0)),
)),
)
.with_position((0, 0)),
))
.with_position((0, 0)),
Statement::While(While {
expression: Expression::Logic(Box::new(Logic::Less(
Expression::Identifier(Identifier::new("i")).with_position((0, 0)),
Expression::Value(ValueNode::Integer(3)).with_position((0, 0)),
)))
.with_position((0, 0)),
statements: vec![Statement::Assignment(Assignment::new(
),
Statement::While(
While::new(
Expression::Logic(
Box::new(Logic::Less(
Expression::Identifier(Identifier::new("i").with_position((0, 0))),
Expression::Value(ValueNode::Integer(3).with_position((0, 0))),
))
.with_position((0, 0)),
),
vec![Statement::Assignment(
Assignment::new(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::AddAssign,
Statement::Expression(Expression::Value(
ValueNode::Integer(1).with_position((0, 0)),
)),
)
.with_position((0, 0)),
)],
)
.with_position((0, 0)),
),
Statement::Expression(Expression::Identifier(
Identifier::new("i").with_position((0, 0)),
None,
AssignmentOperator::AddAssign,
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
.with_position((0, 0)),
))
.with_position((0, 0))],
})
)),
])
.with_position((0, 0)),
Statement::Expression(Expression::Identifier(Identifier::new("i")))
.with_position((0, 0)),
]))
)
.run(&Context::new())
.unwrap();

View File

@ -4,8 +4,9 @@ use std::{
};
use crate::{
abstract_tree::{Identifier, Type},
abstract_tree::Type,
error::{RwLockPoisonError, ValidationError},
identifier::Identifier,
Value,
};

View File

@ -3,7 +3,8 @@ use std::{io, sync::PoisonError};
use chumsky::{prelude::Rich, span::Span};
use crate::{
abstract_tree::{Identifier, SourcePosition, Type},
abstract_tree::{SourcePosition, Type},
identifier::Identifier,
lexer::Token,
};
@ -135,7 +136,10 @@ pub enum ValidationError {
expected: Vec<Type>,
actual: Vec<Type>,
},
VariableNotFound(Identifier),
VariableNotFound {
identifier: Identifier,
position: SourcePosition,
},
PropertyNotFound {
identifier: Identifier,
position: SourcePosition,

View File

@ -0,0 +1,23 @@
use std::{
fmt::{self, Display, Formatter},
sync::Arc,
};
#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(Arc<String>);
impl Identifier {
pub fn new<T: ToString>(string: T) -> Self {
Identifier(Arc::new(string.to_string()))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -2,6 +2,7 @@ pub mod abstract_tree;
pub mod built_in_functions;
pub mod context;
pub mod error;
pub mod identifier;
pub mod lexer;
pub mod parser;
pub mod value;
@ -120,7 +121,7 @@ impl InterpreterError {
let mut reports = Vec::new();
for error in self.errors {
let (mut builder, validation_error, error_position) = match error {
let (mut builder, validation_error) = match error {
Error::Lex {
expected,
span,
@ -145,7 +146,6 @@ impl InterpreterError {
.with_color(Color::Red),
),
None,
span.into(),
)
}
Error::Parse {
@ -172,7 +172,6 @@ impl InterpreterError {
.with_color(Color::Red),
),
None,
span.into(),
)
}
Error::Validation { error, position } => (
@ -184,7 +183,6 @@ impl InterpreterError {
.with_message("The syntax is valid but this code would cause an error.")
.with_note("This error was detected by the interpreter before running the code."),
Some(error),
position,
),
Error::Runtime { error, position } => (
Report::build(
@ -207,7 +205,6 @@ impl InterpreterError {
} else {
None
},
position,
),
};
@ -260,12 +257,16 @@ impl InterpreterError {
.with_message(format!("Got type {} here.", actual.fg(type_color))),
]);
}
ValidationError::VariableNotFound(identifier) => builder.add_label(
Label::new((self.source_id.clone(), error_position.0..error_position.1))
.with_message(format!(
ValidationError::VariableNotFound {
identifier,
position,
} => builder.add_label(
Label::new((self.source_id.clone(), position.0..position.1)).with_message(
format!(
"Variable {} does not exist in this context.",
identifier.fg(identifier_color)
)),
),
),
),
ValidationError::CannotIndex { r#type, position } => builder.add_label(
Label::new((self.source_id.clone(), position.0..position.1)).with_message(

File diff suppressed because it is too large Load Diff

View File

@ -13,10 +13,11 @@ use stanza::{
};
use crate::{
abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPos, WithPosition},
abstract_tree::{AbstractNode, Action, Block, Type, WithPos, WithPosition},
built_in_functions::BuiltInFunction,
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
#[derive(Clone, Debug, PartialEq)]
@ -71,7 +72,7 @@ impl Value {
))))
}
pub fn structure(name: Identifier, fields: Vec<(Identifier, Value)>) -> Self {
pub fn structure(name: WithPosition<Identifier>, fields: Vec<(Identifier, Value)>) -> Self {
Value(Arc::new(ValueInner::Structure { name, fields }))
}
@ -176,7 +177,7 @@ impl Display for Value {
table = table.with_row([identifier.as_str(), &value.to_string()]);
}
write!(f, "{name}\n{}", Console::default().render(&table))
write!(f, "{}\n{}", name.node, Console::default().render(&table))
}
}
}
@ -207,7 +208,7 @@ pub enum ValueInner {
Range(Range<i64>),
String(String),
Structure {
name: Identifier,
name: WithPosition<Identifier>,
fields: Vec<(Identifier, Value)>,
},
}
@ -244,10 +245,13 @@ impl ValueInner {
}
},
ValueInner::Structure { name, .. } => {
if let Some(r#type) = context.get_type(name)? {
if let Some(r#type) = context.get_type(&name.node)? {
r#type
} else {
return Err(ValidationError::VariableNotFound(name.clone()));
return Err(ValidationError::VariableNotFound {
identifier: name.node.clone(),
position: name.position,
});
}
}
};

View File

@ -1,6 +1,6 @@
use dust_lang::{
abstract_tree::Identifier,
error::{Error, ValidationError},
identifier::Identifier,
*,
};
@ -69,7 +69,10 @@ fn function_context_does_not_capture_values() {
.unwrap_err()
.errors(),
&vec![Error::Validation {
error: ValidationError::VariableNotFound(Identifier::new("x")),
error: ValidationError::VariableNotFound {
identifier: Identifier::new("x"),
position: (0, 0).into()
},
position: (32, 50).into()
}]
);

View File

@ -1,6 +1,7 @@
use dust_lang::{
abstract_tree::{Identifier, Type},
abstract_tree::{Type, WithPos},
error::{Error, TypeConflict, ValidationError},
identifier::Identifier,
interpret, Value,
};
@ -22,7 +23,7 @@ fn simple_structure() {
"
),
Ok(Some(Value::structure(
Identifier::new("Foo"),
Identifier::new("Foo").with_position((0, 0)),
vec![
(Identifier::new("bar"), Value::integer(42)),
(Identifier::new("baz"), Value::string("hiya".to_string())),
@ -83,11 +84,11 @@ fn nested_structure() {
"
),
Ok(Some(Value::structure(
Identifier::new("Foo"),
Identifier::new("Foo").with_position((0, 0)),
vec![(
Identifier::new("bar"),
Value::structure(
Identifier::new("Bar"),
Identifier::new("Bar").with_position((0, 0)),
vec![(Identifier::new("baz"), Value::integer(42))]
)
),]
@ -109,7 +110,10 @@ fn undefined_struct() {
.unwrap_err()
.errors(),
&vec![Error::Validation {
error: ValidationError::VariableNotFound(Identifier::new("Foo")),
error: ValidationError::VariableNotFound {
identifier: Identifier::new("Foo"),
position: (0, 0).into()
},
position: (17, 69).into()
}]
)

View File

@ -1,8 +1,9 @@
use std::collections::BTreeMap;
use dust_lang::{
abstract_tree::{Identifier, Type, WithPos},
abstract_tree::{Type, WithPos},
error::{Error, TypeConflict, ValidationError},
identifier::Identifier,
*,
};

View File

@ -1,6 +1,7 @@
use dust_lang::{
abstract_tree::{Block, Expression, Identifier, Statement, Type, WithPos},
abstract_tree::{Block, Expression, Statement, Type, WithPos},
error::{Error, TypeConflict, ValidationError},
identifier::Identifier,
*,
};
@ -49,9 +50,8 @@ fn function_variable() {
vec![(Identifier::new("x"), Type::Integer.with_position((13, 16)))],
Type::Integer.with_position((18, 21)),
Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x")
))
.with_position((24, 25))])
Identifier::new("x").with_position((0, 0))
))])
.with_position((9, 27))
)))
);

18
examples/fizzbuzz.ds Normal file
View File

@ -0,0 +1,18 @@
count = 1
while count <= 15 {
divides_by_3 = count % 3 == 0
divides_by_5 = count % 5 == 0
if divides_by_3 && divides_by_5 {
output('fizzbuzz')
} else if divides_by_3 {
output('fizz')
} else if divides_by_5 {
output('buzz')
} else {
output(count)
}
count += 1
}