Add basic analyzer implementation
This commit is contained in:
parent
447643f315
commit
207d155a25
@ -11,7 +11,9 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
AbstractSyntaxTree, LetStatement, Node, OperatorExpression, Statement, StructDefinition,
|
AbstractSyntaxTree, BlockExpression, CallExpression, ElseExpression, FieldAccessExpression,
|
||||||
|
IfExpression, LetStatement, ListExpression, ListIndexExpression, LoopExpression, Node,
|
||||||
|
OperatorExpression, RangeExpression, Statement, StructExpression, TupleAccessExpression,
|
||||||
},
|
},
|
||||||
parse, Context, DustError, Expression, Identifier, Span, Type,
|
parse, Context, DustError, Expression, Identifier, Span, Type,
|
||||||
};
|
};
|
||||||
@ -126,9 +128,7 @@ impl<'a> Analyzer<'a> {
|
|||||||
value,
|
value,
|
||||||
} => todo!(),
|
} => todo!(),
|
||||||
},
|
},
|
||||||
Statement::StructDefinition(_) => {
|
Statement::StructDefinition(_) => {}
|
||||||
let StructDefinition { identifier, fields } = statement;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -136,10 +136,25 @@ impl<'a> Analyzer<'a> {
|
|||||||
|
|
||||||
fn analyze_expression(&mut self, expression: &Expression) -> Result<(), AnalyzerError> {
|
fn analyze_expression(&mut self, expression: &Expression) -> Result<(), AnalyzerError> {
|
||||||
match expression {
|
match expression {
|
||||||
Expression::Block(_) => {}
|
Expression::Block(block_expression) => self.analyze_block(&block_expression.inner)?,
|
||||||
Expression::Call(_) => {}
|
Expression::Call(call_expression) => {
|
||||||
Expression::FieldAccess(_) => {}
|
let CallExpression { invoker, arguments } = call_expression.inner.as_ref();
|
||||||
Expression::Grouped(_) => {}
|
|
||||||
|
self.analyze_expression(invoker)?;
|
||||||
|
|
||||||
|
for argument in arguments {
|
||||||
|
self.analyze_expression(argument)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expression::FieldAccess(field_access_expression) => {
|
||||||
|
let FieldAccessExpression { container, .. } =
|
||||||
|
field_access_expression.inner.as_ref();
|
||||||
|
|
||||||
|
self.analyze_expression(container)?;
|
||||||
|
}
|
||||||
|
Expression::Grouped(expression) => {
|
||||||
|
self.analyze_expression(expression.inner.as_ref())?;
|
||||||
|
}
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => {
|
||||||
let found = self
|
let found = self
|
||||||
.context
|
.context
|
||||||
@ -151,11 +166,43 @@ impl<'a> Analyzer<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expression::If(_) => {}
|
Expression::If(if_expression) => self.analyze_if(&if_expression.inner)?,
|
||||||
Expression::List(_) => {}
|
Expression::List(list_expression) => match list_expression.inner.as_ref() {
|
||||||
Expression::ListIndex(_) => {}
|
ListExpression::AutoFill {
|
||||||
Expression::Literal(_) => {}
|
repeat_operand,
|
||||||
Expression::Loop(_) => {}
|
length_operand,
|
||||||
|
} => {
|
||||||
|
self.analyze_expression(repeat_operand)?;
|
||||||
|
self.analyze_expression(length_operand)?;
|
||||||
|
}
|
||||||
|
ListExpression::Ordered(expressions) => {
|
||||||
|
for expression in expressions {
|
||||||
|
self.analyze_expression(expression)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expression::ListIndex(list_index_expression) => {
|
||||||
|
let ListIndexExpression { list, index } = list_index_expression.inner.as_ref();
|
||||||
|
|
||||||
|
self.analyze_expression(list)?;
|
||||||
|
self.analyze_expression(index)?;
|
||||||
|
}
|
||||||
|
Expression::Literal(_) => {
|
||||||
|
// 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::While { condition, block } => {
|
||||||
|
self.analyze_expression(condition)?;
|
||||||
|
self.analyze_block(&block.inner)?;
|
||||||
|
}
|
||||||
|
LoopExpression::For {
|
||||||
|
iterator, block, ..
|
||||||
|
} => {
|
||||||
|
self.analyze_expression(iterator)?;
|
||||||
|
self.analyze_block(&block.inner)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
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)?;
|
self.analyze_expression(assignee)?;
|
||||||
@ -187,9 +234,97 @@ impl<'a> Analyzer<'a> {
|
|||||||
self.analyze_expression(right)?;
|
self.analyze_expression(right)?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::Range(_) => {}
|
Expression::Range(range_expression) => match range_expression.inner.as_ref() {
|
||||||
Expression::Struct(_) => {}
|
RangeExpression::Exclusive { start, end } => {
|
||||||
Expression::TupleAccess(_) => {}
|
self.analyze_expression(start)?;
|
||||||
|
self.analyze_expression(end)?;
|
||||||
|
}
|
||||||
|
RangeExpression::Inclusive { start, end } => {
|
||||||
|
self.analyze_expression(start)?;
|
||||||
|
self.analyze_expression(end)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
|
||||||
|
StructExpression::Unit { name } => {
|
||||||
|
let found = self
|
||||||
|
.context
|
||||||
|
.update_last_position(&name.inner, name.position);
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return Err(AnalyzerError::UndefinedType {
|
||||||
|
identifier: name.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StructExpression::Fields { name, fields } => {
|
||||||
|
let found = self
|
||||||
|
.context
|
||||||
|
.update_last_position(&name.inner, name.position);
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return Err(AnalyzerError::UndefinedType {
|
||||||
|
identifier: name.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, expression) in fields {
|
||||||
|
self.analyze_expression(expression)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expression::TupleAccess(tuple_access) => {
|
||||||
|
let TupleAccessExpression { tuple, .. } = tuple_access.inner.as_ref();
|
||||||
|
|
||||||
|
self.analyze_expression(tuple)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze_block(&mut self, block_expression: &BlockExpression) -> Result<(), AnalyzerError> {
|
||||||
|
match block_expression {
|
||||||
|
BlockExpression::Async(statements) => {
|
||||||
|
for statement in statements {
|
||||||
|
self.analyze_statement(statement)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlockExpression::Sync(statements) => {
|
||||||
|
for statement in statements {
|
||||||
|
self.analyze_statement(statement)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze_if(&mut self, if_expression: &IfExpression) -> Result<(), AnalyzerError> {
|
||||||
|
match if_expression {
|
||||||
|
IfExpression::If {
|
||||||
|
condition,
|
||||||
|
if_block,
|
||||||
|
} => {
|
||||||
|
self.analyze_expression(condition)?;
|
||||||
|
self.analyze_block(&if_block.inner)?;
|
||||||
|
}
|
||||||
|
IfExpression::IfElse {
|
||||||
|
condition,
|
||||||
|
if_block,
|
||||||
|
r#else,
|
||||||
|
} => {
|
||||||
|
self.analyze_expression(condition)?;
|
||||||
|
self.analyze_block(&if_block.inner)?;
|
||||||
|
|
||||||
|
match r#else {
|
||||||
|
ElseExpression::Block(block_expression) => {
|
||||||
|
self.analyze_block(&block_expression.inner)?;
|
||||||
|
}
|
||||||
|
ElseExpression::If(if_expression) => {
|
||||||
|
self.analyze_if(&if_expression.inner)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -24,7 +24,7 @@ pub enum Expression {
|
|||||||
Operator(Node<Box<OperatorExpression>>),
|
Operator(Node<Box<OperatorExpression>>),
|
||||||
Range(Node<Box<RangeExpression>>),
|
Range(Node<Box<RangeExpression>>),
|
||||||
Struct(Node<Box<StructExpression>>),
|
Struct(Node<Box<StructExpression>>),
|
||||||
TupleAccess(Node<Box<TupleAccess>>),
|
TupleAccess(Node<Box<TupleAccessExpression>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
@ -61,7 +61,10 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tuple_access(tuple: Expression, index: Node<usize>, position: Span) -> Self {
|
pub fn tuple_access(tuple: Expression, index: Node<usize>, position: Span) -> Self {
|
||||||
Self::TupleAccess(Node::new(Box::new(TupleAccess { tuple, index }), position))
|
Self::TupleAccess(Node::new(
|
||||||
|
Box::new(TupleAccessExpression { tuple, index }),
|
||||||
|
position,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self {
|
pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self {
|
||||||
@ -388,12 +391,12 @@ impl Display for Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub struct TupleAccess {
|
pub struct TupleAccessExpression {
|
||||||
pub tuple: Expression,
|
pub tuple: Expression,
|
||||||
pub index: Node<usize>,
|
pub index: Node<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TupleAccess {
|
impl Display for TupleAccessExpression {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{}.{}", self.tuple, self.index)
|
write!(f, "{}.{}", self.tuple, self.index)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user