Add analyzer; Rename some things
This commit is contained in:
parent
f2bfe2ed06
commit
2268fc827d
28
dust-lang/src/abstract_tree.rs
Normal file
28
dust-lang/src/abstract_tree.rs
Normal 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
85
dust-lang/src/analyzer.rs
Normal 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))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -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)>),
|
|
||||||
}
|
|
@ -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;
|
||||||
|
@ -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)
|
||||||
),
|
),
|
||||||
|
@ -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))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user