1
0

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

View File

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

View File

@ -2,12 +2,13 @@
use annotate_snippets::{Level, Renderer, Snippet};
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
/// corresponding source code.
#[derive(Debug, Clone, PartialEq)]
pub enum DustError<'src> {
ContextError(ContextError),
Runtime {
runtime_error: RuntimeError,
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> {
pub fn runtime(runtime_error: RuntimeError, source: &'src str) -> Self {
DustError::Runtime {
@ -54,6 +61,7 @@ impl<'src> DustError<'src> {
pub fn title(&self) -> &'static str {
match self {
DustError::ContextError(_) => "Context error",
DustError::Runtime { .. } => "Runtime error",
DustError::Analysis { .. } => "Analysis error",
DustError::Parse { .. } => "Parse error",
@ -63,6 +71,7 @@ impl<'src> DustError<'src> {
pub fn source(&self) -> &'src str {
match self {
DustError::ContextError(_) => "",
DustError::Runtime { source, .. } => source,
DustError::Analysis { source, .. } => source,
DustError::Parse { source, .. } => source,
@ -72,6 +81,7 @@ impl<'src> DustError<'src> {
pub fn error_data(&self) -> Vec<(&'static str, Span, String)> {
match self {
DustError::ContextError(_) => vec![],
DustError::Runtime { runtime_error, .. } => vec![(
"Runtime error",
runtime_error.position(),
@ -114,6 +124,7 @@ impl<'src> DustError<'src> {
impl Display for DustError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DustError::ContextError(context_error) => write!(f, "{context_error}"),
DustError::Runtime { runtime_error, .. } => write!(f, "{runtime_error}"),
DustError::Analysis {
analysis_errors, ..

View File

@ -11,8 +11,8 @@ use std::{
};
use crate::{
ast::*, core_library, Context, DustError, Identifier, LexError, Lexer, Token, TokenKind,
TokenOwned, Type,
ast::*, core_library, Context, ContextError, DustError, Identifier, LexError, Lexer, Token,
TokenKind, TokenOwned, Type,
};
/// Parses the input into an abstract syntax tree.
@ -40,34 +40,27 @@ use crate::{
pub fn parse(source: &str) -> Result<AbstractSyntaxTree, DustError> {
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 mut parser = Parser::new(lexer);
loop {
let node = parser
.parse_statement()
let statement = parser
.parse_statement(&tree.context)
.map_err(|parse_error| DustError::Parse {
parse_error,
source,
})?;
tree.statements.push_back(node);
tree.statements.push_back(statement);
if let Token::Eof = parser.current_token {
break;
}
}
Ok(())
Ok(tree)
}
/// 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_position: Span,
mode: ParserMode,
context: Context,
}
impl<'src> Parser<'src> {
@ -111,7 +103,6 @@ impl<'src> Parser<'src> {
current_token,
current_position,
mode: ParserMode::Normal,
context: core_library().create_child(),
}
}
@ -119,7 +110,7 @@ impl<'src> Parser<'src> {
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;
if let Token::Let = self.current_token {
@ -135,7 +126,7 @@ impl<'src> Parser<'src> {
false
};
let identifier = self.parse_identifier()?;
let identifier = self.parse_identifier(context)?;
if let Token::Equal = self.current_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 = self.current_position.1;
@ -174,7 +165,7 @@ impl<'src> Parser<'src> {
self.next_token()?;
let name = if let Token::Identifier(_) = self.current_token {
self.parse_identifier()?
self.parse_identifier(context)?
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::Identifier,
@ -203,10 +194,6 @@ impl<'src> Parser<'src> {
if let Token::RightParenthesis = self.current_token {
self.next_token()?;
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
break;
}
@ -223,6 +210,10 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1);
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
return if types.is_empty() {
Ok(Statement::struct_definition(
StructDefinition::Unit { name },
@ -245,14 +236,10 @@ impl<'src> Parser<'src> {
if let Token::RightCurlyBrace = self.current_token {
self.next_token()?;
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
break;
}
let field_name = self.parse_identifier()?;
let field_name = self.parse_identifier(context)?;
if let Token::Colon = self.current_token {
self.next_token()?;
@ -277,6 +264,10 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1);
if let Token::Semicolon = self.current_token {
self.next_token()?;
}
return if fields.is_empty() {
Ok(Statement::struct_definition(
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 {
let position = (start_position.0, self.current_position.1);
@ -325,19 +316,23 @@ impl<'src> Parser<'src> {
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.
let mut left = if self.current_token.is_prefix() {
self.parse_prefix()?
self.parse_prefix(context)?
} else {
self.parse_primary()?
self.parse_primary(context)?
};
// While the current token has a higher precedence than the given precedence
while precedence < self.current_token.precedence() {
// Give precedence to postfix operations
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();
@ -345,14 +340,14 @@ impl<'src> Parser<'src> {
statement
} else {
// Replace the left-hand side with the infix operation
self.parse_infix(left)?
self.parse_infix(left, context)?
};
}
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);
let operator_start = self.current_position.0;
@ -361,7 +356,7 @@ impl<'src> Parser<'src> {
Token::Bang => {
self.next_token()?;
let operand = self.parse_expression(0)?;
let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1);
Ok(Expression::not(operand, position))
@ -369,7 +364,7 @@ impl<'src> Parser<'src> {
Token::Minus => {
self.next_token()?;
let operand = self.parse_expression(0)?;
let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1);
Ok(Expression::negation(operand, position))
@ -377,7 +372,7 @@ impl<'src> Parser<'src> {
Token::Star => {
self.next_token()?;
let operand = self.parse_expression(0)?;
let operand = self.parse_expression(0, context)?;
let position = (operator_start, self.current_position.1);
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);
let start_position = self.current_position;
match self.current_token {
Token::Async => {
let block = self.parse_block()?;
let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1);
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
(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;
(Some(expression), end)
@ -460,13 +455,15 @@ impl<'src> Parser<'src> {
let identifier = Identifier::new(text);
if let ParserMode::Condition = self.mode {
context.update_last_position(&identifier, start_position)?;
return Ok(Expression::identifier(identifier, start_position));
}
if let Token::LeftCurlyBrace = self.current_token {
self.next_token()?;
let name = Node::new(identifier, start_position);
let name = Node::new(identifier.clone(), start_position);
let mut fields = Vec::new();
loop {
@ -476,7 +473,7 @@ impl<'src> Parser<'src> {
break;
}
let field_name = self.parse_identifier()?;
let field_name = self.parse_identifier(context)?;
if let Token::Colon = self.current_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));
@ -499,12 +496,16 @@ impl<'src> Parser<'src> {
let position = (start_position.0, self.current_position.1);
context.update_last_position(&identifier, position)?;
return Ok(Expression::r#struct(
StructExpression::Fields { name, fields },
position,
));
}
context.update_last_position(&identifier, start_position)?;
Ok(Expression::identifier(identifier, start_position))
}
Token::Integer(text) => {
@ -520,7 +521,7 @@ impl<'src> Parser<'src> {
Token::If => {
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);
Ok(Expression::r#if(r#if, position))
@ -531,14 +532,14 @@ impl<'src> Parser<'src> {
Ok(Expression::literal(text.to_string(), start_position))
}
Token::LeftCurlyBrace => {
let block_node = self.parse_block()?;
let block_node = self.parse_block(context)?;
Ok(Expression::block(block_node.inner, block_node.position))
}
Token::LeftParenthesis => {
self.next_token()?;
let node = self.parse_expression(0)?;
let node = self.parse_expression(0, context)?;
if let Token::RightParenthesis = self.current_token {
let position = (start_position.0, self.current_position.1);
@ -565,12 +566,12 @@ impl<'src> Parser<'src> {
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 {
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 {
let position = (start_position.0, self.current_position.1);
@ -608,7 +609,7 @@ impl<'src> Parser<'src> {
continue;
}
let expression = self.parse_expression(0)?;
let expression = self.parse_expression(0, context)?;
expressions.push(expression);
}
@ -616,7 +617,7 @@ impl<'src> Parser<'src> {
Token::Loop => {
self.next_token()?;
let block = self.parse_block()?;
let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1);
Ok(Expression::infinite_loop(block, position))
@ -645,7 +646,7 @@ impl<'src> Parser<'src> {
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 {
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));
@ -669,8 +670,8 @@ impl<'src> Parser<'src> {
Token::While => {
self.next_token()?;
let condition = self.parse_expression(0)?;
let block = self.parse_block()?;
let condition = self.parse_expression(0, context)?;
let block = self.parse_block(context)?;
let position = (start_position.0, block.position.1);
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);
let operator_precedence = self.current_token.precedence()
@ -709,7 +714,7 @@ impl<'src> Parser<'src> {
if let Token::Equal = &self.current_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);
return Ok(Expression::assignment(left, value, position));
@ -725,7 +730,7 @@ impl<'src> Parser<'src> {
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);
return Ok(Expression::operator(
@ -741,7 +746,7 @@ impl<'src> Parser<'src> {
if let Token::DoubleDot = &self.current_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);
return Ok(Expression::exclusive_range(left, end, position));
@ -761,7 +766,7 @@ impl<'src> Parser<'src> {
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);
return Ok(Expression::operator(
@ -798,7 +803,7 @@ impl<'src> Parser<'src> {
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);
return Ok(Expression::operator(
@ -824,7 +829,7 @@ impl<'src> Parser<'src> {
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);
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);
let expression = match &self.current_token {
@ -856,7 +865,7 @@ impl<'src> Parser<'src> {
Expression::tuple_access(left, index_node, position)
} else {
let field = self.parse_identifier()?;
let field = self.parse_identifier(context)?;
let position = (left.position().0, field.position.1);
Expression::field_access(left, field, position)
@ -868,7 +877,7 @@ impl<'src> Parser<'src> {
let mut arguments = Vec::new();
while self.current_token != Token::RightParenthesis {
let argument = self.parse_expression(0)?;
let argument = self.parse_expression(0, context)?;
arguments.push(argument);
@ -879,16 +888,16 @@ impl<'src> Parser<'src> {
}
}
self.next_token()?;
let position = (left.position().0, self.current_position.1);
self.next_token()?;
Expression::call(left, arguments, position)
}
Token::LeftSquareBrace => {
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 end = self.current_position.1;
@ -922,22 +931,22 @@ impl<'src> Parser<'src> {
};
if self.current_token.is_postfix() {
self.parse_postfix(expression)
self.parse_postfix(expression, context)
} else {
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
self.mode = ParserMode::Condition;
let condition = self.parse_expression(0)?;
let condition = self.parse_expression(0, context)?;
self.mode = ParserMode::Normal;
let if_block = self.parse_block()?;
let if_block = self.parse_block(context)?;
if let Token::Else = self.current_token {
self.next_token()?;
@ -947,7 +956,7 @@ impl<'src> Parser<'src> {
if let Token::If = self.current_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);
Ok(IfExpression::IfElse {
@ -956,7 +965,7 @@ impl<'src> Parser<'src> {
r#else: ElseExpression::If(Node::new(Box::new(if_expression), position)),
})
} else {
let else_block = self.parse_block()?;
let else_block = self.parse_block(context)?;
Ok(IfExpression::IfElse {
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 {
let position = self.current_position;
let identifier = Identifier::new(text);
self.next_token()?;
Ok(Node::new(Identifier::new(text), position))
context.update_last_position(&identifier, position)?;
Ok(Node::new(identifier, position))
} else {
Err(ParseError::ExpectedToken {
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 is_async = if let Token::Async = self.current_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 {
if let Token::RightCurlyBrace = self.current_token {
@ -1016,11 +1031,6 @@ impl<'src> Parser<'src> {
self.next_token()?;
let ast = AbstractSyntaxTree {
statements,
context: self.context.create_child(),
};
return if is_async {
Ok(Node::new(BlockExpression::Async(ast), position))
} 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)]
pub enum ParseError {
ContextError(ContextError),
Boolean {
error: ParseBoolError,
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 {
fn from(v: LexError) -> Self {
Self::Lex(v)
@ -1115,6 +1132,7 @@ impl ParseError {
pub fn position(&self) -> Span {
match self {
ParseError::Boolean { position, .. } => *position,
ParseError::ContextError { .. } => (0, 0),
ParseError::ExpectedAssignment { actual } => actual.position(),
ParseError::ExpectedExpression { actual } => actual.position(),
ParseError::ExpectedIdentifierNode { actual } => actual.position(),
@ -1133,6 +1151,7 @@ impl Display for ParseError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Boolean { error, .. } => write!(f, "{}", error),
Self::ContextError(error) => write!(f, "{}", error),
Self::ExpectedAssignment { .. } => write!(f, "Expected assignment"),
Self::ExpectedExpression { .. } => write!(f, "Expected expression"),
Self::ExpectedIdentifierNode { actual } => {
@ -1398,7 +1417,7 @@ mod tests {
Expression::literal(42, (4, 6)),
Expression::literal("bar".to_string(), (8, 13)),
],
(0, 15)
(0, 14)
),
Node::new(0, (15, 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 mut analyzer = Analyzer::new(&abstract_syntax_tree);
analyzer.analyze();
analyzer.analyze()?;
if !analyzer.errors.is_empty() {
return Err(DustError::Analysis {
@ -58,11 +58,7 @@ pub fn run(source: &str) -> Result<Option<Value>, DustError> {
/// Dust virtual machine.
///
/// **Warning**: Do not run an AbstractSyntaxTree that has not been analyzed *with the same
/// 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.
/// See the `run` function for an example of how to parse, analyze and run code.
pub struct Vm;
impl Vm {
@ -70,7 +66,11 @@ impl Vm {
let mut previous_evaluation = Evaluation::Return(None);
while let Some(statement) = tree.statements.pop_front() {
let statement_end = statement.position().1;
previous_evaluation = self.run_statement(statement, &tree.context, true)?;
tree.context.collect_garbage(statement_end).unwrap();
}
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 {
error: Box::new(error),
position,
@ -1020,7 +1014,7 @@ impl Vm {
fn run_block(
&self,
block: BlockExpression,
context: &Context,
_context: &Context,
collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> {
match block {
@ -1424,7 +1418,7 @@ impl Display for RuntimeError {
mod tests {
use std::collections::HashMap;
use crate::{AnalysisError, Struct};
use crate::Struct;
use super::*;
@ -1480,50 +1474,6 @@ mod tests {
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]
fn character() {
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))));
}