Add analyzer; Rename some things

This commit is contained in:
Jeff 2024-08-04 23:11:04 -04:00
parent f2bfe2ed06
commit 2268fc827d
6 changed files with 199 additions and 118 deletions

View File

@ -0,0 +1,28 @@
use crate::{Identifier, Span, Value};
#[derive(Debug, PartialEq, Clone)]
pub struct Node {
pub operation: Statement,
pub span: Span,
}
impl Node {
pub fn new(operation: Statement, span: Span) -> Self {
Self { operation, span }
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
// Top-level statements
Assign(Box<(Node, Node)>),
// Expressions
Add(Box<(Node, Node)>),
List(Vec<Node>),
Multiply(Box<(Node, Node)>),
// Hard-coded values
Constant(Value),
Identifier(Identifier),
}

85
dust-lang/src/analyzer.rs Normal file
View File

@ -0,0 +1,85 @@
use crate::{Node, Span, Statement};
pub struct Analyzer {
abstract_tree: Vec<Node>,
}
impl Analyzer {
pub fn new(abstract_tree: Vec<Node>) -> Self {
Analyzer { abstract_tree }
}
pub fn analyze(&self) -> Result<(), AnalyzerError> {
for node in &self.abstract_tree {
self.analyze_node(node)?;
}
Ok(())
}
fn analyze_node(&self, node: &Node) -> Result<(), AnalyzerError> {
match &node.operation {
Statement::Add(instructions) => {
self.analyze_node(&instructions.0)?;
self.analyze_node(&instructions.1)?;
}
Statement::Assign(instructions) => {
if let Statement::Identifier(_) = &instructions.0.operation {
// Identifier
} else {
return Err(AnalyzerError::ExpectedIdentifier {
actual: instructions.0.clone(),
});
}
self.analyze_node(&instructions.0)?;
self.analyze_node(&instructions.1)?;
}
Statement::Constant(_) => {}
Statement::Identifier(_) => {}
Statement::List(instructions) => {
for instruction in instructions {
self.analyze_node(instruction)?;
}
}
Statement::Multiply(instructions) => {
self.analyze_node(&instructions.0)?;
self.analyze_node(&instructions.1)?;
}
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum AnalyzerError {
ExpectedIdentifier { actual: Node },
}
#[cfg(test)]
mod tests {
use crate::Value;
use super::*;
#[test]
fn analyze() {
let abstract_tree = vec![Node::new(
Statement::Assign(Box::new((
Node::new(Statement::Constant(Value::integer(1)), (0, 1)),
Node::new(Statement::Constant(Value::integer(2)), (1, 2)),
))),
(0, 1),
)];
let analyzer = Analyzer::new(abstract_tree);
assert_eq!(
analyzer.analyze(),
Err(AnalyzerError::ExpectedIdentifier {
actual: Node::new(Statement::Constant(Value::integer(1)), (0, 1))
})
)
}
}

View File

@ -1,23 +0,0 @@
use crate::{Identifier, Span, Value};
#[derive(Debug, PartialEq, Clone)]
pub struct Instruction {
pub operation: Operation,
pub span: Span,
}
impl Instruction {
pub fn new(operation: Operation, span: Span) -> Self {
Self { operation, span }
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Operation {
Add(Box<(Instruction, Instruction)>),
Assign(Box<(Instruction, Instruction)>),
Constant(Value),
Identifier(Identifier),
List(Vec<Instruction>),
Multiply(Box<(Instruction, Instruction)>),
}

View File

@ -7,8 +7,9 @@ The [interpreter] module contains the `Interpreter` struct, which is used to lex
interpret Dust code. The `interpret` function is a convenience function that creates a new interpret Dust code. The `interpret` function is a convenience function that creates a new
`Interpreter` and runs the given source code. `Interpreter` and runs the given source code.
*/ */
pub mod abstract_tree;
pub mod analyzer;
pub mod identifier; pub mod identifier;
pub mod instruction;
pub mod lex; pub mod lex;
pub mod parse; pub mod parse;
pub mod token; pub mod token;
@ -16,8 +17,9 @@ pub mod r#type;
pub mod value; pub mod value;
pub mod vm; pub mod vm;
pub use abstract_tree::{Node, Statement};
pub use analyzer::Analyzer;
pub use identifier::Identifier; pub use identifier::Identifier;
pub use instruction::{Instruction, Operation};
pub use lex::{lex, LexError, Lexer}; pub use lex::{lex, LexError, Lexer};
pub use parse::{parse, ParseError, Parser}; pub use parse::{parse, ParseError, Parser};
pub use r#type::Type; pub use r#type::Type;

View File

@ -1,9 +1,9 @@
use crate::{ use crate::{
lex::{LexError, Lexer}, lex::{LexError, Lexer},
Instruction, Operation, Span, Token, Value, Node, Span, Statement, Token, Value,
}; };
pub fn parse(input: &str) -> Result<Vec<Instruction>, ParseError> { pub fn parse(input: &str) -> Result<Vec<Node>, ParseError> {
let lexer = Lexer::new(input); let lexer = Lexer::new(input);
let mut parser = Parser::new(lexer); let mut parser = Parser::new(lexer);
let mut instructions = Vec::new(); let mut instructions = Vec::new();
@ -34,7 +34,7 @@ impl<'src> Parser<'src> {
Parser { lexer, current } Parser { lexer, current }
} }
pub fn parse(&mut self) -> Result<Instruction, ParseError> { pub fn parse(&mut self) -> Result<Node, ParseError> {
self.parse_instruction(0) self.parse_instruction(0)
} }
@ -44,7 +44,7 @@ impl<'src> Parser<'src> {
Ok(()) Ok(())
} }
fn parse_instruction(&mut self, precedence: u8) -> Result<Instruction, ParseError> { fn parse_instruction(&mut self, precedence: u8) -> Result<Node, ParseError> {
let left_instruction = self.parse_primary()?; let left_instruction = self.parse_primary()?;
let left_start = left_instruction.span.0; let left_start = left_instruction.span.0;
@ -56,8 +56,8 @@ impl<'src> Parser<'src> {
let right_instruction = self.parse_instruction(self.current_precedence())?; let right_instruction = self.parse_instruction(self.current_precedence())?;
let right_end = right_instruction.span.1; let right_end = right_instruction.span.1;
return Ok(Instruction::new( return Ok(Node::new(
Operation::Add(Box::new((left_instruction, right_instruction))), Statement::Add(Box::new((left_instruction, right_instruction))),
(left_start, right_end), (left_start, right_end),
)); ));
} }
@ -67,8 +67,8 @@ impl<'src> Parser<'src> {
let right_instruction = self.parse_instruction(self.current_precedence())?; let right_instruction = self.parse_instruction(self.current_precedence())?;
let right_end = right_instruction.span.1; let right_end = right_instruction.span.1;
return Ok(Instruction::new( return Ok(Node::new(
Operation::Multiply(Box::new((left_instruction, right_instruction))), Statement::Multiply(Box::new((left_instruction, right_instruction))),
(left_start, right_end), (left_start, right_end),
)); ));
} }
@ -78,8 +78,8 @@ impl<'src> Parser<'src> {
let right_instruction = self.parse_instruction(self.current_precedence())?; let right_instruction = self.parse_instruction(self.current_precedence())?;
let right_end = right_instruction.span.1; let right_end = right_instruction.span.1;
return Ok(Instruction::new( return Ok(Node::new(
Operation::Assign(Box::new((left_instruction, right_instruction))), Statement::Assign(Box::new((left_instruction, right_instruction))),
(left_start, right_end), (left_start, right_end),
)); ));
} }
@ -90,28 +90,22 @@ impl<'src> Parser<'src> {
Ok(left_instruction) Ok(left_instruction)
} }
fn parse_primary(&mut self) -> Result<Instruction, ParseError> { fn parse_primary(&mut self) -> Result<Node, ParseError> {
match self.current.clone() { match self.current.clone() {
(Token::Float(float), span) => { (Token::Float(float), span) => {
self.next_token()?; self.next_token()?;
Ok(Instruction::new( Ok(Node::new(Statement::Constant(Value::float(float)), span))
Operation::Constant(Value::float(float)),
span,
))
} }
(Token::Integer(int), span) => { (Token::Integer(int), span) => {
self.next_token()?; self.next_token()?;
Ok(Instruction::new( Ok(Node::new(Statement::Constant(Value::integer(int)), span))
Operation::Constant(Value::integer(int)),
span,
))
} }
(Token::Identifier(identifier), span) => { (Token::Identifier(identifier), span) => {
self.next_token()?; self.next_token()?;
Ok(Instruction::new(Operation::Identifier(identifier), span)) Ok(Node::new(Statement::Identifier(identifier), span))
} }
(Token::LeftParenthesis, left_span) => { (Token::LeftParenthesis, left_span) => {
self.next_token()?; self.next_token()?;
@ -121,7 +115,7 @@ impl<'src> Parser<'src> {
if let (Token::RightParenthesis, right_span) = self.current { if let (Token::RightParenthesis, right_span) = self.current {
self.next_token()?; self.next_token()?;
Ok(Instruction::new( Ok(Node::new(
instruction.operation, instruction.operation,
(left_span.0, right_span.1), (left_span.0, right_span.1),
)) ))
@ -141,8 +135,8 @@ impl<'src> Parser<'src> {
if let (Token::RightSquareBrace, right_span) = self.current { if let (Token::RightSquareBrace, right_span) = self.current {
self.next_token()?; self.next_token()?;
return Ok(Instruction::new( return Ok(Node::new(
Operation::List(instructions), Statement::List(instructions),
(left_span.0, right_span.1), (left_span.0, right_span.1),
)); ));
} }
@ -203,29 +197,23 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::List(vec![ Statement::List(vec![
Instruction::new(Operation::Constant(Value::integer(1)), (1, 2)), Node::new(Statement::Constant(Value::integer(1)), (1, 2)),
Instruction::new( Node::new(
Operation::Add(Box::new(( Statement::Add(Box::new((
Instruction::new(Operation::Constant(Value::integer(1)), (4, 5)), Node::new(Statement::Constant(Value::integer(1)), (4, 5)),
Instruction::new(Operation::Constant(Value::integer(1)), (8, 9)), Node::new(Statement::Constant(Value::integer(1)), (8, 9)),
))), ))),
(4, 9) (4, 9)
), ),
Instruction::new( Node::new(
Operation::Add(Box::new(( Statement::Add(Box::new((
Instruction::new(Operation::Constant(Value::integer(2)), (11, 12)), Node::new(Statement::Constant(Value::integer(2)), (11, 12)),
Instruction::new( Node::new(
Operation::Multiply(Box::new(( Statement::Multiply(Box::new((
Instruction::new( Node::new(Statement::Constant(Value::integer(4)), (16, 17)),
Operation::Constant(Value::integer(4)), Node::new(Statement::Constant(Value::integer(10)), (20, 22)),
(16, 17)
),
Instruction::new(
Operation::Constant(Value::integer(10)),
(20, 22)
),
))), ))),
(15, 23) (15, 23)
), ),
@ -244,10 +232,10 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::List(vec![ Statement::List(vec![
Instruction::new(Operation::Constant(Value::integer(1)), (1, 2)), Node::new(Statement::Constant(Value::integer(1)), (1, 2)),
Instruction::new(Operation::Constant(Value::integer(2)), (4, 5)), Node::new(Statement::Constant(Value::integer(2)), (4, 5)),
]), ]),
(0, 6) (0, 6)
)]) )])
@ -260,7 +248,7 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new(Operation::List(vec![]), (0, 2))]) Ok(vec![Node::new(Statement::List(vec![]), (0, 2))])
); );
} }
@ -270,8 +258,8 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::Constant(Value::float(42.0)), Statement::Constant(Value::float(42.0)),
(0, 4) (0, 4)
)]) )])
); );
@ -283,10 +271,10 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::Add(Box::new(( Statement::Add(Box::new((
Instruction::new(Operation::Constant(Value::integer(1)), (0, 1)), Node::new(Statement::Constant(Value::integer(1)), (0, 1)),
Instruction::new(Operation::Constant(Value::integer(2)), (4, 5)), Node::new(Statement::Constant(Value::integer(2)), (4, 5)),
))), ))),
(0, 5) (0, 5)
)]) )])
@ -299,10 +287,10 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::Multiply(Box::new(( Statement::Multiply(Box::new((
Instruction::new(Operation::Constant(Value::integer(1)), (0, 1)), Node::new(Statement::Constant(Value::integer(1)), (0, 1)),
Instruction::new(Operation::Constant(Value::integer(2)), (4, 5)), Node::new(Statement::Constant(Value::integer(2)), (4, 5)),
))), ))),
(0, 5) (0, 5)
)]) )])
@ -315,13 +303,13 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::Add(Box::new(( Statement::Add(Box::new((
Instruction::new(Operation::Constant(Value::integer(1)), (0, 1)), Node::new(Statement::Constant(Value::integer(1)), (0, 1)),
Instruction::new( Node::new(
Operation::Multiply(Box::new(( Statement::Multiply(Box::new((
Instruction::new(Operation::Constant(Value::integer(2)), (4, 5)), Node::new(Statement::Constant(Value::integer(2)), (4, 5)),
Instruction::new(Operation::Constant(Value::integer(3)), (8, 9)), Node::new(Statement::Constant(Value::integer(3)), (8, 9)),
))), ))),
(4, 9) (4, 9)
), ),
@ -337,22 +325,16 @@ mod tests {
assert_eq!( assert_eq!(
parse(input), parse(input),
Ok(vec![Instruction::new( Ok(vec![Node::new(
Operation::Assign(Box::new(( Statement::Assign(Box::new((
Instruction::new(Operation::Identifier(Identifier::new("a")), (0, 1)), Node::new(Statement::Identifier(Identifier::new("a")), (0, 1)),
Instruction::new( Node::new(
Operation::Add(Box::new(( Statement::Add(Box::new((
Instruction::new(Operation::Constant(Value::integer(1)), (4, 5)), Node::new(Statement::Constant(Value::integer(1)), (4, 5)),
Instruction::new( Node::new(
Operation::Multiply(Box::new(( Statement::Multiply(Box::new((
Instruction::new( Node::new(Statement::Constant(Value::integer(2)), (8, 9)),
Operation::Constant(Value::integer(2)), Node::new(Statement::Constant(Value::integer(3)), (12, 13)),
(8, 9)
),
Instruction::new(
Operation::Constant(Value::integer(3)),
(12, 13)
),
))), ))),
(8, 13) (8, 13)
), ),

View File

@ -1,4 +1,4 @@
use crate::{parse, Instruction, Operation, ParseError, Parser, Value, ValueError}; use crate::{parse, Node, ParseError, Parser, Statement, Value, ValueError};
pub fn run(input: &str) -> Result<Option<Value>, VmError> { pub fn run(input: &str) -> Result<Option<Value>, VmError> {
let instructions = parse(input)?; let instructions = parse(input)?;
@ -8,11 +8,11 @@ pub fn run(input: &str) -> Result<Option<Value>, VmError> {
} }
pub struct Vm { pub struct Vm {
instructions: Vec<Instruction>, instructions: Vec<Node>,
} }
impl Vm { impl Vm {
pub fn new(instructions: Vec<Instruction>) -> Self { pub fn new(instructions: Vec<Node>) -> Self {
Vm { instructions } Vm { instructions }
} }
@ -26,9 +26,9 @@ impl Vm {
Ok(previous_value) Ok(previous_value)
} }
fn run_instruction(&self, instruction: &Instruction) -> Result<Option<Value>, VmError> { fn run_instruction(&self, instruction: &Node) -> Result<Option<Value>, VmError> {
match &instruction.operation { match &instruction.operation {
Operation::Add(instructions) => { Statement::Add(instructions) => {
let left = if let Some(value) = self.run_instruction(&instructions.0)? { let left = if let Some(value) = self.run_instruction(&instructions.0)? {
value value
} else { } else {
@ -43,19 +43,19 @@ impl Vm {
Ok(Some(sum)) Ok(Some(sum))
} }
Operation::Assign(_) => todo!(), Statement::Assign(_) => todo!(),
Operation::Constant(value) => Ok(Some(value.clone())), Statement::Constant(value) => Ok(Some(value.clone())),
Operation::Identifier(_) => todo!(), Statement::Identifier(_) => todo!(),
Operation::List(_) => todo!(), Statement::List(_) => todo!(),
Operation::Multiply(_) => todo!(), Statement::Multiply(_) => todo!(),
} }
} }
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum VmError { pub enum VmError {
ExpectedValue(Operation), ExpectedValue(Statement),
InvalidOperation(Operation), InvalidOperation(Statement),
ParseError(ParseError), ParseError(ParseError),
ValueError(ValueError), ValueError(ValueError),
} }
@ -82,4 +82,11 @@ mod tests {
assert_eq!(run(input), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::integer(3))));
} }
#[test]
fn add_multiple() {
let input = "(a + b = 1)";
assert_eq!(run(input), Ok(Some(Value::integer(6))));
}
} }