Fix parser
This commit is contained in:
parent
46419956bd
commit
0e2d1021cb
@ -3,15 +3,15 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Statement, Type};
|
use super::{AbstractTree, Action, Positioned, Statement, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Positioned<Statement>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
pub fn new(statements: Vec<Statement>) -> Self {
|
pub fn new(statements: Vec<Positioned<Statement>>) -> Self {
|
||||||
Self { statements }
|
Self { statements }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ impl Block {
|
|||||||
impl AbstractTree for Block {
|
impl AbstractTree for Block {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||||
if let Some(statement) = self.statements.last() {
|
if let Some(statement) = self.statements.last() {
|
||||||
statement.expected_type(_context)
|
statement.node.expected_type(_context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Type::None)
|
Ok(Type::None)
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ impl AbstractTree for Block {
|
|||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
statement.validate(_context)?;
|
statement.node.validate(_context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -37,7 +37,7 @@ impl AbstractTree for Block {
|
|||||||
let mut previous = Action::None;
|
let mut previous = Action::None;
|
||||||
|
|
||||||
for statement in self.statements {
|
for statement in self.statements {
|
||||||
let action = statement.run(_context)?;
|
let action = statement.node.run(_context)?;
|
||||||
previous = match action {
|
previous = match action {
|
||||||
Action::Return(value) => Action::Return(value),
|
Action::Return(value) => Action::Return(value),
|
||||||
Action::None => Action::None,
|
Action::None => Action::None,
|
||||||
@ -62,14 +62,17 @@ mod tests {
|
|||||||
fn run_returns_value_of_final_statement() {
|
fn run_returns_value_of_final_statement() {
|
||||||
let block = Block::new(vec![
|
let block = Block::new(vec![
|
||||||
Statement::Expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::Integer(1)).positioned((0..1).into()),
|
Expression::Value(ValueNode::Integer(1)).positioned((0..0).into()),
|
||||||
),
|
)
|
||||||
|
.positioned((0..0).into()),
|
||||||
Statement::Expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::Integer(2)).positioned((0..1).into()),
|
Expression::Value(ValueNode::Integer(2)).positioned((0..0).into()),
|
||||||
),
|
)
|
||||||
|
.positioned((0..0).into()),
|
||||||
Statement::Expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
),
|
)
|
||||||
|
.positioned((0..0).into()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -83,10 +86,12 @@ mod tests {
|
|||||||
let block = Block::new(vec![
|
let block = Block::new(vec![
|
||||||
Statement::Expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()),
|
Expression::Value(ValueNode::String("42".to_string())).positioned((0..0).into()),
|
||||||
),
|
)
|
||||||
|
.positioned((0..0).into()),
|
||||||
Statement::Expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::Integer(42)).positioned((0..1).into()),
|
Expression::Value(ValueNode::Integer(42)).positioned((0..0).into()),
|
||||||
),
|
)
|
||||||
|
.positioned((0..0).into()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
|
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))
|
||||||
|
@ -3,16 +3,16 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Expression, Type};
|
use super::{AbstractTree, Action, Expression, Positioned, Type};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct FunctionCall {
|
pub struct FunctionCall {
|
||||||
function: Box<Expression>,
|
function: Box<Positioned<Expression>>,
|
||||||
arguments: Vec<Expression>,
|
arguments: Vec<Positioned<Expression>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionCall {
|
impl FunctionCall {
|
||||||
pub fn new(function: Expression, arguments: Vec<Expression>) -> Self {
|
pub fn new(function: Positioned<Expression>, arguments: Vec<Positioned<Expression>>) -> Self {
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
function: Box::new(function),
|
function: Box::new(function),
|
||||||
arguments,
|
arguments,
|
||||||
@ -22,7 +22,7 @@ impl FunctionCall {
|
|||||||
|
|
||||||
impl AbstractTree for FunctionCall {
|
impl AbstractTree for FunctionCall {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||||
if let Type::Function { return_type, .. } = self.function.expected_type(_context)? {
|
if let Type::Function { return_type, .. } = self.function.node.expected_type(_context)? {
|
||||||
Ok(*return_type)
|
Ok(*return_type)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction)
|
Err(ValidationError::ExpectedFunction)
|
||||||
@ -30,7 +30,7 @@ impl AbstractTree for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
if let Type::Function { .. } = self.function.expected_type(_context)? {
|
if let Type::Function { .. } = self.function.node.expected_type(_context)? {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction)
|
Err(ValidationError::ExpectedFunction)
|
||||||
@ -38,12 +38,12 @@ impl AbstractTree for FunctionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let value = self.function.run(context)?.as_return_value()?;
|
let value = self.function.node.run(context)?.as_return_value()?;
|
||||||
let function = value.as_function()?;
|
let function = value.as_function()?;
|
||||||
let mut arguments = Vec::with_capacity(self.arguments.len());
|
let mut arguments = Vec::with_capacity(self.arguments.len());
|
||||||
|
|
||||||
for expression in self.arguments {
|
for expression in self.arguments {
|
||||||
let value = expression.run(context)?.as_return_value()?;
|
let value = expression.node.run(context)?.as_return_value()?;
|
||||||
|
|
||||||
arguments.push(value);
|
arguments.push(value);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,8 @@ mod tests {
|
|||||||
Block::new(vec![Statement::Expression(
|
Block::new(vec![Statement::Expression(
|
||||||
Expression::Value(ValueNode::String("foo".to_string()))
|
Expression::Value(ValueNode::String("foo".to_string()))
|
||||||
.positioned((0..0).into())
|
.positioned((0..0).into())
|
||||||
)])
|
)
|
||||||
|
.positioned((0..0).into())])
|
||||||
.positioned((0..0).into()),
|
.positioned((0..0).into()),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
@ -104,13 +105,15 @@ mod tests {
|
|||||||
Block::new(vec![Statement::Expression(
|
Block::new(vec![Statement::Expression(
|
||||||
Expression::Value(ValueNode::String("foo".to_string()))
|
Expression::Value(ValueNode::String("foo".to_string()))
|
||||||
.positioned((0..0).into())
|
.positioned((0..0).into())
|
||||||
)])
|
)
|
||||||
|
.positioned((0..0).into())])
|
||||||
.positioned((0..0).into()),
|
.positioned((0..0).into()),
|
||||||
Some(
|
Some(
|
||||||
Block::new(vec![Statement::Expression(
|
Block::new(vec![Statement::Expression(
|
||||||
Expression::Value(ValueNode::String("bar".to_string()))
|
Expression::Value(ValueNode::String("bar".to_string()))
|
||||||
.positioned((0..0).into())
|
.positioned((0..0).into())
|
||||||
)])
|
)
|
||||||
|
.positioned((0..0).into())])
|
||||||
.positioned((0..0).into())
|
.positioned((0..0).into())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -3,28 +3,28 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Expression, Type, ValueNode};
|
use super::{AbstractTree, Action, Expression, Positioned, Type, ValueNode};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Index {
|
pub struct Index {
|
||||||
left: Expression,
|
left: Positioned<Expression>,
|
||||||
right: Expression,
|
right: Positioned<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index {
|
impl Index {
|
||||||
pub fn new(left: Expression, right: Expression) -> Self {
|
pub fn new(left: Positioned<Expression>, right: Positioned<Expression>) -> Self {
|
||||||
Self { left, right }
|
Self { left, right }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Index {
|
impl AbstractTree for Index {
|
||||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||||
let left_type = self.left.expected_type(_context)?;
|
let left_type = self.left.node.expected_type(_context)?;
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
Expression::Value(ValueNode::List(expression_list)),
|
Expression::Value(ValueNode::List(expression_list)),
|
||||||
Expression::Value(ValueNode::Integer(index)),
|
Expression::Value(ValueNode::Integer(index)),
|
||||||
) = (&self.left, &self.right)
|
) = (&self.left.node, &self.right.node)
|
||||||
{
|
{
|
||||||
let expression = if let Some(expression) = expression_list.get(*index as usize) {
|
let expression = if let Some(expression) = expression_list.get(*index as usize) {
|
||||||
expression
|
expression
|
||||||
@ -32,20 +32,20 @@ impl AbstractTree for Index {
|
|||||||
return Ok(Type::None);
|
return Ok(Type::None);
|
||||||
};
|
};
|
||||||
|
|
||||||
expression.expected_type(_context)
|
expression.node.expected_type(_context)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::CannotIndex(left_type))
|
Err(ValidationError::CannotIndex(left_type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
let left_type = self.left.expected_type(context)?;
|
let left_type = self.left.node.expected_type(context)?;
|
||||||
|
|
||||||
match left_type {
|
match left_type {
|
||||||
Type::List => todo!(),
|
Type::List => todo!(),
|
||||||
Type::ListOf(_) => todo!(),
|
Type::ListOf(_) => todo!(),
|
||||||
Type::ListExact(_) => {
|
Type::ListExact(_) => {
|
||||||
let right_type = self.right.expected_type(context)?;
|
let right_type = self.right.node.expected_type(context)?;
|
||||||
|
|
||||||
if let Type::Integer = right_type {
|
if let Type::Integer = right_type {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -58,8 +58,8 @@ impl AbstractTree for Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let left_value = self.left.run(_context)?.as_return_value()?;
|
let left_value = self.left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = self.right.run(_context)?.as_return_value()?;
|
let right_value = self.right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (Some(list), Some(index)) = (left_value.as_list(), right_value.as_integer()) {
|
if let (Some(list), Some(index)) = (left_value.as_list(), right_value.as_integer()) {
|
||||||
let found_item = list.get(index as usize);
|
let found_item = list.get(index as usize);
|
||||||
|
@ -3,15 +3,15 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Statement, Type};
|
use super::{AbstractTree, Action, Positioned, Statement, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Loop {
|
pub struct Loop {
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Positioned<Statement>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Loop {
|
impl Loop {
|
||||||
pub fn new(statements: Vec<Statement>) -> Self {
|
pub fn new(statements: Vec<Positioned<Statement>>) -> Self {
|
||||||
Self { statements }
|
Self { statements }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@ impl AbstractTree for Loop {
|
|||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
statement.validate(_context)?;
|
statement.node.validate(_context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -40,7 +40,7 @@ impl AbstractTree for Loop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let statement = self.statements[index].clone();
|
let statement = self.statements[index].clone();
|
||||||
let action = statement.run(_context)?;
|
let action = statement.node.run(_context)?;
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Action::Return(_) => {}
|
Action::Return(_) => {}
|
||||||
@ -58,7 +58,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn basic_loop() {
|
fn basic_loop() {
|
||||||
let result = Loop {
|
let result = Loop {
|
||||||
statements: vec![Statement::Break],
|
statements: vec![Statement::Break.positioned((0..0).into())],
|
||||||
}
|
}
|
||||||
.run(&Context::new());
|
.run(&Context::new());
|
||||||
|
|
||||||
|
@ -5,15 +5,15 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Expression, Type};
|
use super::{AbstractTree, Action, Expression, Positioned, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Math {
|
pub enum Math {
|
||||||
Add(Expression, Expression),
|
Add(Positioned<Expression>, Positioned<Expression>),
|
||||||
Subtract(Expression, Expression),
|
Subtract(Positioned<Expression>, Positioned<Expression>),
|
||||||
Multiply(Expression, Expression),
|
Multiply(Positioned<Expression>, Positioned<Expression>),
|
||||||
Divide(Expression, Expression),
|
Divide(Positioned<Expression>, Positioned<Expression>),
|
||||||
Modulo(Expression, Expression),
|
Modulo(Positioned<Expression>, Positioned<Expression>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for Math {
|
impl AbstractTree for Math {
|
||||||
@ -23,7 +23,7 @@ impl AbstractTree for Math {
|
|||||||
| Math::Subtract(left, _)
|
| Math::Subtract(left, _)
|
||||||
| Math::Multiply(left, _)
|
| Math::Multiply(left, _)
|
||||||
| Math::Divide(left, _)
|
| Math::Divide(left, _)
|
||||||
| Math::Modulo(left, _) => left.expected_type(_context),
|
| Math::Modulo(left, _) => left.node.expected_type(_context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,8 +34,8 @@ impl AbstractTree for Math {
|
|||||||
| Math::Multiply(left, right)
|
| Math::Multiply(left, right)
|
||||||
| Math::Divide(left, right)
|
| Math::Divide(left, right)
|
||||||
| Math::Modulo(left, right) => {
|
| Math::Modulo(left, right) => {
|
||||||
let left_type = left.expected_type(context)?;
|
let left_type = left.node.expected_type(context)?;
|
||||||
let right_type = right.expected_type(context)?;
|
let right_type = right.node.expected_type(context)?;
|
||||||
|
|
||||||
match (left_type, right_type) {
|
match (left_type, right_type) {
|
||||||
(Type::Integer, Type::Integer)
|
(Type::Integer, Type::Integer)
|
||||||
@ -51,20 +51,20 @@ impl AbstractTree for Math {
|
|||||||
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
|
||||||
let value = match self {
|
let value = match self {
|
||||||
Math::Add(left, right) => {
|
Math::Add(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
left_value.add(&right_value)?
|
left_value.add(&right_value)?
|
||||||
}
|
}
|
||||||
Math::Subtract(left, right) => {
|
Math::Subtract(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
left_value.subtract(&right_value)?
|
left_value.subtract(&right_value)?
|
||||||
}
|
}
|
||||||
Math::Multiply(left, right) => {
|
Math::Multiply(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||||
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
||||||
@ -77,8 +77,8 @@ impl AbstractTree for Math {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Math::Divide(left, right) => {
|
Math::Divide(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||||
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
||||||
@ -91,8 +91,8 @@ impl AbstractTree for Math {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Math::Modulo(left, right) => {
|
Math::Modulo(left, right) => {
|
||||||
let left_value = left.run(_context)?.as_return_value()?;
|
let left_value = left.node.run(_context)?.as_return_value()?;
|
||||||
let right_value = right.run(_context)?.as_return_value()?;
|
let right_value = right.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||||
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
(left_value.inner().as_ref(), right_value.inner().as_ref())
|
||||||
|
@ -2,7 +2,7 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, TypeConflict, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -13,12 +13,12 @@ pub enum ValueNode {
|
|||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
List(Vec<Expression>),
|
List(Vec<Positioned<Expression>>),
|
||||||
Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>),
|
Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>),
|
||||||
Range(Range<i64>),
|
Range(Range<i64>),
|
||||||
String(String),
|
String(String),
|
||||||
Function {
|
Function {
|
||||||
parameters: Vec<(Identifier, Type)>,
|
parameters: Vec<(Identifier, Positioned<Type>)>,
|
||||||
return_type: Positioned<Type>,
|
return_type: Positioned<Type>,
|
||||||
body: Positioned<Block>,
|
body: Positioned<Block>,
|
||||||
},
|
},
|
||||||
@ -34,7 +34,7 @@ impl AbstractTree for ValueNode {
|
|||||||
let mut item_types = Vec::with_capacity(items.len());
|
let mut item_types = Vec::with_capacity(items.len());
|
||||||
|
|
||||||
for expression in items {
|
for expression in items {
|
||||||
item_types.push(expression.expected_type(_context)?);
|
item_types.push(expression.node.expected_type(_context)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::ListExact(item_types)
|
Type::ListExact(item_types)
|
||||||
@ -49,8 +49,7 @@ impl AbstractTree for ValueNode {
|
|||||||
} => Type::Function {
|
} => Type::Function {
|
||||||
parameter_types: parameters
|
parameter_types: parameters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, r#type)| r#type)
|
.map(|(_, r#type)| r#type.node.clone())
|
||||||
.cloned()
|
|
||||||
.collect(),
|
.collect(),
|
||||||
return_type: Box::new(return_type.node.clone()),
|
return_type: Box::new(return_type.node.clone()),
|
||||||
},
|
},
|
||||||
@ -85,7 +84,7 @@ impl AbstractTree for ValueNode {
|
|||||||
let function_context = Context::inherit_types_from(context)?;
|
let function_context = Context::inherit_types_from(context)?;
|
||||||
|
|
||||||
for (identifier, r#type) in parameters {
|
for (identifier, r#type) in parameters {
|
||||||
function_context.set_type(identifier.clone(), r#type.clone())?;
|
function_context.set_type(identifier.clone(), r#type.node.clone())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.node.validate(&function_context)?;
|
body.node.validate(&function_context)?;
|
||||||
@ -114,7 +113,7 @@ impl AbstractTree for ValueNode {
|
|||||||
let mut value_list = Vec::with_capacity(expression_list.len());
|
let mut value_list = Vec::with_capacity(expression_list.len());
|
||||||
|
|
||||||
for expression in expression_list {
|
for expression in expression_list {
|
||||||
let value = expression.run(_context)?.as_return_value()?;
|
let value = expression.node.run(_context)?.as_return_value()?;
|
||||||
|
|
||||||
value_list.push(value);
|
value_list.push(value);
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,16 @@ use crate::{
|
|||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractTree, Action, Block, Expression, Type};
|
use super::{AbstractTree, Action, Block, Expression, Positioned, Type};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct While {
|
pub struct While {
|
||||||
expression: Expression,
|
expression: Positioned<Expression>,
|
||||||
block: Block,
|
block: Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl While {
|
impl While {
|
||||||
pub fn new(expression: Expression, block: Block) -> Self {
|
pub fn new(expression: Positioned<Expression>, block: Block) -> Self {
|
||||||
Self { expression, block }
|
Self { expression, block }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,13 +23,14 @@ impl AbstractTree for While {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||||
self.expression.validate(_context)?;
|
self.expression.node.validate(_context)?;
|
||||||
self.block.validate(_context)
|
self.block.validate(_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
fn run(self, context: &Context) -> Result<Action, RuntimeError> {
|
||||||
while self
|
while self
|
||||||
.expression
|
.expression
|
||||||
|
.node
|
||||||
.clone()
|
.clone()
|
||||||
.run(context)?
|
.run(context)?
|
||||||
.as_return_value()?
|
.as_return_value()?
|
||||||
|
313
src/parser.rs
313
src/parser.rs
@ -1,6 +1,7 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap};
|
use std::{cell::RefCell, collections::HashMap};
|
||||||
|
|
||||||
use chumsky::{input::SpannedInput, pratt::*, prelude::*};
|
use chumsky::{input::SpannedInput, pratt::*, prelude::*};
|
||||||
|
use clap::builder::TypedValueParser;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::*,
|
abstract_tree::*,
|
||||||
@ -53,12 +54,12 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
Token::Float(float) => ValueNode::Float(float),
|
Token::Float(float) => ValueNode::Float(float),
|
||||||
Token::String(string) => ValueNode::String(string.to_string()),
|
Token::String(string) => ValueNode::String(string.to_string()),
|
||||||
}
|
}
|
||||||
.map(|value| Expression::Value(value))
|
.map_with(|value, state| Expression::Value(value).positioned(state.span()))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let type_specification = recursive(|type_specification| {
|
|
||||||
let r#type = recursive(|r#type| {
|
let r#type = recursive(|r#type| {
|
||||||
let function_type = type_specification
|
let type_specification = recursive(|r#type| {
|
||||||
|
let function_type = r#type
|
||||||
.clone()
|
.clone()
|
||||||
.separated_by(just(Token::Control(Control::Comma)))
|
.separated_by(just(Token::Control(Control::Comma)))
|
||||||
.collect()
|
.collect()
|
||||||
@ -108,11 +109,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
))
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
just(Token::Control(Control::Colon)).ignore_then(r#type)
|
just(Token::Control(Control::Colon)).ignore_then(type_specification)
|
||||||
});
|
})
|
||||||
|
.map_with(|r#type, state| r#type.positioned(state.span()));
|
||||||
let positioned_type =
|
|
||||||
type_specification.map_with(|r#type, state| r#type.positioned(state.span()));
|
|
||||||
|
|
||||||
let statement = recursive(|statement| {
|
let statement = recursive(|statement| {
|
||||||
let block = statement
|
let block = statement
|
||||||
@ -130,10 +129,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
.map_with(|block, state| block.positioned(state.span()));
|
.map_with(|block, state| block.positioned(state.span()));
|
||||||
|
|
||||||
let expression = recursive(|expression| {
|
let expression = recursive(|expression| {
|
||||||
let identifier_expression = identifier
|
let identifier_expression = identifier.clone().map_with(|identifier, state| {
|
||||||
.clone()
|
Expression::Identifier(identifier).positioned(state.span())
|
||||||
.map(|identifier| Expression::Identifier(identifier))
|
});
|
||||||
.boxed();
|
|
||||||
|
|
||||||
let range = {
|
let range = {
|
||||||
let raw_integer = select! {
|
let raw_integer = select! {
|
||||||
@ -144,7 +142,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
.clone()
|
.clone()
|
||||||
.then_ignore(just(Token::Control(Control::DoubleDot)))
|
.then_ignore(just(Token::Control(Control::DoubleDot)))
|
||||||
.then(raw_integer)
|
.then(raw_integer)
|
||||||
.map(|(start, end)| Expression::Value(ValueNode::Range(start..end)))
|
.map_with(|(start, end), state| {
|
||||||
|
Expression::Value(ValueNode::Range(start..end)).positioned(state.span())
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let list = expression
|
let list = expression
|
||||||
@ -156,22 +156,16 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::SquareOpen)),
|
just(Token::Control(Control::SquareOpen)),
|
||||||
just(Token::Control(Control::SquareClose)),
|
just(Token::Control(Control::SquareClose)),
|
||||||
)
|
)
|
||||||
.map(|list| Expression::Value(ValueNode::List(list)))
|
.map_with(|list, state| {
|
||||||
.boxed();
|
Expression::Value(ValueNode::List(list)).positioned(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
let map_assignment = identifier
|
let map_assignment = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(
|
.then(r#type.clone().or_not())
|
||||||
type_specification
|
|
||||||
.map_with(|r#type, state| r#type.positioned(state.span()))
|
|
||||||
.clone()
|
|
||||||
.or_not(),
|
|
||||||
)
|
|
||||||
.then_ignore(just(Token::Operator(Operator::Assign)))
|
.then_ignore(just(Token::Operator(Operator::Assign)))
|
||||||
.then(expression.clone())
|
.then(expression.clone())
|
||||||
.map_with(|((identifier, r#type), expression), state| {
|
.map(|((identifier, r#type), expression)| (identifier, r#type, expression));
|
||||||
(identifier, r#type, expression.positioned(state.span()))
|
|
||||||
});
|
|
||||||
|
|
||||||
let map = map_assignment
|
let map = map_assignment
|
||||||
.separated_by(just(Token::Control(Control::Comma)).or_not())
|
.separated_by(just(Token::Control(Control::Comma)).or_not())
|
||||||
@ -181,27 +175,29 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::CurlyOpen)),
|
just(Token::Control(Control::CurlyOpen)),
|
||||||
just(Token::Control(Control::CurlyClose)),
|
just(Token::Control(Control::CurlyClose)),
|
||||||
)
|
)
|
||||||
.map(|map_assigment_list| Expression::Value(ValueNode::Map(map_assigment_list)));
|
.map_with(|map_assigment_list, state| {
|
||||||
|
Expression::Value(ValueNode::Map(map_assigment_list)).positioned(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
let function = identifier
|
let function = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(type_specification.clone())
|
.then(r#type.clone())
|
||||||
.separated_by(just(Token::Control(Control::Comma)))
|
.separated_by(just(Token::Control(Control::Comma)))
|
||||||
.collect::<Vec<(Identifier, Type)>>()
|
.collect()
|
||||||
.delimited_by(
|
.delimited_by(
|
||||||
just(Token::Control(Control::ParenOpen)),
|
just(Token::Control(Control::ParenOpen)),
|
||||||
just(Token::Control(Control::ParenClose)),
|
just(Token::Control(Control::ParenClose)),
|
||||||
)
|
)
|
||||||
.then(type_specification.clone())
|
.then(r#type.clone())
|
||||||
.then(block.clone())
|
.then(block.clone())
|
||||||
.map_with(|((parameters, return_type), body), state| {
|
.map_with(|((parameters, return_type), body), state| {
|
||||||
Expression::Value(ValueNode::Function {
|
Expression::Value(ValueNode::Function {
|
||||||
parameters,
|
parameters,
|
||||||
return_type: return_type.positioned(state.span()),
|
return_type,
|
||||||
body: body.positioned(state.span()),
|
body: body.positioned(state.span()),
|
||||||
})
|
})
|
||||||
})
|
.positioned(state.span())
|
||||||
.boxed();
|
});
|
||||||
|
|
||||||
let function_expression = choice((identifier_expression.clone(), function.clone()));
|
let function_expression = choice((identifier_expression.clone(), function.clone()));
|
||||||
|
|
||||||
@ -216,13 +212,13 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::ParenClose)),
|
just(Token::Control(Control::ParenClose)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map(|(function, arguments)| {
|
.map_with(|(function, arguments), state| {
|
||||||
Expression::FunctionCall(FunctionCall::new(function, arguments))
|
Expression::FunctionCall(FunctionCall::new(function, arguments))
|
||||||
})
|
.positioned(state.span())
|
||||||
.boxed();
|
});
|
||||||
|
|
||||||
let atom = choice((
|
let atom = choice((
|
||||||
function_call,
|
function_call.clone(),
|
||||||
identifier_expression.clone(),
|
identifier_expression.clone(),
|
||||||
basic_value.clone(),
|
basic_value.clone(),
|
||||||
list.clone(),
|
list.clone(),
|
||||||
@ -230,68 +226,115 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Control(Control::ParenOpen)),
|
just(Token::Control(Control::ParenOpen)),
|
||||||
just(Token::Control(Control::ParenClose)),
|
just(Token::Control(Control::ParenClose)),
|
||||||
),
|
),
|
||||||
))
|
));
|
||||||
.map_with(|expression, state| expression.positioned(state.span()));
|
|
||||||
|
|
||||||
use Operator::*;
|
use Operator::*;
|
||||||
|
|
||||||
let logic_math_and_index = atom
|
let logic_math_and_index = atom.pratt((
|
||||||
.pratt((
|
prefix(2, just(Token::Operator(Not)), |_, expression, span| {
|
||||||
prefix(2, just(Token::Operator(Not)), |expression| {
|
Expression::Logic(Box::new(Logic::Not(expression))).positioned(span)
|
||||||
Expression::Logic(Box::new(Logic::Not(expression)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Equal)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::Equal(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(NotEqual)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::NotEqual(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Greater)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::Greater(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Less)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::Less(left, right)))
|
|
||||||
}),
|
}),
|
||||||
|
infix(
|
||||||
|
left(3),
|
||||||
|
just(Token::Control(Control::Dot)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Index(Box::new(Index::new(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Equal)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::Equal(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(NotEqual)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::NotEqual(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Greater)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::Greater(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Less)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::Less(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
infix(
|
infix(
|
||||||
left(1),
|
left(1),
|
||||||
just(Token::Operator(GreaterOrEqual)),
|
just(Token::Operator(GreaterOrEqual)),
|
||||||
|left, right| {
|
|left, _, right, span| {
|
||||||
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
|
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
|
||||||
|
.positioned(span)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
infix(
|
infix(
|
||||||
left(1),
|
left(1),
|
||||||
just(Token::Operator(LessOrEqual)),
|
just(Token::Operator(LessOrEqual)),
|
||||||
|left, right| Expression::Logic(Box::new(Logic::LessOrEqual(left, right))),
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::LessOrEqual(left, right)))
|
||||||
|
.positioned(span)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
infix(left(1), just(Token::Operator(And)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::And(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Or)), |left, right| {
|
|
||||||
Expression::Logic(Box::new(Logic::Or(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Add)), |left, right| {
|
|
||||||
Expression::Math(Box::new(Math::Add(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Subtract)), |left, right| {
|
|
||||||
Expression::Math(Box::new(Math::Subtract(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(2), just(Token::Operator(Multiply)), |left, right| {
|
|
||||||
Expression::Math(Box::new(Math::Multiply(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(2), just(Token::Operator(Divide)), |left, right| {
|
|
||||||
Expression::Math(Box::new(Math::Divide(left, right)))
|
|
||||||
}),
|
|
||||||
infix(left(1), just(Token::Operator(Modulo)), |left, right| {
|
|
||||||
Expression::Math(Box::new(Math::Modulo(left, right)))
|
|
||||||
}),
|
|
||||||
infix(
|
infix(
|
||||||
left(3),
|
left(1),
|
||||||
just(Token::Control(Control::Dot)),
|
just(Token::Operator(And)),
|
||||||
|left, right| Expression::Index(Box::new(Index::new(left, right))),
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::And(left, right))).positioned(span)
|
||||||
|
},
|
||||||
),
|
),
|
||||||
))
|
infix(
|
||||||
.boxed();
|
left(1),
|
||||||
|
just(Token::Operator(Or)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Logic(Box::new(Logic::Or(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Add)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Math(Box::new(Math::Add(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Subtract)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Math(Box::new(Math::Subtract(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(2),
|
||||||
|
just(Token::Operator(Multiply)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Math(Box::new(Math::Multiply(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(2),
|
||||||
|
just(Token::Operator(Divide)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Math(Box::new(Math::Divide(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
infix(
|
||||||
|
left(1),
|
||||||
|
just(Token::Operator(Modulo)),
|
||||||
|
|left, _, right, span| {
|
||||||
|
Expression::Math(Box::new(Math::Modulo(left, right))).positioned(span)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
function,
|
function,
|
||||||
@ -303,25 +346,18 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
map,
|
map,
|
||||||
basic_value,
|
basic_value,
|
||||||
))
|
))
|
||||||
.boxed()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let positioned_expression = expression
|
let expression_statement = expression.clone().map_with(|expression, state| {
|
||||||
.clone()
|
Statement::Expression(expression).positioned(state.span())
|
||||||
.map_with(|expression, state| expression.positioned(state.span()));
|
});
|
||||||
|
|
||||||
let expression_statement = expression
|
let r#break = just(Token::Keyword("break"))
|
||||||
.clone()
|
.map_with(|_, state| Statement::Break.positioned(state.span()));
|
||||||
.map_with(|expression, state| {
|
|
||||||
Statement::Expression(expression.positioned(state.span()))
|
|
||||||
})
|
|
||||||
.boxed();
|
|
||||||
|
|
||||||
let r#break = just(Token::Keyword("break")).to(Statement::Break);
|
|
||||||
|
|
||||||
let assignment = identifier
|
let assignment = identifier
|
||||||
.clone()
|
.clone()
|
||||||
.then(positioned_type.clone().or_not())
|
.then(r#type.clone().or_not())
|
||||||
.then(choice((
|
.then(choice((
|
||||||
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
|
just(Token::Operator(Operator::Assign)).to(AssignmentOperator::Assign),
|
||||||
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
|
just(Token::Operator(Operator::AddAssign)).to(AssignmentOperator::AddAssign),
|
||||||
@ -329,18 +365,13 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
)))
|
)))
|
||||||
.then(statement.clone())
|
.then(statement.clone())
|
||||||
.map_with(|(((identifier, r#type), operator), statement), state| {
|
.map_with(|(((identifier, r#type), operator), statement), state| {
|
||||||
Statement::Assignment(Assignment::new(
|
Statement::Assignment(Assignment::new(identifier, r#type, operator, statement))
|
||||||
identifier,
|
.positioned(state.span())
|
||||||
r#type,
|
});
|
||||||
operator,
|
|
||||||
statement.positioned(state.span()),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.boxed();
|
|
||||||
|
|
||||||
let block_statement = block
|
let block_statement = block
|
||||||
.clone()
|
.clone()
|
||||||
.map_with(|block, state| Statement::Block(block));
|
.map_with(|block, state| Statement::Block(block).positioned(state.span()));
|
||||||
|
|
||||||
let r#loop = statement
|
let r#loop = statement
|
||||||
.clone()
|
.clone()
|
||||||
@ -351,16 +382,19 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
|
just(Token::Keyword("loop")).then(just(Token::Control(Control::CurlyOpen))),
|
||||||
just(Token::Control(Control::CurlyClose)),
|
just(Token::Control(Control::CurlyClose)),
|
||||||
)
|
)
|
||||||
.map_with(|statements, state| Statement::Loop(Loop::new(statements)))
|
.map_with(|statements, state| {
|
||||||
.boxed();
|
Statement::Loop(Loop::new(statements)).positioned(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
let r#while = just(Token::Keyword("while"))
|
let r#while = just(Token::Keyword("while"))
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.then(block.clone())
|
.then(block.clone())
|
||||||
.map_with(|(expression, block), state| Statement::While(While::new(expression, block)));
|
.map_with(|(expression, block), state| {
|
||||||
|
Statement::While(While::new(expression, block)).positioned(state.span())
|
||||||
|
});
|
||||||
|
|
||||||
let if_else = just(Token::Keyword("if"))
|
let if_else = just(Token::Keyword("if"))
|
||||||
.ignore_then(positioned_expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.then(positioned_block.clone())
|
.then(positioned_block.clone())
|
||||||
.then(
|
.then(
|
||||||
just(Token::Keyword("else"))
|
just(Token::Keyword("else"))
|
||||||
@ -369,8 +403,8 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
)
|
)
|
||||||
.map_with(|((if_expression, if_block), else_block), state| {
|
.map_with(|((if_expression, if_block), else_block), state| {
|
||||||
Statement::IfElse(IfElse::new(if_expression, if_block, else_block))
|
Statement::IfElse(IfElse::new(if_expression, if_block, else_block))
|
||||||
})
|
.positioned(state.span())
|
||||||
.boxed();
|
});
|
||||||
|
|
||||||
choice((
|
choice((
|
||||||
if_else,
|
if_else,
|
||||||
@ -382,14 +416,9 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
r#while,
|
r#while,
|
||||||
))
|
))
|
||||||
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
|
||||||
.boxed()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
statement
|
statement.repeated().collect().boxed()
|
||||||
.map_with(|statement, state| statement.positioned(state.span()))
|
|
||||||
.repeated()
|
|
||||||
.collect()
|
|
||||||
.boxed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -402,19 +431,19 @@ mod tests {
|
|||||||
fn r#while() {
|
fn r#while() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0],
|
parse(&lex("while true { output('hi') }").unwrap()).unwrap()[0],
|
||||||
Statement::r#while(
|
Statement::While(While::new(
|
||||||
While::new(
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into()),
|
||||||
Expression::Value(ValueNode::Boolean(true)),
|
Block::new(vec![Statement::Expression(
|
||||||
Block::new(vec![Statement::expression(
|
|
||||||
Expression::FunctionCall(FunctionCall::new(
|
Expression::FunctionCall(FunctionCall::new(
|
||||||
Expression::Identifier(Identifier::new("output")),
|
Expression::Identifier(Identifier::new("output")).positioned((0..0).into()),
|
||||||
vec![Expression::Value(ValueNode::String("hi".to_string()))]
|
vec![Expression::Value(ValueNode::String("hi".to_string()))
|
||||||
)),
|
.positioned((0..0).into())]
|
||||||
(0..0).into()
|
))
|
||||||
)])
|
.positioned((0..0).into())
|
||||||
),
|
|
||||||
(0..0).into()
|
|
||||||
)
|
)
|
||||||
|
.positioned((0..0).into())])
|
||||||
|
))
|
||||||
|
.positioned((0..0).into())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,35 +451,33 @@ mod tests {
|
|||||||
fn types() {
|
fn types() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("foobar : bool = true").unwrap()).unwrap()[0],
|
parse(&lex("foobar : bool = true").unwrap()).unwrap()[0],
|
||||||
Statement::assignment(
|
Statement::Assignment(Assignment::new(
|
||||||
Assignment::new(
|
|
||||||
Identifier::new("foobar"),
|
Identifier::new("foobar"),
|
||||||
Some(Type::Boolean),
|
Some(Type::Boolean.positioned((0..0).into())),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Statement::expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::Boolean(true)),
|
Expression::Value(ValueNode::Boolean(true)).positioned((0..0).into())
|
||||||
(0..0).into()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
(0..0).into()
|
|
||||||
)
|
)
|
||||||
|
.positioned((0..0).into())
|
||||||
|
),)
|
||||||
|
.positioned((0..0).into())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0],
|
parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0],
|
||||||
Statement::assignment(
|
Statement::Assignment(Assignment::new(
|
||||||
Assignment::new(
|
|
||||||
Identifier::new("foobar"),
|
Identifier::new("foobar"),
|
||||||
Some(Type::ListOf(Box::new(Type::Boolean))),
|
Some(Type::ListOf(Box::new(Type::Boolean)).positioned((0..0).into())),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Statement::expression(
|
Statement::Expression(
|
||||||
Expression::Value(ValueNode::List(vec![Expression::Value(
|
Expression::Value(ValueNode::List(vec![Expression::Value(
|
||||||
ValueNode::Boolean(true)
|
ValueNode::Boolean(true)
|
||||||
)])),
|
|
||||||
(0..0).into()
|
|
||||||
)
|
)
|
||||||
),
|
.positioned((0..0).into())]))
|
||||||
(0..0).into()
|
.positioned((0..0).into())
|
||||||
)
|
)
|
||||||
|
.positioned((0..0).into())
|
||||||
|
))
|
||||||
|
.positioned((0..0).into())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0],
|
parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0],
|
||||||
|
@ -55,7 +55,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn function(
|
pub fn function(
|
||||||
parameters: Vec<(Identifier, Type)>,
|
parameters: Vec<(Identifier, Positioned<Type>)>,
|
||||||
return_type: Positioned<Type>,
|
return_type: Positioned<Type>,
|
||||||
body: Positioned<Block>,
|
body: Positioned<Block>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -224,7 +224,7 @@ impl Display for Value {
|
|||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
|
|
||||||
for (identifier, r#type) in parameters {
|
for (identifier, r#type) in parameters {
|
||||||
write!(f, "{identifier}: {}", r#type)?;
|
write!(f, "{identifier}: {}", r#type.node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "): {} {:?}", return_type.node, body.node)
|
write!(f, "): {} {:?}", return_type.node, body.node)
|
||||||
@ -330,7 +330,7 @@ impl Function {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct ParsedFunction {
|
pub struct ParsedFunction {
|
||||||
parameters: Vec<(Identifier, Type)>,
|
parameters: Vec<(Identifier, Positioned<Type>)>,
|
||||||
return_type: Positioned<Type>,
|
return_type: Positioned<Type>,
|
||||||
body: Positioned<Block>,
|
body: Positioned<Block>,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user