Fix parsing bug

This commit is contained in:
Jeff 2024-08-31 07:24:45 -04:00
parent f2e5b8d499
commit e643ebe114
6 changed files with 328 additions and 328 deletions

View File

@ -17,8 +17,8 @@ use crate::{
PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition, PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition,
StructExpression, TupleAccessExpression, StructExpression, TupleAccessExpression,
}, },
parse, ContextError, DustError, Expression, Identifier, RangeableType, StructType, Type, parse, Context, ContextData, ContextError, DustError, Expression, Identifier, RangeableType,
TypeConflict, TypeEvaluation, StructType, Type, TypeConflict, TypeEvaluation,
}; };
/// Analyzes the abstract syntax tree for errors. /// Analyzes the abstract syntax tree for errors.
@ -36,7 +36,7 @@ pub fn analyze(source: &str) -> Result<(), DustError> {
let abstract_tree = parse(source)?; let abstract_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_tree); let mut analyzer = Analyzer::new(&abstract_tree);
analyzer.analyze(); analyzer.analyze()?;
if analyzer.errors.is_empty() { if analyzer.errors.is_empty() {
Ok(()) Ok(())
@ -71,19 +71,23 @@ impl<'a> Analyzer<'a> {
} }
} }
pub fn analyze(&mut self) { pub fn analyze(&mut self) -> Result<(), ContextError> {
for statement in &self.abstract_tree.statements { for statement in &self.abstract_tree.statements {
self.analyze_statement(statement); self.analyze_statement(statement, &self.abstract_tree.context)?;
}
} }
fn analyze_statement(&mut self, statement: &Statement) { Ok(())
match statement {
Statement::Expression(expression) => {
self.analyze_expression(expression, statement.position())
} }
fn analyze_statement(
&mut self,
statement: &Statement,
context: &Context,
) -> Result<(), ContextError> {
match statement {
Statement::Expression(expression) => self.analyze_expression(expression, context)?,
Statement::ExpressionNullified(expression_node) => { Statement::ExpressionNullified(expression_node) => {
self.analyze_expression(&expression_node.inner, statement.position()); self.analyze_expression(&expression_node.inner, context)?;
} }
Statement::Let(let_statement) => match &let_statement.inner { Statement::Let(let_statement) => match &let_statement.inner {
LetStatement::Let { identifier, value } LetStatement::Let { identifier, value }
@ -92,42 +96,25 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
Ok(TypeEvaluation::Constructor(StructType::Unit { name })) => { Ok(TypeEvaluation::Constructor(StructType::Unit { name })) => {
let set_type = self.abstract_tree.context.set_variable_type( self.abstract_tree.context.set_variable_type(
identifier.inner.clone(), identifier.inner.clone(),
Type::Struct(StructType::Unit { name }), Type::Struct(StructType::Unit { name }),
statement.position(), )?;
);
if let Err(context_error) = set_type { self.analyze_expression(value, context)?;
self.errors.push(AnalysisError::ContextError {
error: context_error,
position: identifier.position,
});
}
self.analyze_expression(value, statement.position()); return Ok(());
return;
} }
Ok(evaluation) => evaluation.r#type(), Ok(evaluation) => evaluation.r#type(),
}; };
if let Some(r#type) = r#type { if let Some(r#type) = r#type {
let set_type = self.abstract_tree.context.set_variable_type( self.abstract_tree
identifier.inner.clone(), .context
r#type.clone(), .set_variable_type(identifier.inner.clone(), r#type.clone())?;
statement.position(),
);
if let Err(context_error) = set_type {
self.errors.push(AnalysisError::ContextError {
error: context_error,
position: identifier.position,
});
}
} else { } else {
self.errors self.errors
.push(AnalysisError::LetExpectedValueFromStatement { .push(AnalysisError::LetExpectedValueFromStatement {
@ -135,13 +122,13 @@ impl<'a> Analyzer<'a> {
}); });
} }
self.analyze_expression(value, statement.position()); self.analyze_expression(value, context)?;
} }
LetStatement::LetType { .. } => todo!(), LetStatement::LetType { .. } => todo!(),
LetStatement::LetMutType { .. } => todo!(), LetStatement::LetMutType { .. } => todo!(),
}, },
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(struct_definition) => {
let set_constructor_type = match &struct_definition.inner { match &struct_definition.inner {
StructDefinition::Unit { name } => { StructDefinition::Unit { name } => {
self.abstract_tree.context.set_constructor_type( self.abstract_tree.context.set_constructor_type(
name.inner.clone(), name.inner.clone(),
@ -149,7 +136,7 @@ impl<'a> Analyzer<'a> {
name: name.inner.clone(), name: name.inner.clone(),
}, },
statement.position(), statement.position(),
) )?;
} }
StructDefinition::Tuple { name, items } => { StructDefinition::Tuple { name, items } => {
let fields = items.iter().map(|item| item.inner.clone()).collect(); let fields = items.iter().map(|item| item.inner.clone()).collect();
@ -161,7 +148,7 @@ impl<'a> Analyzer<'a> {
fields, fields,
}, },
statement.position(), statement.position(),
) )?;
} }
StructDefinition::Fields { name, fields } => { StructDefinition::Fields { name, fields } => {
let fields = fields let fields = fields
@ -178,32 +165,33 @@ impl<'a> Analyzer<'a> {
fields, fields,
}, },
statement.position(), statement.position(),
) )?;
} }
}; };
if let Err(context_error) = set_constructor_type {
self.errors.push(AnalysisError::ContextError {
error: context_error,
position: struct_definition.position,
});
}
}
} }
} }
fn analyze_expression(&mut self, expression: &Expression, statement_position: Span) { Ok(())
}
fn analyze_expression(
&mut self,
expression: &Expression,
context: &Context,
) -> Result<(), ContextError> {
match expression { match expression {
Expression::Block(block_expression) => self.analyze_block(&block_expression.inner), Expression::Block(block_expression) => {
self.analyze_block(&block_expression.inner, context)?;
}
Expression::Break(break_node) => { Expression::Break(break_node) => {
if let Some(expression) = &break_node.inner { if let Some(expression) = &break_node.inner {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
} }
Expression::Call(call_expression) => { Expression::Call(call_expression) => {
let CallExpression { invoker, arguments } = call_expression.inner.as_ref(); let CallExpression { invoker, arguments } = call_expression.inner.as_ref();
self.analyze_expression(invoker, statement_position); self.analyze_expression(invoker, context)?;
let invoker_evaluation = match invoker.type_evaluation(&self.abstract_tree.context) let invoker_evaluation = match invoker.type_evaluation(&self.abstract_tree.context)
{ {
@ -211,7 +199,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -225,7 +213,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -241,7 +229,7 @@ impl<'a> Analyzer<'a> {
} }
} }
return; return Ok(());
} }
let invoked_type = if let Some(r#type) = invoker_evaluation.r#type() { let invoked_type = if let Some(r#type) = invoker_evaluation.r#type() {
@ -252,7 +240,7 @@ impl<'a> Analyzer<'a> {
expression: invoker.clone(), expression: invoker.clone(),
}); });
return; return Ok(());
}; };
let function_type = if let Type::Function(function_type) = invoked_type { let function_type = if let Type::Function(function_type) = invoked_type {
function_type function_type
@ -262,7 +250,7 @@ impl<'a> Analyzer<'a> {
actual_expression: invoker.clone(), actual_expression: invoker.clone(),
}); });
return; return Ok(());
}; };
let value_parameters = let value_parameters =
@ -277,11 +265,11 @@ impl<'a> Analyzer<'a> {
}); });
} }
return; return Ok(());
}; };
for ((_, expected_type), argument) in value_parameters.iter().zip(arguments) { for ((_, expected_type), argument) in value_parameters.iter().zip(arguments) {
self.analyze_expression(argument, statement_position); self.analyze_expression(argument, context)?;
let argument_evaluation = let argument_evaluation =
match argument.type_evaluation(&self.abstract_tree.context) { match argument.type_evaluation(&self.abstract_tree.context) {
@ -313,11 +301,11 @@ impl<'a> Analyzer<'a> {
} }
for argument in arguments { for argument in arguments {
self.analyze_expression(argument, statement_position); self.analyze_expression(argument, context)?;
} }
} }
Expression::Dereference(expression) => { Expression::Dereference(expression) => {
self.analyze_expression(&expression.inner, statement_position); self.analyze_expression(&expression.inner, context)?;
} }
Expression::FieldAccess(field_access_expression) => { Expression::FieldAccess(field_access_expression) => {
let FieldAccessExpression { container, field } = let FieldAccessExpression { container, field } =
@ -328,7 +316,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let container_type = match evaluation.r#type() { let container_type = match evaluation.r#type() {
@ -339,7 +327,7 @@ impl<'a> Analyzer<'a> {
expression: container.clone(), expression: container.clone(),
}); });
return; return Ok(());
} }
}; };
@ -350,59 +338,47 @@ impl<'a> Analyzer<'a> {
}); });
} }
self.analyze_expression(container, statement_position); self.analyze_expression(container, context)?;
} }
Expression::Grouped(expression) => { Expression::Grouped(expression) => {
self.analyze_expression(expression.inner.as_ref(), statement_position); self.analyze_expression(expression.inner.as_ref(), context)?;
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let find_identifier = self let context_data = context.get_data(&identifier.inner)?;
.abstract_tree
.context
.update_last_position(&identifier.inner, statement_position);
if let Ok(false) = find_identifier { if let Some(ContextData::Reserved) | None = context_data {
self.errors.push(AnalysisError::UndefinedVariable { self.errors.push(AnalysisError::UndefinedVariable {
identifier: identifier.clone(), identifier: identifier.clone(),
}); });
} }
if let Err(context_error) = find_identifier {
self.errors.push(AnalysisError::ContextError {
error: context_error,
position: identifier.position,
});
}
}
Expression::If(if_expression) => {
self.analyze_if(&if_expression.inner, statement_position)
} }
Expression::If(if_expression) => self.analyze_if(&if_expression.inner, context)?,
Expression::List(list_expression) => match list_expression.inner.as_ref() { Expression::List(list_expression) => match list_expression.inner.as_ref() {
ListExpression::AutoFill { ListExpression::AutoFill {
repeat_operand, repeat_operand,
length_operand, length_operand,
} => { } => {
self.analyze_expression(repeat_operand, statement_position); self.analyze_expression(repeat_operand, context)?;
self.analyze_expression(length_operand, statement_position); self.analyze_expression(length_operand, context)?;
} }
ListExpression::Ordered(expressions) => { ListExpression::Ordered(expressions) => {
for expression in expressions { for expression in expressions {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
} }
}, },
Expression::ListIndex(list_index_expression) => { Expression::ListIndex(list_index_expression) => {
let ListIndexExpression { list, index } = list_index_expression.inner.as_ref(); let ListIndexExpression { list, index } = list_index_expression.inner.as_ref();
self.analyze_expression(list, statement_position); self.analyze_expression(list, context)?;
self.analyze_expression(index, statement_position); self.analyze_expression(index, context)?;
let list_type_evaluation = match list.type_evaluation(&self.abstract_tree.context) { let list_type_evaluation = match list.type_evaluation(&self.abstract_tree.context) {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let list_type = match list_type_evaluation.r#type() { let list_type = match list_type_evaluation.r#type() {
@ -413,7 +389,7 @@ impl<'a> Analyzer<'a> {
expression: list.clone(), expression: list.clone(),
}); });
return; return Ok(());
} }
}; };
let index_type_evaluation = match index.type_evaluation(&self.abstract_tree.context) let index_type_evaluation = match index.type_evaluation(&self.abstract_tree.context)
@ -422,7 +398,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let index_type = match index_type_evaluation.r#type() { let index_type = match index_type_evaluation.r#type() {
@ -433,7 +409,7 @@ impl<'a> Analyzer<'a> {
expression: list.clone(), expression: list.clone(),
}); });
return; return Ok(());
} }
}; };
let literal_type = if let Expression::Literal(Node { inner, .. }) = index { let literal_type = if let Expression::Literal(Node { inner, .. }) = index {
@ -510,39 +486,39 @@ impl<'a> Analyzer<'a> {
// Literals don't need to be analyzed // Literals don't need to be analyzed
} }
Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() { Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() {
LoopExpression::Infinite { block } => self.analyze_block(&block.inner), LoopExpression::Infinite { block } => self.analyze_block(&block.inner, context)?,
LoopExpression::While { condition, block } => { LoopExpression::While { condition, block } => {
self.analyze_expression(condition, statement_position); self.analyze_expression(condition, context)?;
self.analyze_block(&block.inner); self.analyze_block(&block.inner, context)?;
} }
LoopExpression::For { LoopExpression::For {
iterator, block, .. iterator, block, ..
} => { } => {
self.analyze_expression(iterator, statement_position); self.analyze_expression(iterator, context)?;
self.analyze_block(&block.inner); self.analyze_block(&block.inner, context)?;
} }
}, },
Expression::Map(map_expression) => { Expression::Map(map_expression) => {
let MapExpression { pairs } = map_expression.inner.as_ref(); let MapExpression { pairs } = map_expression.inner.as_ref();
for (_, expression) in pairs { for (_, expression) in pairs {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
} }
Expression::Operator(operator_expression) => match operator_expression.inner.as_ref() { Expression::Operator(operator_expression) => match operator_expression.inner.as_ref() {
OperatorExpression::Assignment { assignee, value } => { OperatorExpression::Assignment { assignee, value } => {
self.analyze_expression(assignee, statement_position); self.analyze_expression(assignee, context)?;
self.analyze_expression(value, statement_position); self.analyze_expression(value, context)?;
} }
OperatorExpression::Comparison { left, right, .. } => { OperatorExpression::Comparison { left, right, .. } => {
self.analyze_expression(left, statement_position); self.analyze_expression(left, context)?;
self.analyze_expression(right, statement_position); self.analyze_expression(right, context)?;
} }
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee, modifier, .. assignee, modifier, ..
} => { } => {
self.analyze_expression(assignee, statement_position); self.analyze_expression(assignee, context)?;
self.analyze_expression(modifier, statement_position); self.analyze_expression(modifier, context)?;
let assignee_type_evaluation = let assignee_type_evaluation =
match assignee.type_evaluation(&self.abstract_tree.context) { match assignee.type_evaluation(&self.abstract_tree.context) {
@ -550,7 +526,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let modifier_type_evaluation = let modifier_type_evaluation =
@ -559,7 +535,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -577,21 +553,21 @@ impl<'a> Analyzer<'a> {
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: modifier.clone(), expression: modifier.clone(),
}); });
return; return Ok(());
} }
(None, _) => { (None, _) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: assignee.clone(), expression: assignee.clone(),
}); });
return; return Ok(());
} }
(_, None) => { (_, None) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: modifier.clone(), expression: modifier.clone(),
}); });
return; return Ok(());
} }
}; };
@ -605,14 +581,14 @@ impl<'a> Analyzer<'a> {
} }
OperatorExpression::ErrorPropagation(_) => todo!(), OperatorExpression::ErrorPropagation(_) => todo!(),
OperatorExpression::Negation(expression) => { OperatorExpression::Negation(expression) => {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
OperatorExpression::Not(expression) => { OperatorExpression::Not(expression) => {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
OperatorExpression::Math { left, right, .. } => { OperatorExpression::Math { left, right, .. } => {
self.analyze_expression(left, statement_position); self.analyze_expression(left, context)?;
self.analyze_expression(right, statement_position); self.analyze_expression(right, context)?;
let left_type_evaluation = let left_type_evaluation =
match left.type_evaluation(&self.abstract_tree.context) { match left.type_evaluation(&self.abstract_tree.context) {
@ -620,7 +596,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let right_type_evaluation = let right_type_evaluation =
@ -629,7 +605,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -647,21 +623,21 @@ impl<'a> Analyzer<'a> {
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: right.clone(), expression: right.clone(),
}); });
return; return Ok(());
} }
(None, _) => { (None, _) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: left.clone(), expression: left.clone(),
}); });
return; return Ok(());
} }
(_, None) => { (_, None) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: right.clone(), expression: right.clone(),
}); });
return; return Ok(());
} }
}; };
@ -709,8 +685,8 @@ impl<'a> Analyzer<'a> {
} }
} }
OperatorExpression::Logic { left, right, .. } => { OperatorExpression::Logic { left, right, .. } => {
self.analyze_expression(left, statement_position); self.analyze_expression(left, context)?;
self.analyze_expression(right, statement_position); self.analyze_expression(right, context)?;
let left_type_evaluation = let left_type_evaluation =
match left.type_evaluation(&self.abstract_tree.context) { match left.type_evaluation(&self.abstract_tree.context) {
@ -718,7 +694,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
let right_type_evaluation = let right_type_evaluation =
@ -727,7 +703,7 @@ impl<'a> Analyzer<'a> {
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -745,21 +721,21 @@ impl<'a> Analyzer<'a> {
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: right.clone(), expression: right.clone(),
}); });
return; return Ok(());
} }
(None, _) => { (None, _) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: left.clone(), expression: left.clone(),
}); });
return; return Ok(());
} }
(_, None) => { (_, None) => {
self.errors self.errors
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: right.clone(), expression: right.clone(),
}); });
return; return Ok(());
} }
}; };
@ -774,32 +750,18 @@ impl<'a> Analyzer<'a> {
}, },
Expression::Range(range_expression) => match range_expression.inner.as_ref() { Expression::Range(range_expression) => match range_expression.inner.as_ref() {
RangeExpression::Exclusive { start, end } => { RangeExpression::Exclusive { start, end } => {
self.analyze_expression(start, statement_position); self.analyze_expression(start, context)?;
self.analyze_expression(end, statement_position); self.analyze_expression(end, context)?;
} }
RangeExpression::Inclusive { start, end } => { RangeExpression::Inclusive { start, end } => {
self.analyze_expression(start, statement_position); self.analyze_expression(start, context)?;
self.analyze_expression(end, statement_position); self.analyze_expression(end, context)?;
} }
}, },
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Fields { name, fields } => { StructExpression::Fields { fields, .. } => {
let update_position = self
.abstract_tree
.context
.update_last_position(&name.inner, statement_position);
if let Err(error) = update_position {
self.errors.push(AnalysisError::ContextError {
error,
position: name.position,
});
return;
}
for (_, expression) in fields { for (_, expression) in fields {
self.analyze_expression(expression, statement_position); self.analyze_expression(expression, context)?;
} }
} }
}, },
@ -810,7 +772,7 @@ impl<'a> Analyzer<'a> {
Ok(evaluation) => evaluation, Ok(evaluation) => evaluation,
Err(ast_error) => { Err(ast_error) => {
self.errors.push(AnalysisError::AstError(ast_error)); self.errors.push(AnalysisError::AstError(ast_error));
return; return Ok(());
} }
}; };
@ -821,7 +783,7 @@ impl<'a> Analyzer<'a> {
.push(AnalysisError::ExpectedValueFromExpression { .push(AnalysisError::ExpectedValueFromExpression {
expression: tuple.clone(), expression: tuple.clone(),
}); });
return; return Ok(());
} }
}; };
@ -845,64 +807,69 @@ impl<'a> Analyzer<'a> {
}); });
} }
self.analyze_expression(tuple, statement_position); self.analyze_expression(tuple, context)?;
}
} }
} }
fn analyze_block(&mut self, block_expression: &BlockExpression) { Ok(())
}
fn analyze_block(
&mut self,
block_expression: &BlockExpression,
_context: &Context,
) -> Result<(), ContextError> {
let ast = match block_expression { let ast = match block_expression {
BlockExpression::Async(ast) => ast, BlockExpression::Async(ast) => ast,
BlockExpression::Sync(ast) => ast, BlockExpression::Sync(ast) => ast,
}; };
ast.context for statement in &ast.statements {
.assign_parent(self.abstract_tree.context.clone()); self.analyze_statement(statement, &ast.context)?;
let mut analyzer = Analyzer::new(ast);
analyzer.analyze();
self.errors.append(&mut analyzer.errors);
} }
fn analyze_if(&mut self, if_expression: &IfExpression, statement_position: Span) { Ok(())
}
fn analyze_if(
&mut self,
if_expression: &IfExpression,
context: &Context,
) -> Result<(), ContextError> {
match if_expression { match if_expression {
IfExpression::If { IfExpression::If {
condition, condition,
if_block, if_block,
} => { } => {
self.analyze_expression(condition, statement_position); self.analyze_expression(condition, context)?;
self.analyze_block(&if_block.inner); self.analyze_block(&if_block.inner, context)?;
} }
IfExpression::IfElse { IfExpression::IfElse {
condition, condition,
if_block, if_block,
r#else, r#else,
} => { } => {
self.analyze_expression(condition, statement_position); self.analyze_expression(condition, context)?;
self.analyze_block(&if_block.inner); self.analyze_block(&if_block.inner, context)?;
match r#else { match r#else {
ElseExpression::Block(block_expression) => { ElseExpression::Block(block_expression) => {
self.analyze_block(&block_expression.inner); self.analyze_block(&block_expression.inner, context)?;
} }
ElseExpression::If(if_expression) => { ElseExpression::If(if_expression) => {
self.analyze_if(&if_expression.inner, statement_position); self.analyze_if(&if_expression.inner, context)?;
} }
} }
} }
} }
Ok(())
} }
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum AnalysisError { pub enum AnalysisError {
AstError(AstError), AstError(AstError),
ContextError {
error: ContextError,
position: Span,
},
ExpectedFunction { ExpectedFunction {
actual: Type, actual: Type,
actual_expression: Expression, actual_expression: Expression,
@ -978,8 +945,8 @@ pub enum AnalysisError {
} }
impl From<AstError> for AnalysisError { impl From<AstError> for AnalysisError {
fn from(v: AstError) -> Self { fn from(error: AstError) -> Self {
Self::AstError(v) Self::AstError(error)
} }
} }
@ -987,7 +954,6 @@ impl AnalysisError {
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
AnalysisError::AstError(ast_error) => ast_error.position(), AnalysisError::AstError(ast_error) => ast_error.position(),
AnalysisError::ContextError { position, .. } => *position,
AnalysisError::ExpectedFunction { AnalysisError::ExpectedFunction {
actual_expression, .. actual_expression, ..
} => actual_expression.position(), } => actual_expression.position(),
@ -1024,7 +990,6 @@ impl Display for AnalysisError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
AnalysisError::AstError(ast_error) => write!(f, "{}", ast_error), AnalysisError::AstError(ast_error) => write!(f, "{}", ast_error),
AnalysisError::ContextError { error, .. } => write!(f, "{}", error),
AnalysisError::ExpectedFunction { AnalysisError::ExpectedFunction {
actual, actual,
actual_expression, actual_expression,

View File

@ -156,20 +156,13 @@ impl Context {
&self, &self,
identifier: Identifier, identifier: Identifier,
r#type: Type, r#type: Type,
position: Span,
) -> Result<(), ContextError> { ) -> Result<(), ContextError> {
log::trace!("Setting {identifier} to type {type} at {position:?}"); log::trace!("Setting {identifier} to type {type}.");
let mut associations = self.associations.write()?; let mut associations = self.associations.write()?;
let last_position = associations let last_position = associations
.get(&identifier) .get(&identifier)
.map(|(_, last_position)| { .map(|(_, last_position)| *last_position)
if last_position.1 > position.1 {
*last_position
} else {
position
}
})
.unwrap_or_default(); .unwrap_or_default();
associations.insert( associations.insert(
@ -283,18 +276,34 @@ impl Context {
identifier: &Identifier, identifier: &Identifier,
position: Span, position: Span,
) -> Result<bool, ContextError> { ) -> Result<bool, ContextError> {
if let Some((_, last_position)) = self.associations.write()?.get_mut(identifier) { let mut associations = self.associations.write()?;
*last_position = position;
if let Some((_, last_position)) = associations.get_mut(identifier) {
if position.1 > last_position.1 {
log::trace!("Updating {identifier}'s last position to {position:?}"); log::trace!("Updating {identifier}'s last position to {position:?}");
*last_position = position;
}
Ok(true) Ok(true)
} else if let Some(parent) = self.parent.read().unwrap().as_ref() {
parent.contains(identifier)
} else { } else {
let ancestor_contains = if let Some(parent) = self.parent.read().unwrap().as_ref() {
parent.contains(identifier)?
} else {
false
};
if ancestor_contains {
Ok(true)
} else {
log::trace!("Reserving {identifier} at {position:?}");
associations.insert(identifier.clone(), (ContextData::Reserved, position));
Ok(false) Ok(false)
} }
} }
}
/// Recovers the context from a poisoned state by recovering data from an error. /// Recovers the context from a poisoned state by recovering data from an error.
/// ///
@ -327,6 +336,7 @@ pub enum ContextData {
ConstructorType(StructType), ConstructorType(StructType),
VariableValue(Value), VariableValue(Value),
VariableType(Type), VariableType(Type),
Reserved,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -2,12 +2,13 @@
use annotate_snippets::{Level, Renderer, Snippet}; use annotate_snippets::{Level, Renderer, Snippet};
use std::fmt::Display; use std::fmt::Display;
use crate::{ast::Span, AnalysisError, LexError, ParseError, RuntimeError}; use crate::{ast::Span, AnalysisError, ContextError, LexError, ParseError, RuntimeError};
/// An error that occurred during the execution of the Dust language and its /// An error that occurred during the execution of the Dust language and its
/// corresponding source code. /// corresponding source code.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum DustError<'src> { pub enum DustError<'src> {
ContextError(ContextError),
Runtime { Runtime {
runtime_error: RuntimeError, runtime_error: RuntimeError,
source: &'src str, source: &'src str,
@ -26,6 +27,12 @@ pub enum DustError<'src> {
}, },
} }
impl<'src> From<ContextError> for DustError<'src> {
fn from(error: ContextError) -> Self {
Self::ContextError(error)
}
}
impl<'src> DustError<'src> { impl<'src> DustError<'src> {
pub fn runtime(runtime_error: RuntimeError, source: &'src str) -> Self { pub fn runtime(runtime_error: RuntimeError, source: &'src str) -> Self {
DustError::Runtime { DustError::Runtime {
@ -54,6 +61,7 @@ impl<'src> DustError<'src> {
pub fn title(&self) -> &'static str { pub fn title(&self) -> &'static str {
match self { match self {
DustError::ContextError(_) => "Context error",
DustError::Runtime { .. } => "Runtime error", DustError::Runtime { .. } => "Runtime error",
DustError::Analysis { .. } => "Analysis error", DustError::Analysis { .. } => "Analysis error",
DustError::Parse { .. } => "Parse error", DustError::Parse { .. } => "Parse error",
@ -63,6 +71,7 @@ impl<'src> DustError<'src> {
pub fn source(&self) -> &'src str { pub fn source(&self) -> &'src str {
match self { match self {
DustError::ContextError(_) => "",
DustError::Runtime { source, .. } => source, DustError::Runtime { source, .. } => source,
DustError::Analysis { source, .. } => source, DustError::Analysis { source, .. } => source,
DustError::Parse { source, .. } => source, DustError::Parse { source, .. } => source,
@ -72,6 +81,7 @@ impl<'src> DustError<'src> {
pub fn error_data(&self) -> Vec<(&'static str, Span, String)> { pub fn error_data(&self) -> Vec<(&'static str, Span, String)> {
match self { match self {
DustError::ContextError(_) => vec![],
DustError::Runtime { runtime_error, .. } => vec![( DustError::Runtime { runtime_error, .. } => vec![(
"Runtime error", "Runtime error",
runtime_error.position(), runtime_error.position(),
@ -114,6 +124,7 @@ impl<'src> DustError<'src> {
impl Display for DustError<'_> { impl Display for DustError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
DustError::ContextError(context_error) => write!(f, "{context_error}"),
DustError::Runtime { runtime_error, .. } => write!(f, "{runtime_error}"), DustError::Runtime { runtime_error, .. } => write!(f, "{runtime_error}"),
DustError::Analysis { DustError::Analysis {
analysis_errors, .. analysis_errors, ..

View File

@ -11,8 +11,8 @@ use std::{
}; };
use crate::{ use crate::{
ast::*, core_library, Context, DustError, Identifier, LexError, Lexer, Token, TokenKind, ast::*, core_library, Context, ContextError, DustError, Identifier, LexError, Lexer, Token,
TokenOwned, Type, TokenKind, TokenOwned, Type,
}; };
/// Parses the input into an abstract syntax tree. /// Parses the input into an abstract syntax tree.
@ -40,34 +40,27 @@ use crate::{
pub fn parse(source: &str) -> Result<AbstractSyntaxTree, DustError> { pub fn parse(source: &str) -> Result<AbstractSyntaxTree, DustError> {
let mut tree = AbstractSyntaxTree::new(); let mut tree = AbstractSyntaxTree::new();
parse_into(source, &mut tree)?; tree.context.assign_parent(core_library().clone());
Ok(tree)
}
pub fn parse_into<'src>(
source: &'src str,
tree: &mut AbstractSyntaxTree,
) -> Result<(), DustError<'src>> {
let lexer = Lexer::new(source); let lexer = Lexer::new(source);
let mut parser = Parser::new(lexer); let mut parser = Parser::new(lexer);
loop { loop {
let node = parser let statement = parser
.parse_statement() .parse_statement(&tree.context)
.map_err(|parse_error| DustError::Parse { .map_err(|parse_error| DustError::Parse {
parse_error, parse_error,
source, source,
})?; })?;
tree.statements.push_back(node); tree.statements.push_back(statement);
if let Token::Eof = parser.current_token { if let Token::Eof = parser.current_token {
break; break;
} }
} }
Ok(()) Ok(tree)
} }
/// Low-level tool for parsing the input a statement at a time. /// Low-level tool for parsing the input a statement at a time.
@ -99,7 +92,6 @@ pub struct Parser<'src> {
current_token: Token<'src>, current_token: Token<'src>,
current_position: Span, current_position: Span,
mode: ParserMode, mode: ParserMode,
context: Context,
} }
impl<'src> Parser<'src> { impl<'src> Parser<'src> {
@ -111,7 +103,6 @@ impl<'src> Parser<'src> {
current_token, current_token,
current_position, current_position,
mode: ParserMode::Normal, mode: ParserMode::Normal,
context: core_library().create_child(),
} }
} }
@ -119,7 +110,7 @@ impl<'src> Parser<'src> {
matches!(self.current_token, Token::Eof) matches!(self.current_token, Token::Eof)
} }
pub fn parse_statement(&mut self) -> Result<Statement, ParseError> { pub fn parse_statement(&mut self, context: &Context) -> Result<Statement, ParseError> {
let start_position = self.current_position; let start_position = self.current_position;
if let Token::Let = self.current_token { if let Token::Let = self.current_token {
@ -135,7 +126,7 @@ impl<'src> Parser<'src> {
false false
}; };
let identifier = self.parse_identifier()?; let identifier = self.parse_identifier(context)?;
if let Token::Equal = self.current_token { if let Token::Equal = self.current_token {
self.next_token()?; self.next_token()?;
@ -147,7 +138,7 @@ impl<'src> Parser<'src> {
}); });
} }
let value = self.parse_expression(0)?; let value = self.parse_expression(0, context)?;
let end = if let Token::Semicolon = self.current_token { let end = if let Token::Semicolon = self.current_token {
let end = self.current_position.1; let end = self.current_position.1;
@ -174,7 +165,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let name = if let Token::Identifier(_) = self.current_token { let name = if let Token::Identifier(_) = self.current_token {
self.parse_identifier()? self.parse_identifier(context)?
} else { } else {
return Err(ParseError::ExpectedToken { return Err(ParseError::ExpectedToken {
expected: TokenKind::Identifier, expected: TokenKind::Identifier,
@ -203,10 +194,6 @@ impl<'src> Parser<'src> {
if let Token::RightParenthesis = self.current_token { if let Token::RightParenthesis = self.current_token {
self.next_token()?; self.next_token()?;
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
break; break;
} }
@ -223,6 +210,10 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
return if types.is_empty() { return if types.is_empty() {
Ok(Statement::struct_definition( Ok(Statement::struct_definition(
StructDefinition::Unit { name }, StructDefinition::Unit { name },
@ -245,14 +236,10 @@ impl<'src> Parser<'src> {
if let Token::RightCurlyBrace = self.current_token { if let Token::RightCurlyBrace = self.current_token {
self.next_token()?; self.next_token()?;
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
break; break;
} }
let field_name = self.parse_identifier()?; let field_name = self.parse_identifier(context)?;
if let Token::Colon = self.current_token { if let Token::Colon = self.current_token {
self.next_token()?; self.next_token()?;
@ -277,6 +264,10 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
return if fields.is_empty() { return if fields.is_empty() {
Ok(Statement::struct_definition( Ok(Statement::struct_definition(
StructDefinition::Unit { name }, StructDefinition::Unit { name },
@ -301,7 +292,7 @@ impl<'src> Parser<'src> {
}); });
} }
let expression = self.parse_expression(0)?; let expression = self.parse_expression(0, context)?;
if let Token::Semicolon = self.current_token { if let Token::Semicolon = self.current_token {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
@ -325,19 +316,23 @@ impl<'src> Parser<'src> {
Ok(()) Ok(())
} }
fn parse_expression(&mut self, mut precedence: u8) -> Result<Expression, ParseError> { fn parse_expression(
&mut self,
mut precedence: u8,
context: &Context,
) -> Result<Expression, ParseError> {
// Parse a statement starting from the current node. // Parse a statement starting from the current node.
let mut left = if self.current_token.is_prefix() { let mut left = if self.current_token.is_prefix() {
self.parse_prefix()? self.parse_prefix(context)?
} else { } else {
self.parse_primary()? self.parse_primary(context)?
}; };
// While the current token has a higher precedence than the given precedence // While the current token has a higher precedence than the given precedence
while precedence < self.current_token.precedence() { while precedence < self.current_token.precedence() {
// Give precedence to postfix operations // Give precedence to postfix operations
left = if self.current_token.is_postfix() { left = if self.current_token.is_postfix() {
let statement = self.parse_postfix(left)?; let statement = self.parse_postfix(left, context)?;
precedence = self.current_token.precedence(); precedence = self.current_token.precedence();
@ -345,14 +340,14 @@ impl<'src> Parser<'src> {
statement statement
} else { } else {
// Replace the left-hand side with the infix operation // Replace the left-hand side with the infix operation
self.parse_infix(left)? self.parse_infix(left, context)?
}; };
} }
Ok(left) Ok(left)
} }
fn parse_prefix(&mut self) -> Result<Expression, ParseError> { fn parse_prefix(&mut self, context: &Context) -> Result<Expression, ParseError> {
log::trace!("Parsing {} as prefix operator", self.current_token); log::trace!("Parsing {} as prefix operator", self.current_token);
let operator_start = self.current_position.0; let operator_start = self.current_position.0;
@ -361,7 +356,7 @@ impl<'src> Parser<'src> {
Token::Bang => { Token::Bang => {
self.next_token()?; self.next_token()?;
let operand = self.parse_expression(0)?; let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1); let position = (operator_start, self.current_position.1);
Ok(Expression::not(operand, position)) Ok(Expression::not(operand, position))
@ -369,7 +364,7 @@ impl<'src> Parser<'src> {
Token::Minus => { Token::Minus => {
self.next_token()?; self.next_token()?;
let operand = self.parse_expression(0)?; let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1); let position = (operator_start, self.current_position.1);
Ok(Expression::negation(operand, position)) Ok(Expression::negation(operand, position))
@ -377,7 +372,7 @@ impl<'src> Parser<'src> {
Token::Star => { Token::Star => {
self.next_token()?; self.next_token()?;
let operand = self.parse_expression(0)?; let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1); let position = (operator_start, self.current_position.1);
Ok(Expression::dereference(operand, position)) Ok(Expression::dereference(operand, position))
@ -390,14 +385,14 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_primary(&mut self) -> Result<Expression, ParseError> { fn parse_primary(&mut self, context: &Context) -> Result<Expression, ParseError> {
log::trace!("Parsing {} as primary", self.current_token); log::trace!("Parsing {} as primary", self.current_token);
let start_position = self.current_position; let start_position = self.current_position;
match self.current_token { match self.current_token {
Token::Async => { Token::Async => {
let block = self.parse_block()?; let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1); let position = (start_position.0, block.position.1);
Ok(Expression::block(block.inner, position)) Ok(Expression::block(block.inner, position))
@ -422,7 +417,7 @@ impl<'src> Parser<'src> {
// Do not consume the semicolon, allowing it to nullify the expression // Do not consume the semicolon, allowing it to nullify the expression
(None, break_end) (None, break_end)
} else if let Ok(expression) = self.parse_expression(0) { } else if let Ok(expression) = self.parse_expression(0, context) {
let end = expression.position().1; let end = expression.position().1;
(Some(expression), end) (Some(expression), end)
@ -460,13 +455,15 @@ impl<'src> Parser<'src> {
let identifier = Identifier::new(text); let identifier = Identifier::new(text);
if let ParserMode::Condition = self.mode { if let ParserMode::Condition = self.mode {
context.update_last_position(&identifier, start_position)?;
return Ok(Expression::identifier(identifier, start_position)); return Ok(Expression::identifier(identifier, start_position));
} }
if let Token::LeftCurlyBrace = self.current_token { if let Token::LeftCurlyBrace = self.current_token {
self.next_token()?; self.next_token()?;
let name = Node::new(identifier, start_position); let name = Node::new(identifier.clone(), start_position);
let mut fields = Vec::new(); let mut fields = Vec::new();
loop { loop {
@ -476,7 +473,7 @@ impl<'src> Parser<'src> {
break; break;
} }
let field_name = self.parse_identifier()?; let field_name = self.parse_identifier(context)?;
if let Token::Colon = self.current_token { if let Token::Colon = self.current_token {
self.next_token()?; self.next_token()?;
@ -488,7 +485,7 @@ impl<'src> Parser<'src> {
}); });
} }
let field_value = self.parse_expression(0)?; let field_value = self.parse_expression(0, context)?;
fields.push((field_name, field_value)); fields.push((field_name, field_value));
@ -499,12 +496,16 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
context.update_last_position(&identifier, position)?;
return Ok(Expression::r#struct( return Ok(Expression::r#struct(
StructExpression::Fields { name, fields }, StructExpression::Fields { name, fields },
position, position,
)); ));
} }
context.update_last_position(&identifier, start_position)?;
Ok(Expression::identifier(identifier, start_position)) Ok(Expression::identifier(identifier, start_position))
} }
Token::Integer(text) => { Token::Integer(text) => {
@ -520,7 +521,7 @@ impl<'src> Parser<'src> {
Token::If => { Token::If => {
self.next_token()?; self.next_token()?;
let r#if = self.parse_if()?; let r#if = self.parse_if(context)?;
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
Ok(Expression::r#if(r#if, position)) Ok(Expression::r#if(r#if, position))
@ -531,14 +532,14 @@ impl<'src> Parser<'src> {
Ok(Expression::literal(text.to_string(), start_position)) Ok(Expression::literal(text.to_string(), start_position))
} }
Token::LeftCurlyBrace => { Token::LeftCurlyBrace => {
let block_node = self.parse_block()?; let block_node = self.parse_block(context)?;
Ok(Expression::block(block_node.inner, block_node.position)) Ok(Expression::block(block_node.inner, block_node.position))
} }
Token::LeftParenthesis => { Token::LeftParenthesis => {
self.next_token()?; self.next_token()?;
let node = self.parse_expression(0)?; let node = self.parse_expression(0, context)?;
if let Token::RightParenthesis = self.current_token { if let Token::RightParenthesis = self.current_token {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
@ -565,12 +566,12 @@ impl<'src> Parser<'src> {
return Ok(Expression::list(Vec::new(), position)); return Ok(Expression::list(Vec::new(), position));
} }
let first_expression = self.parse_expression(0)?; let first_expression = self.parse_expression(0, context)?;
if let Token::Semicolon = self.current_token { if let Token::Semicolon = self.current_token {
self.next_token()?; self.next_token()?;
let repeat_operand = self.parse_expression(0)?; let repeat_operand = self.parse_expression(0, context)?;
if let Token::RightSquareBrace = self.current_token { if let Token::RightSquareBrace = self.current_token {
let position = (start_position.0, self.current_position.1); let position = (start_position.0, self.current_position.1);
@ -608,7 +609,7 @@ impl<'src> Parser<'src> {
continue; continue;
} }
let expression = self.parse_expression(0)?; let expression = self.parse_expression(0, context)?;
expressions.push(expression); expressions.push(expression);
} }
@ -616,7 +617,7 @@ impl<'src> Parser<'src> {
Token::Loop => { Token::Loop => {
self.next_token()?; self.next_token()?;
let block = self.parse_block()?; let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1); let position = (start_position.0, block.position.1);
Ok(Expression::infinite_loop(block, position)) Ok(Expression::infinite_loop(block, position))
@ -645,7 +646,7 @@ impl<'src> Parser<'src> {
return Ok(Expression::map(fields, position)); return Ok(Expression::map(fields, position));
} }
let field_name = self.parse_identifier()?; let field_name = self.parse_identifier(context)?;
if let Token::Equal = self.current_token { if let Token::Equal = self.current_token {
self.next_token()?; self.next_token()?;
@ -657,7 +658,7 @@ impl<'src> Parser<'src> {
}); });
} }
let field_value = self.parse_expression(0)?; let field_value = self.parse_expression(0, context)?;
fields.push((field_name, field_value)); fields.push((field_name, field_value));
@ -669,8 +670,8 @@ impl<'src> Parser<'src> {
Token::While => { Token::While => {
self.next_token()?; self.next_token()?;
let condition = self.parse_expression(0)?; let condition = self.parse_expression(0, context)?;
let block = self.parse_block()?; let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1); let position = (start_position.0, block.position.1);
Ok(Expression::while_loop(condition, block, position)) Ok(Expression::while_loop(condition, block, position))
@ -695,7 +696,11 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_infix(&mut self, left: Expression) -> Result<Expression, ParseError> { fn parse_infix(
&mut self,
left: Expression,
context: &Context,
) -> Result<Expression, ParseError> {
log::trace!("Parsing {} as infix operator", self.current_token); log::trace!("Parsing {} as infix operator", self.current_token);
let operator_precedence = self.current_token.precedence() let operator_precedence = self.current_token.precedence()
@ -709,7 +714,7 @@ impl<'src> Parser<'src> {
if let Token::Equal = &self.current_token { if let Token::Equal = &self.current_token {
self.next_token()?; self.next_token()?;
let value = self.parse_expression(operator_precedence)?; let value = self.parse_expression(operator_precedence, context)?;
let position = (left_start, value.position().1); let position = (left_start, value.position().1);
return Ok(Expression::assignment(left, value, position)); return Ok(Expression::assignment(left, value, position));
@ -725,7 +730,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let value = self.parse_expression(operator_precedence)?; let value = self.parse_expression(operator_precedence, context)?;
let position = (left_start, value.position().1); let position = (left_start, value.position().1);
return Ok(Expression::operator( return Ok(Expression::operator(
@ -741,7 +746,7 @@ impl<'src> Parser<'src> {
if let Token::DoubleDot = &self.current_token { if let Token::DoubleDot = &self.current_token {
self.next_token()?; self.next_token()?;
let end = self.parse_expression(operator_precedence)?; let end = self.parse_expression(operator_precedence, context)?;
let position = (left_start, end.position().1); let position = (left_start, end.position().1);
return Ok(Expression::exclusive_range(left, end, position)); return Ok(Expression::exclusive_range(left, end, position));
@ -761,7 +766,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let right = self.parse_expression(operator_precedence)?; let right = self.parse_expression(operator_precedence, context)?;
let position = (left_start, right.position().1); let position = (left_start, right.position().1);
return Ok(Expression::operator( return Ok(Expression::operator(
@ -798,7 +803,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let right = self.parse_expression(operator_precedence)?; let right = self.parse_expression(operator_precedence, context)?;
let position = (left_start, right.position().1); let position = (left_start, right.position().1);
return Ok(Expression::operator( return Ok(Expression::operator(
@ -824,7 +829,7 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let right = self.parse_expression(operator_precedence)?; let right = self.parse_expression(operator_precedence, context)?;
let position = (left_start, right.position().1); let position = (left_start, right.position().1);
Ok(Expression::operator( Ok(Expression::operator(
@ -837,7 +842,11 @@ impl<'src> Parser<'src> {
)) ))
} }
fn parse_postfix(&mut self, left: Expression) -> Result<Expression, ParseError> { fn parse_postfix(
&mut self,
left: Expression,
context: &Context,
) -> Result<Expression, ParseError> {
log::trace!("Parsing {} as postfix operator", self.current_token); log::trace!("Parsing {} as postfix operator", self.current_token);
let expression = match &self.current_token { let expression = match &self.current_token {
@ -856,7 +865,7 @@ impl<'src> Parser<'src> {
Expression::tuple_access(left, index_node, position) Expression::tuple_access(left, index_node, position)
} else { } else {
let field = self.parse_identifier()?; let field = self.parse_identifier(context)?;
let position = (left.position().0, field.position.1); let position = (left.position().0, field.position.1);
Expression::field_access(left, field, position) Expression::field_access(left, field, position)
@ -868,7 +877,7 @@ impl<'src> Parser<'src> {
let mut arguments = Vec::new(); let mut arguments = Vec::new();
while self.current_token != Token::RightParenthesis { while self.current_token != Token::RightParenthesis {
let argument = self.parse_expression(0)?; let argument = self.parse_expression(0, context)?;
arguments.push(argument); arguments.push(argument);
@ -879,16 +888,16 @@ impl<'src> Parser<'src> {
} }
} }
self.next_token()?;
let position = (left.position().0, self.current_position.1); let position = (left.position().0, self.current_position.1);
self.next_token()?;
Expression::call(left, arguments, position) Expression::call(left, arguments, position)
} }
Token::LeftSquareBrace => { Token::LeftSquareBrace => {
self.next_token()?; self.next_token()?;
let index = self.parse_expression(0)?; let index = self.parse_expression(0, context)?;
let operator_end = if let Token::RightSquareBrace = self.current_token { let operator_end = if let Token::RightSquareBrace = self.current_token {
let end = self.current_position.1; let end = self.current_position.1;
@ -922,22 +931,22 @@ impl<'src> Parser<'src> {
}; };
if self.current_token.is_postfix() { if self.current_token.is_postfix() {
self.parse_postfix(expression) self.parse_postfix(expression, context)
} else { } else {
Ok(expression) Ok(expression)
} }
} }
fn parse_if(&mut self) -> Result<IfExpression, ParseError> { fn parse_if(&mut self, context: &Context) -> Result<IfExpression, ParseError> {
// Assume that the "if" token has already been consumed // Assume that the "if" token has already been consumed
self.mode = ParserMode::Condition; self.mode = ParserMode::Condition;
let condition = self.parse_expression(0)?; let condition = self.parse_expression(0, context)?;
self.mode = ParserMode::Normal; self.mode = ParserMode::Normal;
let if_block = self.parse_block()?; let if_block = self.parse_block(context)?;
if let Token::Else = self.current_token { if let Token::Else = self.current_token {
self.next_token()?; self.next_token()?;
@ -947,7 +956,7 @@ impl<'src> Parser<'src> {
if let Token::If = self.current_token { if let Token::If = self.current_token {
self.next_token()?; self.next_token()?;
let if_expression = self.parse_if()?; let if_expression = self.parse_if(context)?;
let position = (if_keyword_start, self.current_position.1); let position = (if_keyword_start, self.current_position.1);
Ok(IfExpression::IfElse { Ok(IfExpression::IfElse {
@ -956,7 +965,7 @@ impl<'src> Parser<'src> {
r#else: ElseExpression::If(Node::new(Box::new(if_expression), position)), r#else: ElseExpression::If(Node::new(Box::new(if_expression), position)),
}) })
} else { } else {
let else_block = self.parse_block()?; let else_block = self.parse_block(context)?;
Ok(IfExpression::IfElse { Ok(IfExpression::IfElse {
condition, condition,
@ -972,13 +981,16 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_identifier(&mut self) -> Result<Node<Identifier>, ParseError> { fn parse_identifier(&mut self, context: &Context) -> Result<Node<Identifier>, ParseError> {
if let Token::Identifier(text) = self.current_token { if let Token::Identifier(text) = self.current_token {
let position = self.current_position; let position = self.current_position;
let identifier = Identifier::new(text);
self.next_token()?; self.next_token()?;
Ok(Node::new(Identifier::new(text), position)) context.update_last_position(&identifier, position)?;
Ok(Node::new(identifier, position))
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
expected: TokenKind::Identifier, expected: TokenKind::Identifier,
@ -988,7 +1000,7 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_block(&mut self) -> Result<Node<BlockExpression>, ParseError> { fn parse_block(&mut self, context: &Context) -> Result<Node<BlockExpression>, ParseError> {
let left_start = self.current_position.0; let left_start = self.current_position.0;
let is_async = if let Token::Async = self.current_token { let is_async = if let Token::Async = self.current_token {
self.next_token()?; self.next_token()?;
@ -1008,7 +1020,10 @@ impl<'src> Parser<'src> {
}); });
} }
let mut statements = VecDeque::new(); let mut ast = AbstractSyntaxTree {
statements: VecDeque::new(),
context: context.create_child(),
};
loop { loop {
if let Token::RightCurlyBrace = self.current_token { if let Token::RightCurlyBrace = self.current_token {
@ -1016,11 +1031,6 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
let ast = AbstractSyntaxTree {
statements,
context: self.context.create_child(),
};
return if is_async { return if is_async {
Ok(Node::new(BlockExpression::Async(ast), position)) Ok(Node::new(BlockExpression::Async(ast), position))
} else { } else {
@ -1028,9 +1038,9 @@ impl<'src> Parser<'src> {
}; };
} }
let statement = self.parse_statement()?; let statement = self.parse_statement(&ast.context)?;
statements.push_back(statement); ast.statements.push_back(statement);
} }
} }
@ -1063,6 +1073,7 @@ pub enum ParserMode {
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ParseError { pub enum ParseError {
ContextError(ContextError),
Boolean { Boolean {
error: ParseBoolError, error: ParseBoolError,
position: Span, position: Span,
@ -1105,6 +1116,12 @@ pub enum ParseError {
}, },
} }
impl From<ContextError> for ParseError {
fn from(error: ContextError) -> Self {
Self::ContextError(error)
}
}
impl From<LexError> for ParseError { impl From<LexError> for ParseError {
fn from(v: LexError) -> Self { fn from(v: LexError) -> Self {
Self::Lex(v) Self::Lex(v)
@ -1115,6 +1132,7 @@ impl ParseError {
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
ParseError::Boolean { position, .. } => *position, ParseError::Boolean { position, .. } => *position,
ParseError::ContextError { .. } => (0, 0),
ParseError::ExpectedAssignment { actual } => actual.position(), ParseError::ExpectedAssignment { actual } => actual.position(),
ParseError::ExpectedExpression { actual } => actual.position(), ParseError::ExpectedExpression { actual } => actual.position(),
ParseError::ExpectedIdentifierNode { actual } => actual.position(), ParseError::ExpectedIdentifierNode { actual } => actual.position(),
@ -1133,6 +1151,7 @@ impl Display for ParseError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Self::Boolean { error, .. } => write!(f, "{}", error), Self::Boolean { error, .. } => write!(f, "{}", error),
Self::ContextError(error) => write!(f, "{}", error),
Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"), Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"),
Self::ExpectedExpression { .. } => write!(f, "Expected expression"), Self::ExpectedExpression { .. } => write!(f, "Expected expression"),
Self::ExpectedIdentifierNode { actual } => { Self::ExpectedIdentifierNode { actual } => {
@ -1398,7 +1417,7 @@ mod tests {
Expression::literal(42, (4, 6)), Expression::literal(42, (4, 6)),
Expression::literal("bar".to_string(), (8, 13)), Expression::literal("bar".to_string(), (8, 13)),
], ],
(0, 15) (0, 14)
), ),
Node::new(0, (15, 16)), Node::new(0, (15, 16)),
(0, 16) (0, 16)

View File

@ -40,7 +40,7 @@ pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let abstract_syntax_tree = parse(source)?; let abstract_syntax_tree = parse(source)?;
let mut analyzer = Analyzer::new(&abstract_syntax_tree); let mut analyzer = Analyzer::new(&abstract_syntax_tree);
analyzer.analyze(); analyzer.analyze()?;
if !analyzer.errors.is_empty() { if !analyzer.errors.is_empty() {
return Err(DustError::Analysis { return Err(DustError::Analysis {
@ -58,11 +58,7 @@ pub fn run(source: &str) -> Result<Option<Value>, DustError> {
/// Dust virtual machine. /// Dust virtual machine.
/// ///
/// **Warning**: Do not run an AbstractSyntaxTree that has not been analyzed *with the same /// See the `run` function for an example of how to parse, analyze and run code.
/// context*. Use the `run` or `run_with_context` functions to make sure the program is analyzed
/// before running it.
///
/// See the `run_with_context` function for an example of how to use the Analyzer and the VM.
pub struct Vm; pub struct Vm;
impl Vm { impl Vm {
@ -70,7 +66,11 @@ impl Vm {
let mut previous_evaluation = Evaluation::Return(None); let mut previous_evaluation = Evaluation::Return(None);
while let Some(statement) = tree.statements.pop_front() { while let Some(statement) = tree.statements.pop_front() {
let statement_end = statement.position().1;
previous_evaluation = self.run_statement(statement, &tree.context, true)?; previous_evaluation = self.run_statement(statement, &tree.context, true)?;
tree.context.collect_garbage(statement_end).unwrap();
} }
match previous_evaluation { match previous_evaluation {
@ -193,12 +193,6 @@ impl Vm {
} }
}; };
if collect_garbage {
context
.collect_garbage(position.1)
.map_err(|error| RuntimeError::ContextError { error, position })?;
}
result.map_err(|error| RuntimeError::Statement { result.map_err(|error| RuntimeError::Statement {
error: Box::new(error), error: Box::new(error),
position, position,
@ -1020,7 +1014,7 @@ impl Vm {
fn run_block( fn run_block(
&self, &self,
block: BlockExpression, block: BlockExpression,
context: &Context, _context: &Context,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
match block { match block {
@ -1424,7 +1418,7 @@ impl Display for RuntimeError {
mod tests { mod tests {
use std::collections::HashMap; use std::collections::HashMap;
use crate::{AnalysisError, Struct}; use crate::Struct;
use super::*; use super::*;
@ -1480,50 +1474,6 @@ mod tests {
assert_eq!(run(source), Ok(Some(Value::integer(42)))); assert_eq!(run(source), Ok(Some(Value::integer(42))));
} }
#[test]
fn block_scope_captures_parent() {
let source = "let x = 42; { x }";
assert_eq!(run(source), Ok(Some(Value::integer(42))));
}
#[test]
fn block_scope_does_not_capture_child() {
let source = "{ let x = 42; } x";
assert_eq!(
run(source),
Err(DustError::analysis(
[AnalysisError::UndefinedVariable {
identifier: Node::new(Identifier::new("x"), (16, 17))
}],
source
))
);
}
#[test]
fn block_scope_does_not_capture_sibling() {
let source = "{ let x = 42; } { x }";
assert_eq!(
run(source),
Err(DustError::analysis(
[AnalysisError::UndefinedVariable {
identifier: Node::new(Identifier::new("x"), (18, 19))
}],
source
))
);
}
#[test]
fn block_scope_does_not_pollute_parent() {
let source = "let x = 42; { let x = \"foo\"; let x = \"bar\"; } x";
assert_eq!(run(source), Ok(Some(Value::integer(42))));
}
#[test] #[test]
fn character() { fn character() {
let input = "'a'"; let input = "'a'";

45
dust-lang/tests/scopes.rs Normal file
View File

@ -0,0 +1,45 @@
use dust_lang::*;
#[test]
fn block_scope_captures_parent() {
let source = "let x = 42; { x }";
assert_eq!(run(source), Ok(Some(Value::integer(42))));
}
#[test]
fn block_scope_does_not_capture_child() {
let source = "{ let x = 42; } x";
assert_eq!(
run(source),
Err(DustError::analysis(
[AnalysisError::UndefinedVariable {
identifier: Node::new(Identifier::new("x"), (16, 17))
}],
source
))
);
}
#[test]
fn block_scope_does_not_capture_sibling() {
let source = "{ let x = 42; } { x }";
assert_eq!(
run(source),
Err(DustError::analysis(
[AnalysisError::UndefinedVariable {
identifier: Node::new(Identifier::new("x"), (18, 19))
}],
source
))
);
}
#[test]
fn block_scope_does_not_pollute_parent() {
let source = "let x = 42; { let x = \"foo\"; let x = \"bar\"; } x";
assert_eq!(run(source), Ok(Some(Value::integer(42))));
}