From 43b2393d8a2d571e19a75bf7e615cd060aa14221 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 14 Aug 2024 14:28:39 -0400 Subject: [PATCH] Begin AST overhaul --- dust-lang/src/abstract_tree.rs | 580 ---------- dust-lang/src/abstract_tree/expression.rs | 526 +++++++++ dust-lang/src/abstract_tree/mod.rs | 145 +++ dust-lang/src/analyzer.rs | 564 ++-------- dust-lang/src/parser.rs | 1247 ++++++++------------- dust-lang/src/value.rs | 38 +- dust-lang/src/vm.rs | 65 +- 7 files changed, 1266 insertions(+), 1899 deletions(-) delete mode 100644 dust-lang/src/abstract_tree.rs create mode 100644 dust-lang/src/abstract_tree/expression.rs create mode 100644 dust-lang/src/abstract_tree/mod.rs diff --git a/dust-lang/src/abstract_tree.rs b/dust-lang/src/abstract_tree.rs deleted file mode 100644 index 7139175..0000000 --- a/dust-lang/src/abstract_tree.rs +++ /dev/null @@ -1,580 +0,0 @@ -//! In-memory representation of a Dust program. -use std::{ - collections::{BTreeMap, VecDeque}, - fmt::{self, Display, Formatter}, -}; - -use serde::{Deserialize, Serialize}; - -use crate::{BuiltInFunction, Context, Identifier, Span, Type, Value}; - -/// In-memory representation of a Dust program. -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct AbstractSyntaxTree { - pub nodes: VecDeque>, -} - -impl AbstractSyntaxTree { - pub fn new() -> Self { - Self { - nodes: VecDeque::new(), - } - } -} - -impl Default for AbstractSyntaxTree { - fn default() -> Self { - Self::new() - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct Node { - pub inner: T, - pub position: Span, -} - -impl Node { - pub fn new(inner: T, position: Span) -> Self { - Self { inner, position } - } -} - -impl Display for Node { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.inner) - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum Statement { - // Assignment does not return a value, but has a side effect on the context - Assignment { - identifier: Node, - operator: Node, - value: Box>, - }, - AssignmentMut { - identifier: Node, - value: Box>, - }, - - // Statement blocks, delimited by curly braces - AsyncBlock(Vec>), - Block(Vec>), - - // Logic, math and comparison expressions with two operands - BinaryOperation { - left: Box>, - operator: Node, - right: Box>, - }, - - // Logic and math expressions with one operand - UnaryOperation { - operator: Node, - operand: Box>, - }, - - // Type definitions - StructDefinition(StructDefinition), - - // Function calls and type instantiation - BuiltInFunctionCall { - function: BuiltInFunction, - type_arguments: Option>>, - value_arguments: Option>>, - }, - Invokation { - invokee: Box>, - type_arguments: Option>>, - value_arguments: Option>>, - }, - FieldsStructInstantiation { - name: Node, - fields: Vec<(Node, Node)>, - }, - - // Loops - While { - condition: Box>, - body: Box>, - }, - - // Control flow - If { - condition: Box>, - body: Box>, - }, - IfElse { - condition: Box>, - if_body: Box>, - else_body: Box>, - }, - IfElseIf { - condition: Box>, - if_body: Box>, - else_ifs: Vec<(Node, Node)>, - }, - IfElseIfElse { - condition: Box>, - if_body: Box>, - else_ifs: Vec<(Node, Node)>, - else_body: Box>, - }, - - // Identifier - // - // Identifier statements in the syntax tree (i.e. Node) are evaluated as - // expressions or reconstructed into a Node by the parser - Identifier(Identifier), - - // Value collection expressions - List(Vec>), - Map(Vec<(Node, Node)>), - - // Hard-coded value - Constant(Value), - ConstantMut(Value), - - // A statement that always returns None. Created with a semicolon, it causes the preceding - // statement to return None. This is analagous to the semicolon in Rust. - Nil(Box>), -} - -impl Statement { - pub fn expected_type(&self, context: &Context) -> Option { - match self { - Statement::AsyncBlock(_) => None, - Statement::Assignment { .. } => None, - Statement::AssignmentMut { .. } => None, - Statement::Block(statements) => statements.last().unwrap().inner.expected_type(context), - Statement::BinaryOperation { - left, - operator, - right, - } => match operator.inner { - BinaryOperator::Add - | BinaryOperator::Divide - | BinaryOperator::Modulo - | BinaryOperator::Multiply - | BinaryOperator::Subtract => Some(left.inner.expected_type(context)?), - - BinaryOperator::Equal - | BinaryOperator::Greater - | BinaryOperator::GreaterOrEqual - | BinaryOperator::Less - | BinaryOperator::LessOrEqual - | BinaryOperator::And - | BinaryOperator::Or => Some(Type::Boolean), - - BinaryOperator::FieldAccess => { - let left_type = left.inner.expected_type(context)?; - - if let Type::Map(properties) = left_type { - let key = match &right.inner { - Statement::Identifier(identifier) => identifier, - _ => return None, - }; - - properties.get(key).cloned() - } else { - None - } - } - BinaryOperator::ListIndex => { - let left_type = left.inner.expected_type(context)?; - - if let Type::List { item_type, .. } = left_type { - Some(*item_type) - } else { - None - } - } - }, - Statement::BuiltInFunctionCall { function, .. } => function.expected_return_type(), - Statement::Constant(value) => Some(value.r#type()), - Statement::ConstantMut(value) => Some(value.r#type()), - Statement::FieldsStructInstantiation { name, .. } => context.get_type(&name.inner), - Statement::Invokation { - invokee: function, .. - } => function.inner.expected_type(context), - Statement::Identifier(identifier) => context.get_type(identifier), - Statement::If { .. } => None, - Statement::IfElse { if_body, .. } => if_body.inner.expected_type(context), - Statement::IfElseIf { .. } => None, - Statement::IfElseIfElse { if_body, .. } => if_body.inner.expected_type(context), - Statement::List(nodes) => { - let item_type = nodes.first().unwrap().inner.expected_type(context)?; - - Some(Type::List { - item_type: Box::new(item_type), - length: nodes.len(), - }) - } - Statement::Map(nodes) => { - let mut types = BTreeMap::new(); - - for (identifier, item) in nodes { - types.insert(identifier.inner.clone(), item.inner.expected_type(context)?); - } - - Some(Type::Map(types)) - } - Statement::Nil(_) => None, - Statement::UnaryOperation { operator, operand } => match operator.inner { - UnaryOperator::Negate => Some(operand.inner.expected_type(context)?), - UnaryOperator::Not => Some(Type::Boolean), - }, - Statement::StructDefinition(_) => None, - Statement::While { .. } => None, - } - } - - pub fn block_statements_mut(&mut self) -> Option<&mut Vec>> { - match self { - Statement::Block(statements) => Some(statements), - _ => None, - } - } - - pub fn map_properties_mut(&mut self) -> Option<&mut Vec<(Node, Node)>> { - match self { - Statement::Map(properties) => Some(properties), - _ => None, - } - } -} - -impl Display for Statement { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Statement::Assignment { - identifier, - operator, - value, - } => { - write!(f, "{identifier} {operator} {value}") - } - Statement::AssignmentMut { identifier, value } => { - write!(f, "mut {identifier} = {value}") - } - Statement::AsyncBlock(statements) => { - write!(f, "async {{ ")?; - - for (i, statement) in statements.iter().enumerate() { - if i > 0 { - write!(f, " ")?; - } - - write!(f, "{statement}")?; - } - - write!(f, " }}") - } - Statement::Block(statements) => { - write!(f, "{{ ")?; - - for (i, statement) in statements.iter().enumerate() { - if i > 0 { - write!(f, " ")?; - } - - write!(f, "{statement}")?; - } - - write!(f, " }}") - } - Statement::BinaryOperation { - left, - operator, - right, - } => { - let operator = match operator.inner { - BinaryOperator::FieldAccess => return write!(f, "{left}.{right}"), - BinaryOperator::ListIndex => return write!(f, "{left}[{right}]"), - BinaryOperator::Add => "+", - BinaryOperator::Divide => "/", - BinaryOperator::Equal => "==", - BinaryOperator::Greater => ">", - BinaryOperator::GreaterOrEqual => ">=", - BinaryOperator::Less => "<", - BinaryOperator::LessOrEqual => "<=", - BinaryOperator::Modulo => "%", - BinaryOperator::Multiply => "*", - BinaryOperator::Subtract => "-", - BinaryOperator::And => "&&", - BinaryOperator::Or => "||", - }; - - write!(f, "{left} {operator} {right}") - } - Statement::BuiltInFunctionCall { - function, - type_arguments: type_parameters, - value_arguments: value_parameters, - } => { - write!(f, "{function}")?; - - if let Some(type_parameters) = type_parameters { - write!(f, "<")?; - - for (i, type_parameter) in type_parameters.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{type_parameter}")?; - } - - write!(f, ">")?; - } - - write!(f, "(")?; - - if let Some(value_parameters) = value_parameters { - for (i, value_parameter) in value_parameters.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{value_parameter}")?; - } - } - - write!(f, ")") - } - Statement::Constant(value) => write!(f, "{value}"), - Statement::ConstantMut(value) => write!(f, "{value}"), - Statement::FieldsStructInstantiation { name, fields } => { - write!(f, "{name} {{ ")?; - - for (i, (identifier, value)) in fields.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{identifier}: {value}")?; - } - - write!(f, " }}") - } - Statement::Invokation { - invokee: function, - type_arguments: type_parameters, - value_arguments: value_parameters, - } => { - write!(f, "{function}")?; - - if let Some(type_parameters) = type_parameters { - write!(f, "<")?; - - for (i, type_parameter) in type_parameters.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{type_parameter}")?; - } - - write!(f, ">")?; - } - - write!(f, "(")?; - - if let Some(value_parameters) = value_parameters { - for (i, value_parameter) in value_parameters.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{value_parameter}")?; - } - } - - write!(f, ")") - } - Statement::Identifier(identifier) => write!(f, "{identifier}"), - Statement::If { condition, body } => { - write!(f, "if {condition} {body}") - } - Statement::IfElse { - condition, - if_body, - else_body, - } => { - write!(f, "if {condition} {if_body} else {else_body}") - } - Statement::IfElseIf { - condition, - if_body, - else_ifs, - } => { - write!(f, "if {condition} {if_body}")?; - - for (condition, body) in else_ifs { - write!(f, " else if {condition} {body}")?; - } - - Ok(()) - } - Statement::IfElseIfElse { - condition, - if_body, - else_ifs, - else_body, - } => { - write!(f, "if {condition} {if_body}")?; - - for (condition, body) in else_ifs { - write!(f, " else if {condition} {body}")?; - } - - write!(f, " else {else_body}") - } - Statement::List(nodes) => { - write!(f, "[")?; - - for (i, node) in nodes.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{node}")?; - } - - write!(f, "]") - } - Statement::Map(nodes) => { - write!(f, "{{")?; - - for (i, (identifier, node)) in nodes.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{identifier} = {node}")?; - } - - write!(f, "}}") - } - Statement::Nil(node) => write!(f, "{node};"), - Statement::UnaryOperation { operator, operand } => { - let operator = match operator.inner { - UnaryOperator::Negate => "-", - UnaryOperator::Not => "!", - }; - - write!(f, "{operator}{operand}") - } - Statement::StructDefinition(struct_definition) => { - write!(f, "{struct_definition}") - } - Statement::While { condition, body } => { - write!(f, "while {condition} {body}") - } - } - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum AssignmentOperator { - Assign, - AddAssign, - SubtractAssign, -} - -impl Display for AssignmentOperator { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let operator = match self { - AssignmentOperator::Assign => "=", - AssignmentOperator::AddAssign => "+=", - AssignmentOperator::SubtractAssign => "-=", - }; - - write!(f, "{operator}") - } -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum BinaryOperator { - // Accessors - FieldAccess, - ListIndex, - - // Math - Add, - Divide, - Modulo, - Multiply, - Subtract, - - // Comparison - Equal, - Greater, - GreaterOrEqual, - Less, - LessOrEqual, - - // Logic - And, - Or, -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum UnaryOperator { - Negate, - Not, -} - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum StructDefinition { - Unit { - name: Node, - }, - Tuple { - name: Node, - items: Vec>, - }, - Fields { - name: Node, - fields: Vec<(Node, Node)>, - }, -} - -impl Display for StructDefinition { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - StructDefinition::Unit { name } => write!(f, "struct {name}"), - StructDefinition::Tuple { - name, - items: fields, - } => { - write!(f, "struct {name} {{")?; - - for (i, field) in fields.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{field}")?; - } - - write!(f, "}}") - } - StructDefinition::Fields { name, fields } => { - write!(f, "struct {name} {{")?; - - for (i, (field_name, field_type)) in fields.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - - write!(f, "{field_name}: {field_type}")?; - } - - write!(f, "}}") - } - } - } -} diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs new file mode 100644 index 0000000..bd378db --- /dev/null +++ b/dust-lang/src/abstract_tree/expression.rs @@ -0,0 +1,526 @@ +use std::{ + cmp::Ordering, + fmt::{self, Display, Formatter}, +}; + +use serde::{Deserialize, Serialize}; + +use crate::{Identifier, Span, Value}; + +use super::{Node, Statement}; + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum Expression { + WithBlock(Node>), + WithoutBlock(Node>), +} + +impl Expression { + pub fn call_expression(call_expression: CallExpression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Call(call_expression)), + position, + )) + } + + pub fn field_access(field_access: FieldAccess, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::FieldAccess(field_access)), + position, + )) + } + + pub fn operator_expression(operator_expression: OperatorExpression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Operator(operator_expression)), + position, + )) + } + + pub fn r#loop(r#loop: Loop, position: Span) -> Self { + Expression::WithBlock(Node::new( + Box::new(ExpressionWithBlock::Loop(r#loop)), + position, + )) + } + + pub fn block(block: Block, position: Span) -> Self { + Expression::WithBlock(Node::new( + Box::new(ExpressionWithBlock::Block(block)), + position, + )) + } + + pub fn grouped(expression: Expression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Grouped(expression)), + position, + )) + } + + pub fn struct_expression(struct_expression: StructExpression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Struct(struct_expression)), + position, + )) + } + + pub fn identifier_expression(identifier: Identifier, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Identifier(identifier)), + position, + )) + } + + pub fn list(list_expression: ListExpression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::List(list_expression)), + position, + )) + } + + pub fn list_index(list_index: ListIndex, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::ListIndex(list_index)), + position, + )) + } + + pub fn r#if(r#if: If, position: Span) -> Self { + Expression::WithBlock(Node::new(Box::new(ExpressionWithBlock::If(r#if)), position)) + } + + pub fn literal(literal: LiteralExpression, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Literal(literal)), + position, + )) + } + + pub fn identifier(identifier: Identifier, position: Span) -> Self { + Expression::WithoutBlock(Node::new( + Box::new(ExpressionWithoutBlock::Identifier(identifier)), + position, + )) + } + + pub fn position(&self) -> Span { + match self { + Expression::WithBlock(expression_node) => expression_node.position, + Expression::WithoutBlock(expression_node) => expression_node.position, + } + } +} + +impl Display for Expression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Expression::WithBlock(expression) => write!(f, "{}", expression), + Expression::WithoutBlock(expression) => write!(f, "{}", expression), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum ExpressionWithBlock { + Block(Block), + Loop(Loop), + If(If), +} + +impl Display for ExpressionWithBlock { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ExpressionWithBlock::Block(block) => write!(f, "{}", block), + ExpressionWithBlock::Loop(r#loop) => write!(f, "{}", r#loop), + ExpressionWithBlock::If(r#if) => write!(f, "{}", r#if), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum ExpressionWithoutBlock { + Call(CallExpression), + List(ListExpression), + Literal(LiteralExpression), + Identifier(Identifier), + Operator(OperatorExpression), + Struct(StructExpression), + Grouped(Expression), + FieldAccess(FieldAccess), + ListIndex(ListIndex), +} + +impl Display for ExpressionWithoutBlock { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ExpressionWithoutBlock::Call(call_expression) => write!(f, "{}", call_expression), + ExpressionWithoutBlock::List(list) => write!(f, "{}", list), + ExpressionWithoutBlock::Literal(literal) => write!(f, "{}", literal), + ExpressionWithoutBlock::Identifier(identifier) => write!(f, "{}", identifier), + ExpressionWithoutBlock::Operator(expression) => write!(f, "{}", expression), + ExpressionWithoutBlock::Struct(struct_expression) => write!(f, "{}", struct_expression), + ExpressionWithoutBlock::Grouped(expression) => write!(f, "({})", expression), + ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access), + ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct ListIndex { + pub list: Expression, + pub index: Expression, +} + +impl Display for ListIndex { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}[{}]", self.list, self.index) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct CallExpression { + pub function: Expression, + pub arguments: Vec, +} + +impl Display for CallExpression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}(", self.function)?; + + for (index, argument) in self.arguments.iter().enumerate() { + if index > 0 { + write!(f, ", ")?; + } + + write!(f, "{}", argument)?; + } + + write!(f, ")") + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct FieldAccess { + pub container: Expression, + pub field: Node, +} + +impl Display for FieldAccess { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}.{}", self.container, self.field) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum ListExpression { + AutoFill { + repeat_operand: Expression, + length_operand: Expression, + }, + Ordered(Vec), +} + +impl Display for ListExpression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ListExpression::AutoFill { + repeat_operand, + length_operand, + } => { + write!(f, "[{};{}]", repeat_operand, length_operand) + } + ListExpression::Ordered(expressions) => { + write!(f, "[")?; + + for (index, expression) in expressions.iter().enumerate() { + if index > 0 { + write!(f, ", ")?; + } + + write!(f, "{}", expression)?; + } + + write!(f, "]") + } + } + } +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +pub enum LiteralExpression { + Boolean(bool), + Float(f64), + Integer(i64), + Range(i64, i64), + String(String), + Value(Value), +} + +impl Display for LiteralExpression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + LiteralExpression::Boolean(boolean) => write!(f, "{}", boolean), + LiteralExpression::Float(float) => write!(f, "{}", float), + LiteralExpression::Integer(integer) => write!(f, "{}", integer), + LiteralExpression::Range(start, end) => write!(f, "{}..{}", start, end), + LiteralExpression::String(string) => write!(f, "{}", string), + LiteralExpression::Value(value) => write!(f, "{}", value), + } + } +} + +impl Eq for LiteralExpression {} + +impl Ord for LiteralExpression { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (LiteralExpression::Boolean(left), LiteralExpression::Boolean(right)) => { + left.cmp(right) + } + (LiteralExpression::Float(left), LiteralExpression::Float(right)) => { + left.to_bits().cmp(&right.to_bits()) + } + (LiteralExpression::Integer(left), LiteralExpression::Integer(right)) => { + left.cmp(right) + } + (LiteralExpression::String(left), LiteralExpression::String(right)) => left.cmp(right), + (LiteralExpression::Value(left), LiteralExpression::Value(right)) => left.cmp(right), + _ => unreachable!(), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum OperatorExpression { + Assignment { + assignee: Expression, + value: Expression, + }, + CompoundAssignment { + assignee: Expression, + operator: Node, + value: Expression, + }, + ErrorPropagation(Expression), + Negation(Expression), + Not(Expression), + Math { + left: Expression, + operator: Node, + right: Expression, + }, + Logic { + left: Expression, + operator: LogicOperator, + right: Expression, + }, +} + +impl Display for OperatorExpression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + OperatorExpression::Assignment { assignee, value } => { + write!(f, "{} = {}", assignee, value) + } + OperatorExpression::CompoundAssignment { + assignee, + operator, + value, + } => write!(f, "{} {}= {}", assignee, operator, value), + OperatorExpression::ErrorPropagation(expression) => write!(f, "{}?", expression), + OperatorExpression::Negation(expression) => write!(f, "-{}", expression), + OperatorExpression::Not(expression) => write!(f, "!{}", expression), + OperatorExpression::Math { + left, + operator, + right, + } => { + write!(f, "{} {} {}", left, operator, right) + } + OperatorExpression::Logic { + left, + operator, + right, + } => { + write!(f, "{} {} {}", left, operator, right) + } + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum MathOperator { + Add, + Subtract, + Multiply, + Divide, + Modulo, +} + +impl Display for MathOperator { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let operator = match self { + MathOperator::Add => "+", + MathOperator::Subtract => "-", + MathOperator::Multiply => "*", + MathOperator::Divide => "/", + MathOperator::Modulo => "%", + }; + + write!(f, "{}", operator) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum LogicOperator { + And, + Or, +} + +impl Display for LogicOperator { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let operator = match self { + LogicOperator::And => "&&", + LogicOperator::Or => "||", + }; + + write!(f, "{}", operator) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct If { + pub condition: Expression, + pub if_block: Node, + pub else_block: Option>, +} + +impl Display for If { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "if {} {}", self.condition, self.if_block)?; + + if let Some(else_block) = &self.else_block { + write!(f, " else {}", else_block)?; + } + + Ok(()) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum Block { + Async(Vec), + Sync(Vec), +} + +impl Display for Block { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Block::Async(statements) => { + writeln!(f, "async {{ ")?; + + for (i, statement) in statements.iter().enumerate() { + if i > 0 { + writeln!(f, " ")?; + } + + writeln!(f, "{}", statement)?; + } + + write!(f, " }}") + } + Block::Sync(statements) => { + writeln!(f, "{{ ")?; + + for (i, statement) in statements.iter().enumerate() { + if i > 0 { + writeln!(f, " ")?; + } + + writeln!(f, "{}", statement)?; + } + + write!(f, " }}") + } + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum Loop { + Infinite(Block), + While { + condition: Expression, + block: Node, + }, + For { + identifier: Node, + iterator: Expression, + block: Block, + }, +} + +impl Display for Loop { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Loop::Infinite(block) => write!(f, "loop {}", block), + Loop::While { condition, block } => write!(f, "while {} {}", condition, block), + Loop::For { + identifier, + iterator, + block, + } => write!(f, "for {} in {} {}", identifier, iterator, block), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum StructExpression { + Unit { + name: Node, + }, + Tuple { + name: Node, + items: Vec, + }, + Fields { + name: Node, + fields: Vec<(Node, Expression)>, + }, +} + +impl Display for StructExpression { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + StructExpression::Unit { name } => write!(f, "{}", name), + StructExpression::Tuple { name, items } => { + write!(f, "{}(", name)?; + + for (index, item) in items.iter().enumerate() { + write!(f, "{}", item)?; + + if index < items.len() - 1 { + write!(f, ", ")?; + } + } + + write!(f, ")") + } + StructExpression::Fields { name, fields } => { + write!(f, "{} {{", name)?; + + for (index, (field, value)) in fields.iter().enumerate() { + write!(f, "{}: {}", field, value)?; + + if index < fields.len() - 1 { + write!(f, ", ")?; + } + } + + write!(f, "}}") + } + } + } +} diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs new file mode 100644 index 0000000..ab8311d --- /dev/null +++ b/dust-lang/src/abstract_tree/mod.rs @@ -0,0 +1,145 @@ +//! In-memory representation of a Dust program. +mod expression; + +pub use expression::*; + +use std::{ + collections::VecDeque, + fmt::{self, Display, Formatter}, +}; + +use serde::{Deserialize, Serialize}; + +use crate::{BuiltInFunction, Context, Identifier, Span, Type, Value}; + +/// In-memory representation of a Dust program. +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct AbstractSyntaxTree { + pub statements: VecDeque, +} + +impl AbstractSyntaxTree { + pub fn new() -> Self { + Self { + statements: VecDeque::new(), + } + } +} + +impl Default for AbstractSyntaxTree { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct Node { + pub inner: T, + pub position: Span, +} + +impl Node { + pub fn new(inner: T, position: Span) -> Self { + Self { inner, position } + } +} + +impl Display for Node { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.inner) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum Statement { + Expression(Expression), + ExpressionNullified(Node), + Let(Node), + StructDefinition(Node), +} + +impl Statement { + pub fn position(&self) -> Span { + match self { + Statement::Expression(expression) => expression.position(), + Statement::ExpressionNullified(expression_node) => expression_node.position, + Statement::Let(r#let) => r#let.position, + Statement::StructDefinition(definition) => definition.position, + } + } +} + +impl Display for Statement { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Statement::Expression(expression) => write!(f, "{}", expression), + Statement::ExpressionNullified(expression) => write!(f, "{}", expression), + Statement::Let(r#let) => write!(f, "{}", r#let), + Statement::StructDefinition(definition) => write!(f, "{}", definition), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct Let { + pub identifier: Node, + pub value: Node, +} + +impl Display for Let { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "let {} = {}", self.identifier, self.value) + } +} + +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum StructDefinition { + Unit { + name: Node, + }, + Tuple { + name: Node, + items: Vec>, + }, + Fields { + name: Node, + fields: Vec<(Node, Node)>, + }, +} + +impl Display for StructDefinition { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + StructDefinition::Unit { name } => write!(f, "struct {name}"), + StructDefinition::Tuple { + name, + items: fields, + } => { + write!(f, "struct {name} {{")?; + + for (i, field) in fields.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + + write!(f, "{field}")?; + } + + write!(f, "}}") + } + StructDefinition::Fields { name, fields } => { + write!(f, "struct {name} {{")?; + + for (i, (field_name, field_type)) in fields.iter().enumerate() { + if i > 0 { + write!(f, ", ")?; + } + + write!(f, "{field_name}: {field_type}")?; + } + + write!(f, "}}") + } + } + } +} diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 4a4b2d6..2b1da5d 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -66,512 +66,14 @@ impl<'a> Analyzer<'a> { } pub fn analyze(&mut self) -> Result<(), AnalyzerError> { - for node in &self.abstract_tree.nodes { + for node in &self.abstract_tree.statements { self.analyze_statement(node)?; } Ok(()) } - fn analyze_statement(&mut self, node: &Node) -> Result<(), AnalyzerError> { - match &node.inner { - Statement::Assignment { - identifier, value, .. - } => { - self.analyze_statement(value)?; - - let value_type = value.inner.expected_type(self.context); - - if let Some(r#type) = value_type { - self.context - .set_type(identifier.inner.clone(), r#type, identifier.position); - } else { - return Err(AnalyzerError::ExpectedValue { - actual: value.as_ref().clone(), - }); - } - } - Statement::AssignmentMut { identifier, value } => { - self.analyze_statement(value)?; - - let value_type = value.inner.expected_type(self.context); - - if let Some(r#type) = value_type { - self.context - .set_type(identifier.inner.clone(), r#type, identifier.position); - } else { - return Err(AnalyzerError::ExpectedValue { - actual: value.as_ref().clone(), - }); - } - } - Statement::AsyncBlock(statements) => { - for statement in statements { - self.analyze_statement(statement)?; - } - } - Statement::BinaryOperation { - left, - operator, - right, - } => { - if let BinaryOperator::FieldAccess = operator.inner { - self.analyze_statement(left)?; - - if let Statement::Identifier(_) = right.inner { - // Do not expect a value for property accessors - } else { - self.analyze_statement(right)?; - } - - let left_type = left.inner.expected_type(self.context); - let right_type = right.inner.expected_type(self.context); - - if let Some(Type::Map { .. }) = left_type { - if let Some(Type::String) = right_type { - // Allow indexing maps with strings - } else if let Statement::Identifier(_) = right.inner { - // Allow indexing maps with identifiers - } else { - return Err(AnalyzerError::ExpectedIdentifierOrString { - actual: right.as_ref().clone(), - }); - } - } else { - return Err(AnalyzerError::ExpectedMap { - actual: left.as_ref().clone(), - }); - } - - // If the accessor is an identifier, check if it is a valid field - if let Statement::Identifier(identifier) = &right.inner { - if let Some(Type::Map(fields)) = &left_type { - if !fields.contains_key(identifier) { - return Err(AnalyzerError::UndefinedField { - identifier: right.as_ref().clone(), - statement: left.as_ref().clone(), - }); - } - } - } - // If the accessor is a constant, check if it is a valid field - if let Statement::Constant(value) = &right.inner { - if let Some(field_name) = value.as_string() { - if let Some(Type::Map(fields)) = left_type { - if !fields.contains_key(&Identifier::new(field_name)) { - return Err(AnalyzerError::UndefinedField { - identifier: right.as_ref().clone(), - statement: left.as_ref().clone(), - }); - } - } - } - } - - return Ok(()); - } - - if let BinaryOperator::ListIndex = operator.inner { - self.analyze_statement(left)?; - self.analyze_statement(right)?; - - if let Some(Type::List { length, .. }) = left.inner.expected_type(self.context) - { - let index_type = right.inner.expected_type(self.context); - - if let Some(Type::Integer | Type::Range) = index_type { - // List and index are valid - } else { - return Err(AnalyzerError::ExpectedIntegerOrRange { - actual: right.as_ref().clone(), - }); - } - - // If the index is a constant, check if it is out of bounds - if let Statement::Constant(value) = &right.inner { - if let Some(index_value) = value.as_integer() { - let index_value = index_value as usize; - - if index_value >= length { - return Err(AnalyzerError::IndexOutOfBounds { - list: left.as_ref().clone(), - index: right.as_ref().clone(), - index_value, - length, - }); - } - } - } - } else { - return Err(AnalyzerError::ExpectedList { - actual: left.as_ref().clone(), - }); - } - - return Ok(()); - } - - self.analyze_statement(left)?; - self.analyze_statement(right)?; - - let left_type = left.inner.expected_type(self.context); - let right_type = right.inner.expected_type(self.context); - - if let BinaryOperator::Add - | BinaryOperator::Subtract - | BinaryOperator::Multiply - | BinaryOperator::Divide - | BinaryOperator::Greater - | BinaryOperator::GreaterOrEqual - | BinaryOperator::Less - | BinaryOperator::LessOrEqual = operator.inner - { - if let Some(expected_type) = left_type { - if let Some(actual_type) = right_type { - expected_type.check(&actual_type).map_err(|conflict| { - AnalyzerError::TypeConflict { - actual_statement: right.as_ref().clone(), - actual_type: conflict.actual, - expected: conflict.expected, - } - })?; - } else { - return Err(AnalyzerError::ExpectedValue { - actual: right.as_ref().clone(), - }); - } - } else { - return Err(AnalyzerError::ExpectedValue { - actual: left.as_ref().clone(), - }); - } - } - } - Statement::Block(statements) => { - for statement in statements { - self.analyze_statement(statement)?; - } - } - Statement::BuiltInFunctionCall { - function, - value_arguments, - .. - } => { - let value_parameters = function.value_parameters(); - - if let Some(arguments) = value_arguments { - for argument in arguments { - self.analyze_statement(argument)?; - } - - if arguments.len() != value_parameters.len() { - return Err(AnalyzerError::ExpectedValueArgumentCount { - expected: value_parameters.len(), - actual: arguments.len(), - position: node.position, - }); - } - - for ((_identifier, parameter_type), argument) in - value_parameters.iter().zip(arguments) - { - let argument_type_option = argument.inner.expected_type(self.context); - - if let Some(argument_type) = argument_type_option { - parameter_type.check(&argument_type).map_err(|conflict| { - AnalyzerError::TypeConflict { - actual_statement: argument.clone(), - actual_type: conflict.actual, - expected: parameter_type.clone(), - } - })?; - } else { - return Err(AnalyzerError::ExpectedValue { - actual: argument.clone(), - }); - } - } - - if arguments.is_empty() && !value_parameters.is_empty() { - return Err(AnalyzerError::ExpectedValueArgumentCount { - expected: value_parameters.len(), - actual: 0, - position: node.position, - }); - } - } else if !value_parameters.is_empty() { - return Err(AnalyzerError::ExpectedValueArgumentCount { - expected: value_parameters.len(), - actual: 0, - position: node.position, - }); - } - } - Statement::Constant(_) => {} - Statement::ConstantMut(_) => {} - Statement::FieldsStructInstantiation { - name, - fields: field_arguments, - } => { - let expected_type = self.context.get_type(&name.inner); - - if let Some(Type::Struct(StructType::Fields { fields, .. })) = expected_type { - for ((_, expected_type), (_, argument)) in - fields.iter().zip(field_arguments.iter()) - { - let actual_type = argument.inner.expected_type(self.context); - - if let Some(actual_type) = actual_type { - expected_type.check(&actual_type).map_err(|conflict| { - AnalyzerError::TypeConflict { - actual_statement: argument.clone(), - actual_type: conflict.actual, - expected: conflict.expected, - } - })?; - } else { - return Err(AnalyzerError::ExpectedValue { - actual: argument.clone(), - }); - } - } - } - } - Statement::Invokation { - invokee, - value_arguments, - .. - } => { - self.analyze_statement(invokee)?; - - let invokee_type = invokee.inner.expected_type(self.context); - - if let Some(arguments) = value_arguments { - for argument in arguments { - self.analyze_statement(argument)?; - } - - if let Some(Type::Struct(struct_type)) = invokee_type { - match struct_type { - StructType::Unit { .. } => todo!(), - StructType::Tuple { fields, .. } => { - for (expected_type, argument) in fields.iter().zip(arguments.iter()) - { - let actual_type = argument.inner.expected_type(self.context); - - if let Some(actual_type) = actual_type { - expected_type.check(&actual_type).map_err(|conflict| { - AnalyzerError::TypeConflict { - actual_statement: argument.clone(), - actual_type: conflict.actual, - expected: expected_type.clone(), - } - })?; - } else { - return Err(AnalyzerError::ExpectedValue { - actual: argument.clone(), - }); - } - } - } - StructType::Fields { .. } => todo!(), - } - } - } - } - Statement::Identifier(identifier) => { - let exists = self.context.update_last_position(identifier, node.position); - - if !exists { - return Err(AnalyzerError::UndefinedVariable { - identifier: node.clone(), - }); - } - } - Statement::If { condition, body } => { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.as_ref().clone(), - }); - } - - self.analyze_statement(body)?; - } - Statement::IfElse { - condition, - if_body, - else_body, - } => { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.as_ref().clone(), - }); - } - - self.analyze_statement(if_body)?; - self.analyze_statement(else_body)?; - } - Statement::IfElseIf { - condition, - if_body, - else_ifs, - } => { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.as_ref().clone(), - }); - } - - self.analyze_statement(if_body)?; - - for (condition, body) in else_ifs { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.clone(), - }); - } - - self.analyze_statement(body)?; - } - } - Statement::IfElseIfElse { - condition, - if_body, - else_ifs, - else_body, - } => { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.as_ref().clone(), - }); - } - - self.analyze_statement(if_body)?; - - for (condition, body) in else_ifs { - self.analyze_statement(condition)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - // Condition is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.clone(), - }); - } - - self.analyze_statement(body)?; - } - - self.analyze_statement(else_body)?; - } - Statement::List(statements) => { - for statement in statements { - self.analyze_statement(statement)?; - } - } - Statement::Map(properties) => { - for (_key, value_node) in properties { - self.analyze_statement(value_node)?; - } - } - Statement::Nil(node) => { - self.analyze_statement(node)?; - } - Statement::StructDefinition(struct_definition) => { - let (name, r#type) = match struct_definition { - StructDefinition::Unit { name } => ( - name.inner.clone(), - Type::Struct(StructType::Unit { - name: name.inner.clone(), - }), - ), - StructDefinition::Tuple { - name, - items: fields, - } => ( - name.inner.clone(), - Type::Struct(StructType::Tuple { - name: name.inner.clone(), - fields: fields - .iter() - .map(|type_node| type_node.inner.clone()) - .collect(), - }), - ), - StructDefinition::Fields { name, fields } => ( - name.inner.clone(), - Type::Struct(StructType::Fields { - name: name.inner.clone(), - fields: fields - .iter() - .map(|(identifier, r#type)| { - (identifier.inner.clone(), r#type.inner.clone()) - }) - .collect(), - }), - ), - }; - - self.context.set_type(name, r#type, node.position); - } - Statement::UnaryOperation { operator, operand } => { - self.analyze_statement(operand)?; - - if let UnaryOperator::Negate = operator.inner { - if let Some(Type::Integer | Type::Float | Type::Number) = - operand.inner.expected_type(self.context) - { - // Operand is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: operand.as_ref().clone(), - }); - } - } - - if let UnaryOperator::Not = operator.inner { - if let Some(Type::Boolean) = operand.inner.expected_type(self.context) { - // Operand is valid - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: operand.as_ref().clone(), - }); - } - } - } - Statement::While { condition, body } => { - self.analyze_statement(condition)?; - self.analyze_statement(body)?; - - if let Some(Type::Boolean) = condition.inner.expected_type(self.context) { - } else { - return Err(AnalyzerError::ExpectedBoolean { - actual: condition.as_ref().clone(), - }); - } - } - } - + fn analyze_statement(&mut self, _: &Node) -> Result<(), AnalyzerError> { Ok(()) } } @@ -729,10 +231,70 @@ impl Display for AnalyzerError { #[cfg(test)] mod tests { - use crate::{Identifier, Value}; + use crate::{AssignmentOperator, Identifier, Value}; use super::*; + #[test] + fn add_assign_wrong_type() { + let source = " + a = 1 + a += 1.0 + "; + + assert_eq!( + analyze(source), + Err(DustError::AnalyzerError { + analyzer_error: AnalyzerError::TypeConflict { + actual_statement: Node::new( + Statement::Assignment { + identifier: Node::new(Identifier::new("a"), (31, 32)), + operator: Node::new(AssignmentOperator::AddAssign, (33, 35)), + value: Box::new(Node::new( + Statement::Constant(Value::float(1.0)), + (38, 41) + )) + }, + (31, 32) + ), + actual_type: Type::Integer, + expected: Type::Float + }, + source + }) + ); + } + + #[test] + fn subtract_assign_wrong_type() { + let source = " + a = 1 + a -= 1.0 + "; + + assert_eq!( + analyze(source), + Err(DustError::AnalyzerError { + analyzer_error: AnalyzerError::TypeConflict { + actual_statement: Node::new( + Statement::Assignment { + identifier: Node::new(Identifier::new("a"), (31, 32)), + operator: Node::new(AssignmentOperator::SubtractAssign, (33, 37)), + value: Box::new(Node::new( + Statement::Constant(Value::float(1.0)), + (40, 43) + )) + }, + (31, 32) + ), + actual_type: Type::Integer, + expected: Type::Float + }, + source + }) + ); + } + #[test] fn tuple_struct_with_wrong_field_types() { let source = " diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index cba0319..f7971a9 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -7,14 +7,14 @@ use std::{ collections::VecDeque, error::Error, fmt::{self, Display, Formatter}, + marker::PhantomData, num::{ParseFloatError, ParseIntError}, str::ParseBoolError, }; use crate::{ - AbstractSyntaxTree, AssignmentOperator, BinaryOperator, BuiltInFunction, DustError, Identifier, - LexError, Lexer, Node, Span, Statement, StructDefinition, Token, TokenKind, TokenOwned, Type, - UnaryOperator, Value, + abstract_tree::*, AbstractSyntaxTree, BuiltInFunction, DustError, Identifier, LexError, Lexer, + Node, Span, Statement, StructDefinition, Token, TokenKind, TokenOwned, Type, Value, }; /// Parses the input into an abstract syntax tree. @@ -51,7 +51,7 @@ use crate::{ /// ``` pub fn parse(source: &str) -> Result { let lexer = Lexer::new(); - let mut parser = Parser::new(source, lexer); + let mut parser = Parser::::new(source, lexer); let mut nodes = VecDeque::new(); loop { @@ -64,12 +64,12 @@ pub fn parse(source: &str) -> Result { nodes.push_back(node); - if let Token::Eof = parser.current.0 { + if let Token::Eof = parser.current_token { break; } } - Ok(AbstractSyntaxTree { nodes }) + Ok(AbstractSyntaxTree { statements: nodes }) } pub fn parse_into<'src>( @@ -77,7 +77,7 @@ pub fn parse_into<'src>( tree: &mut AbstractSyntaxTree, ) -> Result<(), DustError<'src>> { let lexer = Lexer::new(); - let mut parser = Parser::new(source, lexer); + let mut parser = Parser::::new(source, lexer); loop { let node = parser @@ -87,9 +87,9 @@ pub fn parse_into<'src>( source, })?; - tree.nodes.push_back(node); + tree.statements.push_back(node); - if let Token::Eof = parser.current.0 { + if let Token::Eof = parser.current_token { break; } } @@ -121,55 +121,57 @@ pub fn parse_into<'src>( /// let tree = AbstractSyntaxTree { nodes }; /// /// ``` -pub struct Parser<'src> { +pub struct Parser<'src, T> { source: &'src str, lexer: Lexer, - current: (Token<'src>, Span), - mode: ParserMode, + current_token: Token<'src>, + current_position: Span, + product: PhantomData, } -impl<'src> Parser<'src> { +impl<'src, T> Parser<'src, T> { pub fn new(source: &'src str, lexer: Lexer) -> Self { let mut lexer = lexer; - let current = lexer.next_token(source).unwrap_or((Token::Eof, (0, 0))); + let (current_token, current_position) = + lexer.next_token(source).unwrap_or((Token::Eof, (0, 0))); Parser { source, lexer, - current, - mode: ParserMode::None, + current_token, + current_position, + product: PhantomData, } } - pub fn current(&self) -> &(Token, Span) { - &self.current - } - - pub fn parse(&mut self) -> Result, ParseError> { - self.parse_statement(0) + pub fn parse(&mut self) -> Result { + self.parse_next(0) } fn next_token(&mut self) -> Result<(), ParseError> { - self.current = self.lexer.next_token(self.source)?; + let (token, position) = self.lexer.next_token(self.source)?; + + self.current_token = token; + self.current_position = position; Ok(()) } - fn parse_statement(&mut self, mut precedence: u8) -> Result, ParseError> { + fn parse_next(&mut self, mut precedence: u8) -> Result { // Parse a statement starting from the current node. - let mut left = if self.current.0.is_prefix() { + let mut left = if self.current_token.is_prefix() { self.parse_prefix()? } else { self.parse_primary()? }; // While the current token has a higher precedence than the given precedence - while precedence < self.current.0.precedence() { + while precedence < self.current_token.precedence() { // Give precedence to postfix operations - left = if self.current.0.is_postfix() { + left = if self.current_token.is_postfix() { let statement = self.parse_postfix(left)?; - precedence = self.current.0.precedence(); + precedence = self.current_token.precedence(); // Replace the left-hand side with the postfix operation statement @@ -179,592 +181,326 @@ impl<'src> Parser<'src> { }; } - log::trace!( - "{}'s precedence is lower than or equal to {}", - self.current.0, - precedence - ); - Ok(left) } - fn parse_statement_in_mode( - &mut self, - mode: ParserMode, - precedence: u8, - ) -> Result, ParseError> { - let old_mode = self.mode; - self.mode = mode; + fn parse_prefix(&mut self) -> Result { + log::trace!("Parsing {} as prefix operator", self.current_token); - let result = self.parse_statement(precedence); + let operator_start = self.current_position.0; - self.mode = old_mode; - - result - } - - fn parse_prefix(&mut self) -> Result, ParseError> { - log::trace!("Parsing {} as prefix operator", self.current.0); - - match self.current { - (Token::Bang, position) => { + match self.current_token { + Token::Bang => { self.next_token()?; - let operand = Box::new(self.parse_statement(0)?); - let operand_end = operand.position.1; + let operand = self.parse_expression(0)?; + let position = (operator_start, self.current_position.1); - Ok(Node::new( - Statement::UnaryOperation { - operator: Node::new(UnaryOperator::Not, position), - operand, - }, - (position.0, operand_end), - )) + Ok(Statement::Expression(Expression::operator_expression( + OperatorExpression::Not(operand), + position, + ))) } - (Token::Minus, position) => { + Token::Minus => { self.next_token()?; - let operand = Box::new(self.parse_statement(0)?); - let operand_end = operand.position.1; + let operand = self.parse_expression(0)?; + let position = (operator_start, self.current_position.1); - Ok(Node::new( - Statement::UnaryOperation { - operator: Node::new(UnaryOperator::Negate, position), - operand, - }, - (position.0, operand_end), - )) + Ok(Statement::Expression(Expression::operator_expression( + OperatorExpression::Negation(operand), + position, + ))) } _ => Err(ParseError::UnexpectedToken { - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }), } } - fn parse_primary(&mut self) -> Result, ParseError> { - log::trace!("Parsing {} as primary", self.current.0); + fn parse_primary(&mut self) -> Result { + log::trace!("Parsing {} as primary", self.current_token); - match self.current { - (Token::Async, position) => { - self.next_token()?; + let start_position = self.current_position; - if let Token::LeftCurlyBrace = self.current.0 { - self.next_token()?; - } else { - return Err(ParseError::UnexpectedToken { - actual: self.current.0.to_owned(), - position: self.current.1, - }); - } + match self.current_token { + Token::Async => { + let block = self.parse_block()?; + let position = (start_position.0, self.current_position.1); - let mut statements = Vec::new(); - - loop { - if let Token::RightCurlyBrace = self.current.0 { - let right_end = self.current.1 .1; - - self.next_token()?; - - return Ok(Node::new( - Statement::AsyncBlock(statements), - (position.0, right_end), - )); - } - - let statement = self.parse_statement(0)?; - - statements.push(statement); - } + return Ok(Statement::block(block.inner, position)); } - (Token::Boolean(text), position) => { + Token::Boolean(text) => { self.next_token()?; - let boolean = text - .parse() - .map_err(|error| ParseError::BooleanError { error, position })?; + let boolean = text.parse().map_err(|error| ParseError::Boolean { + error, + position: start_position, + })?; + let right_end = self.current_position.1; + let statement = Statement::literal( + LiteralExpression::Boolean(boolean), + (start_position.0, right_end), + ); - if let ParserMode::Mutable = self.mode { - Ok(Node::new( - Statement::ConstantMut(Value::boolean_mut(boolean)), - position, - )) - } else { - Ok(Node::new( - Statement::Constant(Value::boolean(boolean)), - position, - )) - } + return Ok(statement); } - (Token::Float(text), position) => { + Token::Float(text) => { self.next_token()?; - let float = text - .parse() - .map_err(|error| ParseError::FloatError { error, position })?; + let float = text.parse().map_err(|error| ParseError::Float { + error, + position: start_position, + })?; + let position = (start_position.0, self.current_position.1); - Ok(Node::new( - Statement::Constant(Value::float(float)), + return Ok(Statement::literal( + LiteralExpression::Float(float), position, - )) + )); } - (Token::Identifier(text), position) => { + Token::Identifier(text) => { + let identifier = Identifier::new(text); + let identifier_position = self.current_position; + self.next_token()?; - if let ParserMode::Condition = self.mode { - return Ok(Node::new( - Statement::Identifier(Identifier::new(text)), - position, - )); - } - - if let Token::LeftCurlyBrace = self.current.0 { + if let Token::LeftCurlyBrace = self.current_token { self.next_token()?; let mut fields = Vec::new(); loop { - if let Token::RightCurlyBrace = self.current.0 { - let right_end = self.current.1 .1; + if let Token::RightCurlyBrace = self.current_token { + let position = (start_position.0, self.current_position.1); self.next_token()?; - return Ok(Node::new( - Statement::FieldsStructInstantiation { - name: Node::new(Identifier::new(text), position), + return Ok(Statement::struct_expression( + StructExpression::Fields { + name: Node::new(identifier, identifier_position), fields, }, - (position.0, right_end), + position, )); } let field_name = self.parse_identifier()?; - if let Token::Equal = self.current.0 { + if let Token::Colon = self.current_token { self.next_token()?; } else { return Err(ParseError::ExpectedToken { expected: TokenKind::Equal, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } - let field_value = self.parse_statement(0)?; + let field_value = self.parse_expression(0)?; fields.push((field_name, field_value)); - if let Token::Comma = self.current.0 { + if let Token::Comma = self.current_token { self.next_token()?; } } } - Ok(Node::new( - Statement::Identifier(Identifier::new(text)), - position, + Ok(Statement::identifier_expression( + identifier, + identifier_position, )) } - (Token::Integer(text), position) => { + Token::Integer(text) => { self.next_token()?; - let integer = text - .parse::() - .map_err(|error| ParseError::IntegerError { error, position })?; + let integer = text.parse::().map_err(|error| ParseError::Integer { + error, + position: start_position, + })?; - if let Token::DoubleDot = self.current.0 { + if let Token::DoubleDot = self.current_token { self.next_token()?; - if let Token::Integer(range_end) = self.current.0 { + if let Token::Integer(range_end) = self.current_token { + let end_position = self.current_position; + self.next_token()?; - let range_end = range_end - .parse::() - .map_err(|error| ParseError::IntegerError { error, position })?; + let range_end = + range_end + .parse::() + .map_err(|error| ParseError::Integer { + error, + position: end_position, + })?; - Ok(Node::new( - Statement::Constant(Value::range(integer..range_end)), - (position.0, self.current.1 .1), + Ok(Statement::literal( + LiteralExpression::Range(integer, range_end), + (start_position.0, end_position.1), )) } else { Err(ParseError::ExpectedToken { expected: TokenKind::Integer, - actual: self.current.0.to_owned(), - position: (position.0, self.current.1 .1), + actual: self.current_token.to_owned(), + position: (start_position.0, self.current_position.1), }) } } else { - Ok(Node::new( - Statement::Constant(Value::integer(integer)), - position, + Ok(Statement::literal( + LiteralExpression::Integer(integer), + start_position, )) } } - (Token::If, position) => { + Token::If => { self.next_token()?; - let condition = Box::new(self.parse_statement_in_mode(ParserMode::Condition, 0)?); - let if_body = Box::new(self.parse_block()?); - - if let Token::Else = self.current.0 { + let condition = self.parse_expression(0)?; + let if_block = self.parse_block()?; + let else_block = if let Token::Else = self.current_token { self.next_token()?; - if let Token::If = self.current.0 { - self.next_token()?; - - let first_else_if = ( - self.parse_statement_in_mode(ParserMode::Condition, 0)?, - self.parse_statement(0)?, - ); - let mut else_ifs = vec![first_else_if]; - - loop { - if let Token::Else = self.current.0 { - self.next_token()?; - } else { - return Ok(Node::new( - Statement::IfElseIf { - condition, - if_body, - else_ifs, - }, - position, - )); - } - - if let Token::If = self.current.0 { - self.next_token()?; - - let else_if = ( - self.parse_statement_in_mode(ParserMode::Condition, 0)?, - self.parse_statement(0)?, - ); - - else_ifs.push(else_if); - } else { - let else_body = Box::new(self.parse_block()?); - let else_end = else_body.position.1; - - return Ok(Node::new( - Statement::IfElseIfElse { - condition, - if_body, - else_ifs, - else_body, - }, - (position.0, else_end), - )); - } - } - } else { - let else_body = Box::new(self.parse_block()?); - let else_end = else_body.position.1; - - Ok(Node::new( - Statement::IfElse { - condition, - if_body, - else_body, - }, - (position.0, else_end), - )) - } + Some(self.parse_block()?) } else { - let if_end = if_body.position.1; - - self.mode = ParserMode::None; - - Ok(Node::new( - Statement::If { - condition, - body: if_body, - }, - (position.0, if_end), - )) - } - } - (Token::String(string), position) => { - self.next_token()?; - - if let ParserMode::Mutable = self.mode { - Ok(Node::new( - Statement::ConstantMut(Value::string_mut(string)), - position, - )) - } else { - Ok(Node::new( - Statement::Constant(Value::string(string)), - position, - )) - } - } - (Token::LeftCurlyBrace, left_position) => { - self.next_token()?; - - // If the next token is a right curly brace, this is an empty map - if let (Token::RightCurlyBrace, right_position) = self.current { - self.next_token()?; - - return Ok(Node::new( - Statement::Map(Vec::new()), - (left_position.0, right_position.1), - )); - } - - let first_node = self.parse_statement(0)?; - - // Determine whether the new statement is a block or a map - // - // If the first node is an assignment, this might be a map - let mut statement = if let Statement::Assignment { - identifier: left, - operator: - Node { - inner: AssignmentOperator::Assign, - position: operator_position, - }, - value: right, - } = first_node.inner - { - // If the current token is a comma or closing brace - if self.current.0 == Token::Comma || self.current.0 == Token::RightCurlyBrace { - // Allow commas after properties - if let Token::Comma = self.current.0 { - self.next_token()?; - } - - // The new statement is a map - Statement::Map(vec![(left, *right)]) - } else { - // Otherwise, the new statement is a block - Statement::Block(vec![Node::new( - Statement::Assignment { - identifier: left, - operator: Node::new(AssignmentOperator::Assign, operator_position), - value: right, - }, - first_node.position, - )]) - } - // If the next node is not an assignment, the new statement is a block - } else { - Statement::Block(vec![first_node]) + None }; + let position = (start_position.0, self.current_position.1); - loop { - // If a closing brace is found, return the new statement - if let (Token::RightCurlyBrace, right_position) = self.current { - self.next_token()?; - - return Ok(Node::new(statement, (left_position.0, right_position.1))); - } - - let next_node = self.parse_statement(0)?; - - // If the new statement is already a block, add the next node to it - if let Some(block_statements) = statement.block_statements_mut() { - block_statements.push(next_node); - - continue; - } - - // If the new statement is already a map - if let Some(map_properties) = statement.map_properties_mut() { - // Expect the next node to be an assignment - if let Statement::Assignment { - identifier, - operator: - Node { - inner: AssignmentOperator::Assign, - .. - }, - value, - } = next_node.inner - { - // Add the new property to the map - map_properties.push((identifier, *value)); - - // Allow commas after properties - if let Token::Comma = self.current.0 { - self.next_token()?; - } - - continue; - } else { - return Err(ParseError::ExpectedAssignment { actual: next_node }); - } - } - } + Ok(Statement::r#if( + If { + condition, + if_block, + else_block, + }, + position, + )) } - (Token::LeftParenthesis, left_position) => { + Token::String(text) => { self.next_token()?; - let node = self.parse_statement(0)?; + Ok(Statement::literal( + LiteralExpression::String(text.to_string()), + start_position, + )) + } + Token::LeftCurlyBrace => { + let block_node = self.parse_block()?; + + Ok(Statement::block(block_node.inner, block_node.position)) + } + Token::LeftParenthesis => { + self.next_token()?; + + let node = self.parse_expression(0)?; + + if let Token::RightParenthesis = self.current_token { + let position = (start_position.0, self.current_position.1); - if let (Token::RightParenthesis, right_position) = self.current { self.next_token()?; - Ok(Node::new(node.inner, (left_position.0, right_position.1))) + Ok(Statement::grouped(node, position)) } else { Err(ParseError::ExpectedToken { expected: TokenKind::RightParenthesis, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }) } } - (Token::LeftSquareBrace, left_position) => { + Token::LeftSquareBrace => { self.next_token()?; - let mut nodes = Vec::new(); + let first_expression = self.parse_expression(0)?; - loop { - if let (Token::RightSquareBrace, right_position) = self.current { - self.next_token()?; - - return Ok(Node::new( - Statement::List(nodes), - (left_position.0, right_position.1), - )); - } - - if let (Token::Comma, _) = self.current { - self.next_token()?; - - continue; - } - - let statement = self.parse_statement(0)?; - - nodes.push(statement); - } - } - ( - Token::IsEven - | Token::IsOdd - | Token::Length - | Token::ReadLine - | Token::ToString - | Token::WriteLine, - left_position, - ) => { - let function = match self.current.0 { - Token::IsEven => BuiltInFunction::IsEven, - Token::IsOdd => BuiltInFunction::IsOdd, - Token::Length => BuiltInFunction::Length, - Token::ReadLine => BuiltInFunction::ReadLine, - Token::ToString => BuiltInFunction::ToString, - Token::WriteLine => BuiltInFunction::WriteLine, - _ => unreachable!(), - }; - - self.next_token()?; - - if let (Token::LeftParenthesis, _) = self.current { + if let Token::Semicolon = self.current_token { self.next_token()?; - } else { - return Err(ParseError::ExpectedToken { - expected: TokenKind::LeftParenthesis, - actual: self.current.0.to_owned(), - position: self.current.1, - }); - } - let mut value_arguments: Option>> = None; + let repeat_operand = self.parse_expression(0)?; + + if let Token::RightSquareBrace = self.current_token { + let position = (start_position.0, self.current_position.1); - loop { - if let (Token::RightParenthesis, _) = self.current { self.next_token()?; - break; - } - if let (Token::Comma, _) = self.current { - self.next_token()?; - continue; - } - - if let Ok(node) = self.parse_statement(0) { - if let Some(ref mut arguments) = value_arguments { - arguments.push(node); - } else { - value_arguments = Some(vec![node]); - } + return Ok(Statement::list( + ListExpression::AutoFill { + length_operand: first_expression, + repeat_operand, + }, + position, + )); } else { return Err(ParseError::ExpectedToken { - expected: TokenKind::RightParenthesis, - actual: self.current.0.to_owned(), - position: self.current.1, + expected: TokenKind::RightSquareBrace, + actual: self.current_token.to_owned(), + position: self.current_position, }); } } - Ok(Node::new( - Statement::BuiltInFunctionCall { - function, - type_arguments: None, - value_arguments, - }, - left_position, - )) - } - (Token::Mut, left_position) => { - self.next_token()?; + let mut expressions = vec![first_expression]; - let identifier = self.parse_identifier()?; + loop { + if let Token::RightSquareBrace = self.current_token { + let position = (start_position.0, self.current_position.1); - if let (Token::Equal, _) = self.current { - self.next_token()?; - } else { - return Err(ParseError::ExpectedToken { - expected: TokenKind::Equal, - actual: self.current.0.to_owned(), - position: self.current.1, - }); + self.next_token()?; + + return Ok(Statement::list( + ListExpression::Ordered(expressions), + position, + )); + } + + if let Token::Comma = self.current_token { + self.next_token()?; + + continue; + } + + let expression = self.parse_expression(0)?; + + expressions.push(expression); } - - let value = Box::new(self.parse_statement_in_mode(ParserMode::Mutable, 0)?); - let value_end = value.position.1; - - Ok(Node::new( - Statement::AssignmentMut { identifier, value }, - (left_position.0, value_end), - )) } - (Token::Struct, left_position) => { + Token::Struct => { self.next_token()?; - let (name, name_end) = if let Token::Identifier(_) = self.current.0 { - let position = self.current.1 .1; + let (name, name_end) = if let Token::Identifier(_) = self.current_token { + let end = self.current_position.1; - (self.parse_identifier()?, position) + (self.parse_identifier()?, end) } else { return Err(ParseError::ExpectedToken { expected: TokenKind::Identifier, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); }; - if let Token::LeftParenthesis = self.current.0 { + if let Token::LeftParenthesis = self.current_token { self.next_token()?; let mut types = Vec::new(); loop { - if let (Token::RightParenthesis, right_position) = self.current { + if let Token::RightParenthesis = self.current_token { + let position = (start_position.0, self.current_position.1); + self.next_token()?; - return Ok(Node::new( - Statement::StructDefinition(StructDefinition::Tuple { - name, - items: types, - }), - (left_position.0, right_position.1), + return Ok(Statement::struct_definition( + StructDefinition::Tuple { name, items: types }, + position, )); } - if let (Token::Comma, _) = self.current { + if let Token::Comma = self.current_token { self.next_token()?; + continue; } @@ -774,38 +510,38 @@ impl<'src> Parser<'src> { } } - if let Token::LeftCurlyBrace = self.current.0 { + if let Token::LeftCurlyBrace = self.current_token { self.next_token()?; let mut fields = Vec::new(); loop { - if let (Token::RightCurlyBrace, right_position) = self.current { + if let Token::RightCurlyBrace = self.current_token { + let position = (start_position.0, self.current_position.1); + self.next_token()?; - return Ok(Node::new( - Statement::StructDefinition(StructDefinition::Fields { - name, - fields, - }), - (left_position.0, right_position.1), + return Ok(Statement::struct_definition( + StructDefinition::Fields { name, fields }, + position, )); } - if let (Token::Comma, _) = self.current { + if let Token::Comma = self.current_token { self.next_token()?; + continue; } let field_name = self.parse_identifier()?; - if let (Token::Colon, _) = self.current { + if let Token::Colon = self.current_token { self.next_token()?; } else { return Err(ParseError::ExpectedToken { expected: TokenKind::Colon, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } @@ -815,198 +551,149 @@ impl<'src> Parser<'src> { } } - Ok(Node::new( - Statement::StructDefinition(StructDefinition::Unit { name }), - (left_position.0, name_end), + Ok(Statement::struct_definition( + StructDefinition::Unit { name }, + (start_position.0, name_end), )) } - (Token::While, left_position) => { + Token::While => { self.next_token()?; - let condition = self.parse_statement_in_mode(ParserMode::Condition, 0)?; + let condition = self.parse_expression(0)?; + let block = self.parse_block()?; + let position = (start_position.0, self.current_position.1); - let body = self.parse_block()?; - let body_end = body.position.1; - - Ok(Node::new( - Statement::While { - condition: Box::new(condition), - body: Box::new(body), - }, - (left_position.0, body_end), + Ok(Statement::r#loop( + Loop::While { condition, block }, + position, )) } _ => Err(ParseError::UnexpectedToken { - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }), } } - fn parse_infix(&mut self, left: Node) -> Result, ParseError> { - log::trace!("Parsing {} as infix operator", self.current.0); + fn parse_infix(&mut self, left: Statement) -> Result { + log::trace!("Parsing {} as infix operator", self.current_token); - let operator_precedence = self.current.0.precedence() - - if self.current.0.is_right_associative() { + let left = if let Statement::Expression(expression) = left { + expression + } else { + return Err(ParseError::ExpectedExpression { actual: left }); + }; + let operator_precedence = self.current_token.precedence() + - if self.current_token.is_right_associative() { 1 } else { 0 }; - let left_start = left.position.0; + let left_start = left.position().0; - if let Token::Equal | Token::PlusEqual | Token::MinusEqual = &self.current.0 { - let operator = match self.current.0 { - Token::Equal => AssignmentOperator::Assign, - Token::PlusEqual => AssignmentOperator::AddAssign, - Token::MinusEqual => AssignmentOperator::SubtractAssign, + if let Token::Equal = &self.current_token { + self.next_token()?; + + let value = self.parse_expression(operator_precedence)?; + let position = (left_start, value.position().1); + + return Ok(Statement::operator_expression( + OperatorExpression::Assignment { + assignee: left, + value, + }, + position, + )); + } + + if let Token::PlusEqual | Token::MinusEqual = &self.current_token { + let math_operator = match self.current_token { + Token::PlusEqual => MathOperator::Add, + Token::MinusEqual => MathOperator::Subtract, _ => unreachable!(), }; - let operator_position = self.current.1; + let operator = Node::new(math_operator, self.current_position); self.next_token()?; - let identifier = if let Statement::Identifier(identifier) = left.inner { - Node::new(identifier, left.position) - } else { - return Err(ParseError::ExpectedToken { - expected: TokenKind::Identifier, - actual: self.current.0.to_owned(), - position: self.current.1, - }); - }; - let right = self.parse_statement(operator_precedence)?; - let right_end = right.position.1; + let value = self.parse_expression(operator_precedence)?; + let position = (left_start, value.position().1); - return Ok(Node::new( - Statement::Assignment { - identifier, - operator: Node::new(operator, operator_position), - value: Box::new(right), + return Ok(Statement::operator_expression( + OperatorExpression::CompoundAssignment { + assignee: left, + operator, + value, }, - (left_start, right_end), + position, )); } - if let Token::Dot = &self.current.0 { - let operator_position = self.current.1; - + if let Token::Dot = &self.current_token { self.next_token()?; - let right = self.parse_statement(operator_precedence)?; - let right_end = right.position.1; + let field = self.parse_identifier()?; + let position = (left_start, self.current_position.1); - if let Statement::BuiltInFunctionCall { - function, - type_arguments, - value_arguments, - } = right.inner - { - let value_arguments = if let Some(mut arguments) = value_arguments { - arguments.insert(0, left); - - Some(arguments) - } else { - Some(vec![left]) - }; - - return Ok(Node::new( - Statement::BuiltInFunctionCall { - function, - type_arguments, - value_arguments, - }, - (left_start, right_end), - )); - } - - if let Statement::Invokation { - invokee: function, - type_arguments, - value_arguments, - } = right.inner - { - let value_arguments = if let Some(mut arguments) = value_arguments { - arguments.insert(0, left); - - Some(arguments) - } else { - Some(vec![left]) - }; - - return Ok(Node::new( - Statement::Invokation { - invokee: function, - type_arguments, - value_arguments, - }, - (left_start, right_end), - )); - } - - return Ok(Node::new( - Statement::BinaryOperation { - left: Box::new(left), - operator: Node::new(BinaryOperator::FieldAccess, operator_position), - right: Box::new(right), + return Ok(Statement::field_access( + FieldAccess { + container: left, + field, }, - (left_start, right_end), + position, )); } - let binary_operator = match &self.current.0 { - Token::DoubleAmpersand => Node::new(BinaryOperator::And, self.current.1), - Token::DoubleEqual => Node::new(BinaryOperator::Equal, self.current.1), - Token::DoublePipe => Node::new(BinaryOperator::Or, self.current.1), - Token::Greater => Node::new(BinaryOperator::Greater, self.current.1), - Token::GreaterEqual => Node::new(BinaryOperator::GreaterOrEqual, self.current.1), - Token::Less => Node::new(BinaryOperator::Less, self.current.1), - Token::LessEqual => Node::new(BinaryOperator::LessOrEqual, self.current.1), - Token::Minus => Node::new(BinaryOperator::Subtract, self.current.1), - Token::Plus => Node::new(BinaryOperator::Add, self.current.1), - Token::Star => Node::new(BinaryOperator::Multiply, self.current.1), - Token::Slash => Node::new(BinaryOperator::Divide, self.current.1), - Token::Percent => Node::new(BinaryOperator::Modulo, self.current.1), + let math_operator = match &self.current_token { + Token::Minus => Node::new(MathOperator::Subtract, self.current_position), + Token::Plus => Node::new(MathOperator::Add, self.current_position), + Token::Star => Node::new(MathOperator::Multiply, self.current_position), + Token::Slash => Node::new(MathOperator::Divide, self.current_position), + Token::Percent => Node::new(MathOperator::Modulo, self.current_position), _ => { return Err(ParseError::UnexpectedToken { - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } }; self.next_token()?; - let left_start = left.position.0; - let right = self.parse_statement(operator_precedence)?; - let right_end = right.position.1; + let right = self.parse_expression(operator_precedence)?; + let position = (left_start, right.position().1); - Ok(Node::new( - Statement::BinaryOperation { - left: Box::new(left), - operator: binary_operator, - right: Box::new(right), + Ok(Statement::operator_expression( + OperatorExpression::Math { + left, + operator: math_operator, + right, }, - (left_start, right_end), + position, )) } - fn parse_postfix(&mut self, left: Node) -> Result, ParseError> { - log::trace!("Parsing {} as postfix operator", self.current.0); + fn parse_postfix(&mut self, left: Statement) -> Result { + log::trace!("Parsing {} as postfix operator", self.current_token); - let left_start = left.position.0; + let left = if let Statement::Expression(expression) = left { + expression + } else { + return Err(ParseError::ExpectedExpression { actual: left }); + }; - let statement = match &self.current.0 { + let statement = match &self.current_token { Token::LeftParenthesis => { self.next_token()?; let mut arguments = Vec::new(); - while self.current.0 != Token::RightParenthesis { - let argument = self.parse_statement(0)?; + while self.current_token != Token::RightParenthesis { + let argument = self.parse_expression(0)?; arguments.push(argument); - if let Token::Comma = self.current.0 { + if let Token::Comma = self.current_token { self.next_token()?; } else { break; @@ -1015,26 +702,25 @@ impl<'src> Parser<'src> { self.next_token()?; - let right_end = self.current.1 .1; + let position = (left.position().0, self.current_position.1); - Node::new( - Statement::Invokation { - invokee: Box::new(left), - type_arguments: None, - value_arguments: Some(arguments), + Statement::call_expression( + CallExpression { + function: left, + arguments, }, - (left_start, right_end), + position, ) } Token::LeftSquareBrace => { - let operator_start = self.current.1 .0; + let operator_start = self.current_position.0; self.next_token()?; - let index = self.parse_statement(0)?; + let index = self.parse_expression(0)?; - let operator_end = if let Token::RightSquareBrace = self.current.0 { - let end = self.current.1 .1; + let operator_end = if let Token::RightSquareBrace = self.current_token { + let end = self.current_position.1; self.next_token()?; @@ -1042,110 +728,118 @@ impl<'src> Parser<'src> { } else { return Err(ParseError::ExpectedToken { expected: TokenKind::RightSquareBrace, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); }; - let right_end = self.current.1 .1; + let position = (left.position().0, operator_end); - Node::new( - Statement::BinaryOperation { - left: Box::new(left), - operator: Node::new( - BinaryOperator::ListIndex, - (operator_start, operator_end), - ), - right: Box::new(index), - }, - (left_start, right_end), - ) + Statement::list_index(ListIndex { list: left, index }, position) } Token::Semicolon => { - let operator_end = self.current.1 .1; + let position = (left.position().0, self.current_position.1); self.next_token()?; - Node::new(Statement::Nil(Box::new(left)), (left_start, operator_end)) + Statement::ExpressionNullified(Node::new(left, position)) } _ => { return Err(ParseError::UnexpectedToken { - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } }; - if self.current.0.is_postfix() { + if self.current_token.is_postfix() { self.parse_postfix(statement) } else { Ok(statement) } } - fn parse_identifier(&mut self) -> Result, ParseError> { - let identifier = if let Token::Identifier(text) = &self.current.0 { - Node::new(Identifier::new(text), self.current.1) + fn parse_expression(&mut self, precedence: u8) -> Result { + log::trace!("Parsing expression"); + + let statement = self.parse_next(precedence)?; + + if let Statement::Expression(expression) = statement { + Ok(expression) } else { - return Err(ParseError::ExpectedToken { - expected: TokenKind::Identifier, - actual: self.current.0.to_owned(), - position: self.current.1, - }); - }; - - self.next_token()?; - - Ok(identifier) + Err(ParseError::ExpectedExpression { actual: statement }) + } } - fn parse_block(&mut self) -> Result, ParseError> { - let left_start = self.current.1 .0; + fn parse_identifier(&mut self) -> Result, ParseError> { + if let Token::Identifier(text) = self.current_token { + self.next_token()?; - if let Token::LeftCurlyBrace = self.current.0 { + Ok(Node::new(Identifier::new(text), self.current_position)) + } else { + Err(ParseError::ExpectedToken { + expected: TokenKind::Identifier, + actual: self.current_token.to_owned(), + position: self.current_position, + }) + } + } + + fn parse_block(&mut self) -> Result, ParseError> { + let left_start = self.current_position.0; + let is_async = if let Token::Async = self.current_token { + self.next_token()?; + + true + } else { + false + }; + + if let Token::LeftCurlyBrace = self.current_token { self.next_token()?; } else { return Err(ParseError::ExpectedToken { expected: TokenKind::LeftCurlyBrace, - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } let mut statements = Vec::new(); loop { - if let Token::RightCurlyBrace = self.current.0 { - let right_end = self.current.1 .1; + if let Token::RightCurlyBrace = self.current_token { + let position = (left_start, self.current_position.1); self.next_token()?; - return Ok(Node::new( - Statement::Block(statements), - (left_start, right_end), - )); + return if is_async { + Ok(Node::new(Block::Async(statements), position)) + } else { + Ok(Node::new(Block::Sync(statements), position)) + }; } - let statement = self.parse_statement(0)?; + let statement = self.parse_next(0)?; statements.push(statement); } } fn parse_type(&mut self) -> Result, ParseError> { - let r#type = match self.current.0 { + let r#type = match self.current_token { Token::Bool => Type::Boolean, Token::FloatKeyword => Type::Float, Token::Int => Type::Integer, _ => { return Err(ParseError::ExpectedTokenMultiple { expected: vec![TokenKind::Bool, TokenKind::FloatKeyword, TokenKind::Int], - actual: self.current.0.to_owned(), - position: self.current.1, + actual: self.current_token.to_owned(), + position: self.current_position, }); } }; - let position = self.current.1; + let position = self.current_position; self.next_token()?; @@ -1153,22 +847,18 @@ impl<'src> Parser<'src> { } } -#[derive(Debug, PartialEq, Clone, Copy)] -enum ParserMode { - Condition, - Mutable, - None, -} - #[derive(Debug, PartialEq, Clone)] pub enum ParseError { - BooleanError { + Boolean { error: ParseBoolError, position: Span, }, - LexError(LexError), + Lex(LexError), ExpectedAssignment { - actual: Node, + actual: Statement, + }, + ExpectedExpression { + actual: Statement, }, ExpectedIdentifier { actual: TokenOwned, @@ -1188,11 +878,11 @@ pub enum ParseError { actual: TokenOwned, position: Span, }, - FloatError { + Float { error: ParseFloatError, position: Span, }, - IntegerError { + Integer { error: ParseIntError, position: Span, }, @@ -1200,21 +890,22 @@ pub enum ParseError { impl From for ParseError { fn from(v: LexError) -> Self { - Self::LexError(v) + Self::Lex(v) } } impl ParseError { pub fn position(&self) -> Span { match self { - ParseError::BooleanError { position, .. } => *position, - ParseError::ExpectedAssignment { actual } => actual.position, + ParseError::Boolean { position, .. } => *position, + ParseError::ExpectedAssignment { actual } => actual.position(), + ParseError::ExpectedExpression { actual } => actual.position(), ParseError::ExpectedIdentifier { position, .. } => *position, ParseError::ExpectedToken { position, .. } => *position, ParseError::ExpectedTokenMultiple { position, .. } => *position, - ParseError::FloatError { position, .. } => *position, - ParseError::IntegerError { position, .. } => *position, - ParseError::LexError(error) => error.position(), + ParseError::Float { position, .. } => *position, + ParseError::Integer { position, .. } => *position, + ParseError::Lex(error) => error.position(), ParseError::UnexpectedToken { position, .. } => *position, } } @@ -1223,7 +914,7 @@ impl ParseError { impl Error for ParseError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { - Self::LexError(error) => Some(error), + Self::Lex(error) => Some(error), _ => None, } } @@ -1232,8 +923,9 @@ impl Error for ParseError { impl Display for ParseError { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Self::BooleanError { error, .. } => write!(f, "{}", error), + Self::Boolean { error, .. } => write!(f, "{}", error), Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"), + Self::ExpectedExpression { .. } => write!(f, "Expected expression"), Self::ExpectedIdentifier { actual, .. } => { write!(f, "Expected identifier, found {actual}") } @@ -1257,9 +949,9 @@ impl Display for ParseError { write!(f, ", found {actual}") } - Self::FloatError { error, .. } => write!(f, "{}", error), - Self::IntegerError { error, .. } => write!(f, "{}", error), - Self::LexError(error) => write!(f, "{}", error), + Self::Float { error, .. } => write!(f, "{}", error), + Self::Integer { error, .. } => write!(f, "{}", error), + Self::Lex(error) => write!(f, "{}", error), Self::UnexpectedToken { actual, .. } => write!(f, "Unexpected token {actual}"), } } @@ -1267,7 +959,7 @@ impl Display for ParseError { #[cfg(test)] mod tests { - use crate::{BinaryOperator, Identifier, StructDefinition, Type, UnaryOperator}; + use crate::{Identifier, StructDefinition, Type}; use super::*; @@ -1275,22 +967,7 @@ mod tests { fn mutable_variable() { let input = "mut x = false"; - assert_eq!( - parse(input), - Ok(AbstractSyntaxTree { - nodes: [Node::new( - Statement::AssignmentMut { - identifier: Node::new(Identifier::new("x"), (4, 5)), - value: Box::new(Node::new( - Statement::ConstantMut(Value::boolean_mut(false)), - (8, 13) - )), - }, - (0, 13) - )] - .into() - }) - ); + assert_eq!(parse(input), todo!()); } #[test] @@ -1300,35 +977,15 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( - Statement::AsyncBlock(vec![ - Node::new( - Statement::Nil(Box::new(Node::new( - Statement::Assignment { - identifier: Node::new(Identifier::new("x"), (8, 9)), - operator: Node::new(AssignmentOperator::Assign, (10, 11)), - value: Box::new(Node::new( - Statement::Constant(Value::integer(42)), - (12, 14) - )), - }, - (8, 14) - ))), - (8, 15) - ), - Node::new( - Statement::Assignment { - identifier: Node::new(Identifier::new("y"), (16, 17)), - operator: Node::new(AssignmentOperator::Assign, (18, 19)), - value: Box::new(Node::new( - Statement::Constant(Value::float(4.0)), - (20, 23) - )), - }, - (16, 23) - ) - ]), - (0, 25) + statements: [Statement::block( + Block::Async(vec![Statement::operator_expression( + OperatorExpression::Assignment { + assignee: Expression::WithoutBlock(()), + value: () + }, + position + )]), + position )] .into() }) @@ -1347,7 +1004,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::Invokation { @@ -1383,7 +1040,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::FieldsStructInstantiation { name: Node::new(Identifier::new("Foo"), (0, 3)), fields: vec![ @@ -1411,7 +1068,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::StructDefinition(StructDefinition::Fields { name: Node::new(Identifier::new("Foo"), (7, 10)), fields: vec![ @@ -1439,7 +1096,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [ + statements: [ Node::new( Statement::StructDefinition(StructDefinition::Tuple { name: Node::new(Identifier::new("Foo"), (7, 10)), @@ -1477,7 +1134,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::StructDefinition(StructDefinition::Tuple { name: Node::new(Identifier::new("Foo"), (7, 10)), items: vec![ @@ -1499,7 +1156,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::StructDefinition(StructDefinition::Unit { name: Node::new(Identifier::new("Foo"), (7, 10)), }), @@ -1517,7 +1174,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::BinaryOperation { @@ -1563,7 +1220,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::BinaryOperation { @@ -1611,7 +1268,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new(Statement::Constant(Value::range(0..42)), (0, 5))].into() + statements: [Node::new(Statement::Constant(Value::range(0..42)), (0, 5))].into() }) ); } @@ -1623,7 +1280,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [ + statements: [ Node::new( Statement::Nil(Box::new(Node::new( Statement::Assignment { @@ -1661,7 +1318,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::UnaryOperation { operator: Node::new(UnaryOperator::Negate, (0, 1)), operand: Box::new(Node::new( @@ -1693,7 +1350,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::UnaryOperation { operator: Node::new(UnaryOperator::Not, (0, 1)), operand: Box::new(Node::new( @@ -1725,7 +1382,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [ + statements: [ Node::new( Statement::Nil(Box::new(Node::new( Statement::Assignment { @@ -1763,7 +1420,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::If { condition: Box::new(Node::new( Statement::Identifier(Identifier::new("x")), @@ -1791,7 +1448,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::IfElse { condition: Box::new(Node::new( Statement::Identifier(Identifier::new("x")), @@ -1826,7 +1483,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::IfElseIfElse { condition: Box::new(Node::new( Statement::Identifier(Identifier::new("x")), @@ -1899,7 +1556,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::While { condition: Box::new(Node::new( Statement::BinaryOperation { @@ -1944,7 +1601,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Assignment { identifier: Node::new(Identifier::new("a"), (0, 1)), operator: Node::new(AssignmentOperator::AddAssign, (2, 4)), @@ -1964,7 +1621,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::Constant(Value::boolean(true)), @@ -2006,7 +1663,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Block(vec![Node::new( Statement::BinaryOperation { left: Box::new(Node::new( @@ -2035,7 +1692,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Block(vec![ Node::new( Statement::Nil(Box::new(Node::new( @@ -2091,7 +1748,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new(Statement::Map(vec![]), (0, 2))].into() + statements: [Node::new(Statement::Map(vec![]), (0, 2))].into() }) ); } @@ -2103,7 +1760,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Map(vec![ ( Node::new(Identifier::new("foo"), (2, 5)), @@ -2132,7 +1789,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Map(vec![ ( Node::new(Identifier::new("x"), (2, 3)), @@ -2157,7 +1814,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Map(vec![( Node::new(Identifier::new("x"), (2, 3)), Node::new(Statement::Constant(Value::integer(42)), (6, 8)) @@ -2176,7 +1833,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(42)), (0, 2))), operator: Node::new(BinaryOperator::Equal, (3, 5)), @@ -2196,7 +1853,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(42)), (0, 2))), operator: Node::new(BinaryOperator::Modulo, (3, 4)), @@ -2216,7 +1873,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(42)), (0, 2))), operator: Node::new(BinaryOperator::Divide, (3, 4)), @@ -2236,7 +1893,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::Less, (2, 3)), @@ -2256,7 +1913,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::LessOrEqual, (2, 4)), @@ -2276,7 +1933,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::GreaterOrEqual, (2, 4)), @@ -2296,7 +1953,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::Greater, (2, 3)), @@ -2316,7 +1973,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Node::new(Statement::Constant(Value::integer(-1)), (0, 2)).into(), operator: Node::new(BinaryOperator::Subtract, (3, 4)), @@ -2336,7 +1993,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::Constant(Value::string("Hello, ")), @@ -2362,7 +2019,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Constant(Value::string("Hello, World!")), (0, 15) )] @@ -2378,7 +2035,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new(Statement::Constant(Value::boolean(true)), (0, 4))].into() + statements: [Node::new(Statement::Constant(Value::boolean(true)), (0, 4))].into() }) ); } @@ -2390,7 +2047,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BuiltInFunctionCall { function: BuiltInFunction::IsEven, type_arguments: None, @@ -2413,7 +2070,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::List(vec![ @@ -2443,7 +2100,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new( Statement::Identifier(Identifier::new("a")), @@ -2469,7 +2126,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::List(vec![ Node::new(Statement::Constant(Value::integer(1)), (1, 2)), Node::new( @@ -2525,7 +2182,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::List(vec![ Node::new(Statement::Constant(Value::integer(1)), (1, 2)), Node::new(Statement::Constant(Value::integer(2)), (4, 5)), @@ -2544,7 +2201,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new(Statement::List(vec![]), (0, 2))].into() + statements: [Node::new(Statement::List(vec![]), (0, 2))].into() }) ); } @@ -2556,7 +2213,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new(Statement::Constant(Value::float(42.0)), (0, 4))].into() + statements: [Node::new(Statement::Constant(Value::float(42.0)), (0, 4))].into() }) ); } @@ -2568,7 +2225,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::Add, (2, 3)), @@ -2588,7 +2245,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::Multiply, (2, 3)), @@ -2608,7 +2265,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::BinaryOperation { left: Box::new(Node::new(Statement::Constant(Value::integer(1)), (0, 1))), operator: Node::new(BinaryOperator::Add, (2, 3)), @@ -2641,7 +2298,7 @@ mod tests { assert_eq!( parse(input), Ok(AbstractSyntaxTree { - nodes: [Node::new( + statements: [Node::new( Statement::Assignment { identifier: Node::new(Identifier::new("a"), (0, 1)), operator: Node::new(AssignmentOperator::Assign, (2, 3)), diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index cafea0e..5a0ff2a 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -389,6 +389,42 @@ impl Value { Err(ValueError::CannotSubtract(self.clone(), other.clone())) } + pub fn subtract_mut(&self, other: &Value) -> Result<(), ValueError> { + match (self, other) { + (Value::Mutable(left), Value::Mutable(right)) => { + match (&mut *left.write().unwrap(), &*right.read().unwrap()) { + (ValueData::Float(left), ValueData::Float(right)) => { + *left -= right; + return Ok(()); + } + (ValueData::Integer(left), ValueData::Integer(right)) => { + *left = left.saturating_sub(*right); + return Ok(()); + } + _ => {} + } + } + (Value::Mutable(left), Value::Immutable(right)) => { + match (&mut *left.write().unwrap(), right.as_ref()) { + (ValueData::Float(left), ValueData::Float(right)) => { + *left -= right; + return Ok(()); + } + (ValueData::Integer(left), ValueData::Integer(right)) => { + *left = left.saturating_sub(*right); + return Ok(()); + } + _ => {} + } + } + (Value::Immutable(_), _) => { + return Err(ValueError::CannotMutate(self.clone())); + } + } + + Err(ValueError::CannotSubtract(self.clone(), other.clone())) + } + pub fn multiply(&self, other: &Value) -> Result { match (self, other) { (Value::Immutable(left), Value::Immutable(right)) => { @@ -1424,7 +1460,7 @@ impl Display for Function { write!(f, ") {{")?; - for statement in &self.body.nodes { + for statement in &self.body.statements { write!(f, "{}", statement)?; } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 40f7428..8b93e66 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -88,7 +88,7 @@ impl Vm { let mut previous_position = (0, 0); let mut previous_value = None; - while let Some(statement) = self.abstract_tree.nodes.pop_front() { + while let Some(statement) = self.abstract_tree.statements.pop_front() { let new_position = statement.position; previous_value = self.run_statement(statement)?; @@ -118,7 +118,18 @@ impl Vm { return Err(VmError::ExpectedValue { position }); }; - self.context.set_value(identifier.inner, value); + if let Some(existing_value) = self.context.get_value(&identifier.inner) { + if existing_value.is_mutable() { + existing_value.mutate(&value); + } else { + return Err(VmError::CannotMutate { + value: existing_value, + position: identifier.position, + }); + } + } else { + self.context.set_value(identifier.inner, value); + } Ok(None) } @@ -146,14 +157,10 @@ impl Vm { } })?; } else { - let new_value = left_value.add(&right_value).map_err(|value_error| { - VmError::ValueError { - error: value_error, - position: (identifier.position.0, value_position.1), - } - })?; - - self.context.set_value(identifier.inner, new_value); + return Err(VmError::CannotMutate { + value: left_value, + position: identifier.position, + }); } Ok(None) @@ -173,14 +180,20 @@ impl Vm { position: value_position, }); }; - let new_value = left_value.subtract(&right_value).map_err(|value_error| { - VmError::ValueError { - error: value_error, - position: (identifier.position.0, value_position.1), - } - })?; - self.context.set_value(identifier.inner, new_value); + if left_value.is_mutable() { + left_value + .subtract_mut(&right_value) + .map_err(|value_error| VmError::ValueError { + error: value_error, + position: (identifier.position.0, value_position.1), + })?; + } else { + return Err(VmError::CannotMutate { + value: left_value, + position: identifier.position, + }); + } Ok(None) } @@ -748,6 +761,10 @@ pub enum VmError { error: BuiltInFunctionError, position: Span, }, + CannotMutate { + value: Value, + position: Span, + }, ExpectedBoolean { position: Span, }, @@ -795,6 +812,7 @@ impl VmError { match self { Self::ParseError(parse_error) => parse_error.position(), Self::ValueError { position, .. } => *position, + Self::CannotMutate { position, .. } => *position, Self::BuiltInFunctionError { position, .. } => *position, Self::ExpectedBoolean { position } => *position, Self::ExpectedIdentifier { position } => *position, @@ -825,6 +843,9 @@ impl Display for VmError { match self { Self::ParseError(parse_error) => write!(f, "{}", parse_error), Self::ValueError { error, .. } => write!(f, "{}", error), + Self::CannotMutate { value, .. } => { + write!(f, "Cannot mutate immutable value {}", value) + } Self::BuiltInFunctionError { error, .. } => { write!(f, "{}", error) } @@ -834,7 +855,7 @@ impl Display for VmError { Self::ExpectedFunction { actual, position } => { write!( f, - "Expected a function, but got: {} at position: {:?}", + "Expected a function, but got {} at position: {:?}", actual, position ) } @@ -908,7 +929,7 @@ mod tests { #[test] fn async_block() { - let input = "x = 1; async { x += 1; x -= 1; } x"; + let input = "mut x = 1; async { x += 1; x -= 1; } x"; assert!(run(input).unwrap().unwrap().as_integer().is_some()); } @@ -1107,21 +1128,21 @@ mod tests { #[test] fn while_loop() { - let input = "x = 0; while x < 5 { x += 1; } x"; + let input = "mut x = 0; while x < 5 { x += 1; } x"; assert_eq!(run(input), Ok(Some(Value::integer(5)))); } #[test] fn subtract_assign() { - let input = "x = 1; x -= 1; x"; + let input = "mut x = 1; x -= 1; x"; assert_eq!(run(input), Ok(Some(Value::integer(0)))); } #[test] fn add_assign() { - let input = "x = 1; x += 1; x"; + let input = "mut x = 1; x += 1; x"; assert_eq!(run(input), Ok(Some(Value::integer(2)))); }