1
0

Implement VM

This commit is contained in:
Jeff 2024-08-16 05:14:00 -04:00
parent 26348fb82e
commit bfb07047a5
6 changed files with 443 additions and 228 deletions

View File

@ -5,22 +5,22 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{Identifier, Span, Value}; use crate::{Context, Identifier, Span, StructType, Type, Value};
use super::{Node, Statement}; use super::{Node, Statement};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Expression { pub enum Expression {
Block(Node<Box<Block>>), Block(Node<Box<BlockExpression>>),
Call(Node<Box<CallExpression>>), Call(Node<Box<CallExpression>>),
FieldAccess(Node<Box<FieldAccess>>), FieldAccess(Node<Box<FieldAccessExpression>>),
Grouped(Node<Box<Expression>>), Grouped(Node<Box<Expression>>),
Identifier(Node<Identifier>), Identifier(Node<Identifier>),
If(Node<Box<IfExpression>>), If(Node<Box<IfExpression>>),
List(Node<Box<ListExpression>>), List(Node<Box<ListExpression>>),
ListIndex(Node<Box<ListIndex>>), ListIndex(Node<Box<ListIndexExpression>>),
Literal(Node<Box<LiteralExpression>>), Literal(Node<Box<LiteralExpression>>),
Loop(Node<Box<Loop>>), Loop(Node<Box<LoopExpression>>),
Operator(Node<Box<OperatorExpression>>), Operator(Node<Box<OperatorExpression>>),
Range(Node<Box<Range>>), Range(Node<Box<Range>>),
Struct(Node<Box<StructExpression>>), Struct(Node<Box<StructExpression>>),
@ -45,7 +45,7 @@ impl Expression {
pub fn field_access(container: Expression, field: Node<Identifier>, position: Span) -> Self { pub fn field_access(container: Expression, field: Node<Identifier>, position: Span) -> Self {
Self::FieldAccess(Node::new( Self::FieldAccess(Node::new(
Box::new(FieldAccess { container, field }), Box::new(FieldAccessExpression { container, field }),
position, position,
)) ))
} }
@ -146,13 +146,16 @@ impl Expression {
)) ))
} }
pub fn infinite_loop(block: Node<Block>, position: Span) -> Self { pub fn infinite_loop(block: Node<BlockExpression>, position: Span) -> Self {
Self::Loop(Node::new(Box::new(Loop::Infinite { block }), position)) Self::Loop(Node::new(
Box::new(LoopExpression::Infinite { block }),
position,
))
} }
pub fn while_loop(condition: Expression, block: Node<Block>, position: Span) -> Self { pub fn while_loop(condition: Expression, block: Node<BlockExpression>, position: Span) -> Self {
Self::Loop(Node::new( Self::Loop(Node::new(
Box::new(Loop::While { condition, block }), Box::new(LoopExpression::While { condition, block }),
position, position,
)) ))
} }
@ -160,11 +163,11 @@ impl Expression {
pub fn for_loop( pub fn for_loop(
identifier: Node<Identifier>, identifier: Node<Identifier>,
iterator: Expression, iterator: Expression,
block: Node<Block>, block: Node<BlockExpression>,
position: Span, position: Span,
) -> Self { ) -> Self {
Self::Loop(Node::new( Self::Loop(Node::new(
Box::new(Loop::For { Box::new(LoopExpression::For {
identifier, identifier,
iterator, iterator,
block, block,
@ -173,7 +176,7 @@ impl Expression {
)) ))
} }
pub fn block(block: Block, position: Span) -> Self { pub fn block(block: BlockExpression, position: Span) -> Self {
Self::Block(Node::new(Box::new(block), position)) Self::Block(Node::new(Box::new(block), position))
} }
@ -193,7 +196,7 @@ impl Expression {
Self::List(Node::new(Box::new(list_expression), position)) Self::List(Node::new(Box::new(list_expression), position))
} }
pub fn list_index(list_index: ListIndex, position: Span) -> Self { pub fn list_index(list_index: ListIndexExpression, position: Span) -> Self {
Self::ListIndex(Node::new(Box::new(list_index), position)) Self::ListIndex(Node::new(Box::new(list_index), position))
} }
@ -213,6 +216,127 @@ impl Expression {
} }
} }
pub fn return_type(&self, context: &Context) -> Option<Type> {
match self {
Expression::Block(block_expression) => {
block_expression.inner.as_ref().return_type(context)
}
Expression::Call(call_expression) => {
let CallExpression { invoker, .. } = call_expression.inner.as_ref();
let invoker_type = invoker.return_type(context)?;
if let Type::Function { return_type, .. } = invoker_type {
return_type.map(|r#type| *r#type)
} else if let Type::Struct(_) = invoker_type {
Some(invoker_type)
} else {
None
}
}
Expression::FieldAccess(field_access_expression) => {
let FieldAccessExpression { container, field } =
field_access_expression.inner.as_ref();
let container_type = container.return_type(context)?;
if let Type::Struct(StructType::Fields { fields, .. }) = container_type {
fields
.into_iter()
.find(|(name, _)| name == &field.inner)
.map(|(_, r#type)| r#type)
} else {
None
}
}
Expression::Grouped(expression) => expression.inner.return_type(context),
Expression::Identifier(identifier) => context.get_type(&identifier.inner),
Expression::If(if_expression) => match if_expression.inner.as_ref() {
IfExpression::If { .. } => None,
IfExpression::IfElse { if_block, .. } => if_block.inner.return_type(context),
},
Expression::List(list_expression) => match list_expression.inner.as_ref() {
ListExpression::AutoFill { repeat_operand, .. } => {
let item_type = repeat_operand.return_type(context)?;
Some(Type::ListOf {
item_type: Box::new(item_type),
})
}
ListExpression::Ordered(expressions) => {
if expressions.is_empty() {
return Some(Type::EmptyList);
}
let item_type = expressions.last().unwrap().return_type(context)?;
let length = expressions.len();
Some(Type::List {
item_type: Box::new(item_type),
length,
})
}
},
Expression::ListIndex(list_index_expression) => {
let ListIndexExpression { list, .. } = list_index_expression.inner.as_ref();
let list_type = list.return_type(context)?;
if let Type::List { item_type, .. } = list_type {
Some(*item_type)
} else {
None
}
}
Expression::Literal(literal_expression) => match literal_expression.inner.as_ref() {
LiteralExpression::Boolean(_) => Some(Type::Boolean),
LiteralExpression::Float(_) => Some(Type::Float),
LiteralExpression::Integer(_) => Some(Type::Integer),
LiteralExpression::String(_) => Some(Type::String),
LiteralExpression::Value(value) => Some(value.r#type()),
},
Expression::Loop(loop_expression) => match loop_expression.inner.as_ref() {
LoopExpression::For { block, .. } => block.inner.return_type(context),
LoopExpression::Infinite { .. } => None,
LoopExpression::While { block, .. } => block.inner.return_type(context),
},
Expression::Operator(operator_expression) => match operator_expression.inner.as_ref() {
OperatorExpression::Assignment { .. } => None,
OperatorExpression::Comparison { .. } => Some(Type::Boolean),
OperatorExpression::CompoundAssignment { .. } => None,
OperatorExpression::ErrorPropagation(expression) => expression.return_type(context),
OperatorExpression::Negation(expression) => expression.return_type(context),
OperatorExpression::Not(_) => Some(Type::Boolean),
OperatorExpression::Math { left, .. } => left.return_type(context),
OperatorExpression::Logic { .. } => Some(Type::Boolean),
},
Expression::Range(_) => Some(Type::Range),
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Fields { name, fields } => {
let mut field_types = Vec::with_capacity(fields.len());
for (name, expression) in fields {
let r#type = expression.return_type(context)?;
field_types.push((name.inner.clone(), r#type));
}
Some(Type::Struct(StructType::Fields {
name: name.inner.clone(),
fields: field_types,
}))
}
StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit {
name: name.inner.clone(),
})),
},
Expression::TupleAccess(tuple_access_expression) => {
todo!()
}
}
}
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
Expression::Block(block) => block.position, Expression::Block(block) => block.position,
@ -279,12 +403,12 @@ impl Display for Range {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ListIndex { pub struct ListIndexExpression {
pub list: Expression, pub list: Expression,
pub index: Expression, pub index: Expression,
} }
impl Display for ListIndex { impl Display for ListIndexExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}[{}]", self.list, self.index) write!(f, "{}[{}]", self.list, self.index)
} }
@ -313,12 +437,12 @@ impl Display for CallExpression {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FieldAccess { pub struct FieldAccessExpression {
pub container: Expression, pub container: Expression,
pub field: Node<Identifier>, pub field: Node<Identifier>,
} }
impl Display for FieldAccess { impl Display for FieldAccessExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}.{}", self.container, self.field) write!(f, "{}.{}", self.container, self.field)
} }
@ -546,18 +670,18 @@ impl Display for LogicOperator {
pub enum IfExpression { pub enum IfExpression {
If { If {
condition: Expression, condition: Expression,
if_block: Node<Block>, if_block: Node<BlockExpression>,
}, },
IfElse { IfElse {
condition: Expression, condition: Expression,
if_block: Node<Block>, if_block: Node<BlockExpression>,
r#else: ElseExpression, r#else: ElseExpression,
}, },
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ElseExpression { pub enum ElseExpression {
Block(Node<Block>), Block(Node<BlockExpression>),
If(Node<Box<IfExpression>>), If(Node<Box<IfExpression>>),
} }
@ -591,15 +715,28 @@ impl Display for IfExpression {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Block { pub enum BlockExpression {
Async(Vec<Statement>), Async(Vec<Statement>),
Sync(Vec<Statement>), Sync(Vec<Statement>),
} }
impl Display for Block { impl BlockExpression {
fn return_type(&self, context: &Context) -> Option<Type> {
match self {
BlockExpression::Async(statements) => statements
.last()
.and_then(|statement| statement.return_type(context)),
BlockExpression::Sync(statements) => statements
.last()
.and_then(|statement| statement.return_type(context)),
}
}
}
impl Display for BlockExpression {
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 {
Block::Async(statements) => { BlockExpression::Async(statements) => {
writeln!(f, "async {{ ")?; writeln!(f, "async {{ ")?;
for (i, statement) in statements.iter().enumerate() { for (i, statement) in statements.iter().enumerate() {
@ -612,7 +749,7 @@ impl Display for Block {
write!(f, " }}") write!(f, " }}")
} }
Block::Sync(statements) => { BlockExpression::Sync(statements) => {
writeln!(f, "{{ ")?; writeln!(f, "{{ ")?;
for (i, statement) in statements.iter().enumerate() { for (i, statement) in statements.iter().enumerate() {
@ -630,27 +767,29 @@ impl Display for Block {
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Loop { pub enum LoopExpression {
Infinite { Infinite {
block: Node<Block>, block: Node<BlockExpression>,
}, },
While { While {
condition: Expression, condition: Expression,
block: Node<Block>, block: Node<BlockExpression>,
}, },
For { For {
identifier: Node<Identifier>, identifier: Node<Identifier>,
iterator: Expression, iterator: Expression,
block: Node<Block>, block: Node<BlockExpression>,
}, },
} }
impl Display for Loop { impl Display for LoopExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Loop::Infinite { block } => write!(f, "loop {}", block), LoopExpression::Infinite { block } => write!(f, "loop {}", block),
Loop::While { condition, block } => write!(f, "while {} {}", condition, block), LoopExpression::While { condition, block } => {
Loop::For { write!(f, "while {} {}", condition, block)
}
LoopExpression::For {
identifier, identifier,
iterator, iterator,
block, block,

View File

@ -10,7 +10,7 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{Identifier, Span, Type}; use crate::{Context, Identifier, Span, Type};
/// In-memory representation of a Dust program. /// In-memory representation of a Dust program.
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -69,6 +69,17 @@ impl Statement {
Statement::StructDefinition(Node::new(struct_definition, position)) Statement::StructDefinition(Node::new(struct_definition, position))
} }
pub fn return_type(&self, context: &Context) -> Option<Type> {
match self {
Statement::Expression(expression) => expression.return_type(context),
Statement::ExpressionNullified(expression_node) => {
expression_node.inner.return_type(context)
}
Statement::Let(_) => None,
Statement::StructDefinition(_) => None,
}
}
pub fn position(&self) -> Span { pub fn position(&self) -> Span {
match self { match self {
Statement::Expression(expression) => expression.position(), Statement::Expression(expression) => expression.position(),

View File

@ -757,7 +757,7 @@ impl<'src> Parser<'src> {
let position = (left.position().0, operator_end); let position = (left.position().0, operator_end);
Expression::list_index(ListIndex { list: left, index }, position) Expression::list_index(ListIndexExpression { list: left, index }, position)
} }
_ => { _ => {
return Err(ParseError::UnexpectedToken { return Err(ParseError::UnexpectedToken {
@ -834,7 +834,7 @@ impl<'src> Parser<'src> {
} }
} }
fn parse_block(&mut self) -> Result<Node<Block>, ParseError> { fn parse_block(&mut self) -> 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()?;
@ -863,9 +863,9 @@ impl<'src> Parser<'src> {
self.next_token()?; self.next_token()?;
return if is_async { return if is_async {
Ok(Node::new(Block::Async(statements), position)) Ok(Node::new(BlockExpression::Async(statements), position))
} else { } else {
Ok(Node::new(Block::Sync(statements), position)) Ok(Node::new(BlockExpression::Sync(statements), position))
}; };
} }
@ -1041,7 +1041,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree { Ok(AbstractSyntaxTree {
statements: [Statement::Expression(Expression::block( statements: [Statement::Expression(Expression::block(
Block::Async(vec![ BlockExpression::Async(vec![
Statement::ExpressionNullified(Node::new( Statement::ExpressionNullified(Node::new(
Expression::operator( Expression::operator(
OperatorExpression::Assignment { OperatorExpression::Assignment {
@ -1230,9 +1230,9 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::list_index( Statement::Expression(Expression::list_index(
ListIndex { ListIndexExpression {
list: Expression::list_index( list: Expression::list_index(
ListIndex { ListIndexExpression {
list: Expression::list( list: Expression::list(
ListExpression::Ordered(vec![ ListExpression::Ordered(vec![
Expression::literal(LiteralExpression::Integer(1), (1, 2)), Expression::literal(LiteralExpression::Integer(1), (1, 2)),
@ -1389,10 +1389,9 @@ mod tests {
IfExpression::If { IfExpression::If {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( BlockExpression::Sync(vec![Statement::Expression(
Identifier::new("y"), Expression::identifier(Identifier::new("y"), (7, 8))
(7, 8) )]),
))]),
(5, 10) (5, 10)
) )
}, },
@ -1413,17 +1412,15 @@ mod tests {
IfExpression::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( BlockExpression::Sync(vec![Statement::Expression(
Identifier::new("y"), Expression::identifier(Identifier::new("y"), (7, 8))
(7, 8) )]),
))]),
(5, 10) (5, 10)
), ),
r#else: ElseExpression::Block(Node::new( r#else: ElseExpression::Block(Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( BlockExpression::Sync(vec![Statement::Expression(
Identifier::new("z"), Expression::identifier(Identifier::new("z"), (18, 19))
(18, 19) )]),
))]),
(16, 21) (16, 21)
)) ))
}, },
@ -1444,23 +1441,22 @@ mod tests {
IfExpression::IfElse { IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("x"), (3, 4)), condition: Expression::identifier(Identifier::new("x"), (3, 4)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression(Expression::identifier( BlockExpression::Sync(vec![Statement::Expression(
Identifier::new("y"), Expression::identifier(Identifier::new("y"), (7, 8))
(7, 8) )]),
))]),
(5, 10) (5, 10)
), ),
r#else: ElseExpression::If(Node::new( r#else: ElseExpression::If(Node::new(
Box::new(IfExpression::IfElse { Box::new(IfExpression::IfElse {
condition: Expression::identifier(Identifier::new("z"), (19, 20)), condition: Expression::identifier(Identifier::new("z"), (19, 20)),
if_block: Node::new( if_block: Node::new(
Block::Sync(vec![Statement::Expression( BlockExpression::Sync(vec![Statement::Expression(
Expression::identifier(Identifier::new("a"), (23, 24)) Expression::identifier(Identifier::new("a"), (23, 24))
)]), )]),
(21, 26) (21, 26)
), ),
r#else: ElseExpression::Block(Node::new( r#else: ElseExpression::Block(Node::new(
Block::Sync(vec![Statement::Expression( BlockExpression::Sync(vec![Statement::Expression(
Expression::identifier(Identifier::new("b"), (34, 35)) Expression::identifier(Identifier::new("b"), (34, 35))
)]), )]),
(32, 37) (32, 37)
@ -1492,7 +1488,7 @@ mod tests {
(6, 12) (6, 12)
), ),
Node::new( Node::new(
Block::Sync(vec![Statement::Expression(Expression::operator( BlockExpression::Sync(vec![Statement::Expression(Expression::operator(
OperatorExpression::CompoundAssignment { OperatorExpression::CompoundAssignment {
assignee: Expression::identifier(Identifier::new("x"), (15, 16)), assignee: Expression::identifier(Identifier::new("x"), (15, 16)),
operator: Node::new(MathOperator::Add, (17, 19)), operator: Node::new(MathOperator::Add, (17, 19)),
@ -1557,7 +1553,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::block( Statement::Expression(Expression::block(
Block::Sync(vec![Statement::Expression(Expression::operator( BlockExpression::Sync(vec![Statement::Expression(Expression::operator(
OperatorExpression::Math { OperatorExpression::Math {
left: Expression::literal(LiteralExpression::Integer(40), (2, 4)), left: Expression::literal(LiteralExpression::Integer(40), (2, 4)),
operator: Node::new(MathOperator::Add, (5, 6)), operator: Node::new(MathOperator::Add, (5, 6)),
@ -1579,7 +1575,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::block( Statement::Expression(Expression::block(
Block::Sync(vec![ BlockExpression::Sync(vec![
Statement::ExpressionNullified(Node::new( Statement::ExpressionNullified(Node::new(
Expression::operator( Expression::operator(
OperatorExpression::Assignment { OperatorExpression::Assignment {
@ -1844,7 +1840,7 @@ mod tests {
parse(source), parse(source),
Ok(AbstractSyntaxTree::with_statements([ Ok(AbstractSyntaxTree::with_statements([
Statement::Expression(Expression::list_index( Statement::Expression(Expression::list_index(
ListIndex { ListIndexExpression {
list: Expression::list( list: Expression::list(
ListExpression::Ordered(vec![ ListExpression::Ordered(vec![
Expression::literal(LiteralExpression::Integer(1), (1, 2)), Expression::literal(LiteralExpression::Integer(1), (1, 2)),

View File

@ -31,6 +31,7 @@ pub struct TypeConflict {
pub enum Type { pub enum Type {
Any, Any,
Boolean, Boolean,
EmptyList,
Enum { Enum {
name: Identifier, name: Identifier,
type_parameters: Option<Vec<Type>>, type_parameters: Option<Vec<Type>>,
@ -251,6 +252,7 @@ impl Display for Type {
match self { match self {
Type::Any => write!(f, "any"), Type::Any => write!(f, "any"),
Type::Boolean => write!(f, "bool"), Type::Boolean => write!(f, "bool"),
Type::EmptyList => write!(f, "[]"),
Type::Enum { variants, .. } => { Type::Enum { variants, .. } => {
write!(f, "enum ")?; write!(f, "enum ")?;
@ -282,7 +284,7 @@ impl Display for Type {
} }
Type::Integer => write!(f, "int"), Type::Integer => write!(f, "int"),
Type::List { item_type, length } => write!(f, "[{item_type}; {length}]"), Type::List { item_type, length } => write!(f, "[{item_type}; {length}]"),
Type::ListOf { item_type } => write!(f, "list_of({item_type})"), Type::ListOf { item_type } => write!(f, "[{item_type}]"),
Type::Map(map) => { Type::Map(map) => {
write!(f, "{{ ")?; write!(f, "{{ ")?;

View File

@ -241,17 +241,17 @@ impl Value {
} }
pub fn get_field(&self, field: &Identifier) -> Option<Value> { pub fn get_field(&self, field: &Identifier) -> Option<Value> {
return match self { match self {
Value::Immutable(inner) => inner.get_field(field), Value::Immutable(inner) => inner.get_field(field),
Value::Mutable(inner) => inner.read().unwrap().get_field(field), Value::Mutable(inner) => inner.read().unwrap().get_field(field),
}; }
} }
pub fn get_index(&self, index: usize) -> Option<Value> { pub fn get_index(&self, index: usize) -> Option<Value> {
return match self { match self {
Value::Immutable(inner) => inner.get_index(index), Value::Immutable(inner) => inner.get_index(index),
Value::Mutable(inner) => inner.read().unwrap().get_index(index), Value::Mutable(inner) => inner.read().unwrap().get_index(index),
}; }
} }
pub fn add(&self, other: &Value) -> Result<Value, ValueError> { pub fn add(&self, other: &Value) -> Result<Value, ValueError> {

View File

@ -5,19 +5,20 @@
//! - `run_with_context` convenience function that takes a source code string and a context //! - `run_with_context` convenience function that takes a source code string and a context
//! - `Vm` struct that can be used to run an abstract syntax tree //! - `Vm` struct that can be used to run an abstract syntax tree
use std::{ use std::{
collections::BTreeMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
sync::{Arc, Mutex},
}; };
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
use crate::{ use crate::{
abstract_tree::{ abstract_tree::{
AbstractSyntaxTree, Block, CallExpression, ElseExpression, FieldAccess, IfExpression, AbstractSyntaxTree, BlockExpression, CallExpression, ElseExpression, FieldAccessExpression,
ListExpression, Node, Statement, IfExpression, ListExpression, ListIndexExpression, LiteralExpression, LoopExpression, Node,
OperatorExpression, Statement,
}, },
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Value, ValueError, Span, Type, Value, ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -109,7 +110,9 @@ impl Vm {
fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> { fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> {
let position = statement.position(); let position = statement.position();
let result = match statement { let result = match statement {
Statement::Expression(expression) => self.run_expression(expression), Statement::Expression(expression) => self
.run_expression(expression)
.map(|evaluation| evaluation.value()),
Statement::ExpressionNullified(expression) => { Statement::ExpressionNullified(expression) => {
self.run_expression(expression.inner)?; self.run_expression(expression.inner)?;
@ -125,15 +128,113 @@ impl Vm {
}) })
} }
fn run_expression(&self, expression: Expression) -> Result<Option<Value>, VmError> { fn run_expression(&self, expression: Expression) -> Result<Evaluation, VmError> {
let position = expression.position(); let position = expression.position();
let result = match expression { let evaluation_result = match expression {
Expression::Block(Node { inner, .. }) => self.run_block(*inner), Expression::Block(Node { inner, .. }) => self.run_block(*inner),
Expression::Call(Node { inner, .. }) => { Expression::Call(call) => self.run_call(*call.inner),
let CallExpression { invoker, arguments } = *inner; Expression::FieldAccess(field_access) => self.run_field_access(*field_access.inner),
Expression::Grouped(expression) => self.run_expression(*expression.inner),
Expression::Identifier(identifier) => self.run_identifier(identifier.inner),
Expression::If(if_expression) => self.run_if(*if_expression.inner),
Expression::List(list_expression) => self.run_list(*list_expression.inner),
Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner),
Expression::Literal(literal) => self.run_literal(*literal.inner),
Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner),
Expression::Operator(_) => todo!(),
Expression::Range(_) => todo!(),
Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(),
};
evaluation_result.map_err(|error| VmError::Trace {
error: Box::new(error),
position,
})
}
fn run_operator(&self, operator: OperatorExpression) -> Result<Evaluation, VmError> {
match operator {
OperatorExpression::Assignment { assignee, value } => todo!(),
OperatorExpression::Comparison {
left,
operator,
right,
} => todo!(),
OperatorExpression::CompoundAssignment {
assignee,
operator,
modifier,
} => todo!(),
OperatorExpression::ErrorPropagation(_) => todo!(),
OperatorExpression::Negation(_) => todo!(),
OperatorExpression::Not(_) => todo!(),
OperatorExpression::Math {
left,
operator,
right,
} => todo!(),
OperatorExpression::Logic {
left,
operator,
right,
} => todo!(),
}
}
fn run_loop(&self, loop_expression: LoopExpression) -> Result<Evaluation, VmError> {
match loop_expression {
LoopExpression::Infinite { block } => loop {
self.run_expression(Expression::block(block.inner.clone(), block.position))?;
},
LoopExpression::While { condition, block } => todo!(),
LoopExpression::For {
identifier,
iterator,
block,
} => todo!(),
}
}
fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, VmError> {
let value = match literal {
LiteralExpression::Boolean(boolean) => Value::boolean(boolean),
LiteralExpression::Float(float) => Value::float(float),
LiteralExpression::Integer(integer) => Value::integer(integer),
LiteralExpression::String(string) => Value::string(string),
LiteralExpression::Value(value) => value,
};
Ok(Evaluation::Return(Some(value)))
}
fn run_list_index(&self, list_index: ListIndexExpression) -> Result<Evaluation, VmError> {
let ListIndexExpression { list, index } = list_index;
let list_position = list.position();
let list_value = self.run_expression(list)?.expect_value(list_position)?;
let index_position = index.position();
let index_value = self.run_expression(index)?.expect_value(index_position)?;
let index = if let Some(index) = index_value.as_integer() {
index as usize
} else {
return Err(VmError::ExpectedInteger {
position: index_position,
});
};
let value_option = list_value.get_index(index);
Ok(Evaluation::Return(value_option))
}
fn run_call(&self, call_expression: CallExpression) -> Result<Evaluation, VmError> {
let CallExpression { invoker, arguments } = call_expression;
let invoker_position = invoker.position(); let invoker_position = invoker.position();
let invoker_value = if let Some(value) = self.run_expression(invoker)? { let invoker_value = if let Some(value) = self.run_expression(invoker)?.value() {
value value
} else { } else {
return Err(VmError::ExpectedValue { return Err(VmError::ExpectedValue {
@ -155,7 +256,7 @@ impl Vm {
for argument in arguments { for argument in arguments {
let position = argument.position(); let position = argument.position();
if let Some(value) = self.run_expression(argument)? { if let Some(value) = self.run_expression(argument)?.value() {
value_arguments.push(value); value_arguments.push(value);
} else { } else {
return Err(VmError::ExpectedValue { position }); return Err(VmError::ExpectedValue { position });
@ -164,13 +265,16 @@ impl Vm {
let context = Context::new(); let context = Context::new();
function.call(None, Some(value_arguments), &context) function
.call(None, Some(value_arguments), &context)
.map(|value_option| Evaluation::Return(value_option))
} }
Expression::FieldAccess(Node { inner, .. }) => {
let FieldAccess { container, field } = *inner; fn run_field_access(&self, field_access: FieldAccessExpression) -> Result<Evaluation, VmError> {
let FieldAccessExpression { container, field } = field_access;
let container_position = container.position(); let container_position = container.position();
let container_value = if let Some(value) = self.run_expression(container)? { let container_value = if let Some(value) = self.run_expression(container)?.value() {
value value
} else { } else {
return Err(VmError::ExpectedValue { return Err(VmError::ExpectedValue {
@ -178,93 +282,76 @@ impl Vm {
}); });
}; };
Ok(container_value.get_field(&field.inner)) Ok(Evaluation::Return(container_value.get_field(&field.inner)))
} }
Expression::Grouped(expression) => self.run_expression(*expression.inner),
Expression::Identifier(identifier) => { fn run_identifier(&self, identifier: Identifier) -> Result<Evaluation, VmError> {
let value_option = self.context.get_value(&identifier.inner); let value_option = self.context.get_value(&identifier);
if let Some(value) = value_option { if let Some(value) = value_option {
Ok(Some(value)) Ok(Evaluation::Return(Some(value)))
} else { } else {
Err(VmError::UndefinedVariable { identifier }) Err(VmError::UndefinedVariable { identifier })
} }
} }
Expression::If(if_expression) => self.run_if(*if_expression.inner),
Expression::List(list_expression) => self.run_list(*list_expression.inner),
Expression::ListIndex(_) => todo!(),
Expression::Literal(_) => todo!(),
Expression::Loop(_) => todo!(),
Expression::Operator(_) => todo!(),
Expression::Range(_) => todo!(),
Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(),
};
result.map_err(|error| VmError::Trace { fn run_list(&self, list_expression: ListExpression) -> Result<Evaluation, VmError> {
error: Box::new(error),
position,
})
}
fn run_list(&self, list_expression: ListExpression) -> Result<Option<Value>, VmError> {
match list_expression { match list_expression {
ListExpression::AutoFill { ListExpression::AutoFill {
repeat_operand, repeat_operand,
length_operand, length_operand,
} => { } => {
let position = length_operand.position(); let position = length_operand.position();
let length = if let Some(value) = self.run_expression(length_operand)? { let length = self
if let Some(length) = value.as_integer() { .run_expression(length_operand)?
length .expect_value(position)?
} else { .as_integer()
return Err(VmError::ExpectedInteger { position }); .ok_or(VmError::ExpectedInteger { position })?;
}
} else {
return Err(VmError::ExpectedValue { position });
};
let position = repeat_operand.position(); let position = repeat_operand.position();
let value = if let Some(value) = self.run_expression(repeat_operand)? { let value = self
value .run_expression(repeat_operand)?
} else { .expect_value(position)?;
return Err(VmError::ExpectedValue { position });
};
Ok(Some(Value::list(vec![value; length as usize]))) Ok(Evaluation::Return(Some(Value::list(vec![
value;
length as usize
]))))
} }
ListExpression::Ordered(expressions) => { ListExpression::Ordered(expressions) => {
let mut values = Vec::new(); let mut values = Vec::new();
for expression in expressions { for expression in expressions {
let position = expression.position(); let position = expression.position();
let value = self.run_expression(expression)?.expect_value(position)?;
if let Some(value) = self.run_expression(expression)? {
values.push(value); values.push(value);
} else {
return Err(VmError::ExpectedValue { position });
}
} }
Ok(Some(Value::list(values))) Ok(Evaluation::Return(Some(Value::list(values))))
} }
} }
} }
fn run_block(&self, block: Block) -> Result<Option<Value>, VmError> { fn run_block(&self, block: BlockExpression) -> Result<Evaluation, VmError> {
match block { match block {
Block::Async(statements) => { BlockExpression::Async(statements) => {
let expected_return = statements.last().unwrap().expected_type();
let final_result = Arc::new(Mutex::new(None));
let error_option = statements let error_option = statements
.into_par_iter() .into_par_iter()
.enumerate()
.find_map_any(|statement| self.run_statement(statement).err()); .find_map_any(|statement| self.run_statement(statement).err());
if let Some(error) = error_option { if let Some(error) = error_option {
Err(error) Err(error)
} else { } else {
Ok(None) Ok(Evaluation::Return(None))
} }
} }
Block::Sync(statements) => { BlockExpression::Sync(statements) => {
let mut previous_value = None; let mut previous_value = None;
for statement in statements { for statement in statements {
@ -275,61 +362,45 @@ impl Vm {
self.context.collect_garbage(position.1); self.context.collect_garbage(position.1);
} }
Ok(previous_value) Ok(Evaluation::Return(previous_value))
} }
} }
} }
fn run_if(&self, if_expression: IfExpression) -> Result<Option<Value>, VmError> { fn run_if(&self, if_expression: IfExpression) -> Result<Evaluation, VmError> {
match if_expression { match if_expression {
IfExpression::If { IfExpression::If {
condition, condition,
if_block, if_block,
} => { } => {
let condition_position = condition.position(); let position = condition.position();
let condition_value = if let Some(value) = self.run_expression(condition)? { let boolean = self
value .run_expression(condition)?
} else { .expect_value(position)?
return Err(VmError::ExpectedValue { .as_boolean()
position: condition_position, .ok_or(VmError::ExpectedBoolean { position })?;
});
};
if let Some(boolean) = condition_value.as_boolean() {
if boolean { if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?; self.run_expression(Expression::block(if_block.inner, if_block.position))?;
} }
} else {
return Err(VmError::ExpectedBoolean {
position: condition_position,
});
}
Ok(None) Ok(Evaluation::Return(None))
} }
IfExpression::IfElse { IfExpression::IfElse {
condition, condition,
if_block, if_block,
r#else, r#else,
} => { } => {
let condition_position = condition.position(); let position = condition.position();
let condition_value = if let Some(value) = self.run_expression(condition)? { let boolean = self
value .run_expression(condition)?
} else { .expect_value(position)?
return Err(VmError::ExpectedValue { .as_boolean()
position: condition_position, .ok_or(VmError::ExpectedBoolean { position })?;
});
};
if let Some(boolean) = condition_value.as_boolean() {
if boolean { if boolean {
self.run_expression(Expression::block(if_block.inner, if_block.position))?; self.run_expression(Expression::block(if_block.inner, if_block.position))?;
} }
} else {
return Err(VmError::ExpectedBoolean {
position: condition_position,
});
}
match r#else { match r#else {
ElseExpression::If(if_expression) => { ElseExpression::If(if_expression) => {
@ -344,6 +415,28 @@ impl Vm {
} }
} }
enum Evaluation {
Break,
Return(Option<Value>),
}
impl Evaluation {
pub fn value(self) -> Option<Value> {
match self {
Evaluation::Break => None,
Evaluation::Return(value_option) => value_option,
}
}
pub fn expect_value(self, position: Span) -> Result<Value, VmError> {
if let Evaluation::Return(Some(value)) = self {
Ok(value)
} else {
Err(VmError::ExpectedValue { position })
}
}
}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum VmError { pub enum VmError {
ParseError(ParseError), ParseError(ParseError),
@ -398,7 +491,7 @@ pub enum VmError {
position: Span, position: Span,
}, },
UndefinedVariable { UndefinedVariable {
identifier: Node<Identifier>, identifier: Identifier,
}, },
UndefinedProperty { UndefinedProperty {
value: Value, value: Value,
@ -408,32 +501,6 @@ pub enum VmError {
}, },
} }
impl VmError {
pub fn position(&self) -> Span {
match self {
Self::ParseError(parse_error) => parse_error.position(),
Self::Trace { position, .. } => *position,
Self::ValueError { position, .. } => *position,
Self::CannotMutate { position, .. } => *position,
Self::BuiltInFunctionError { position, .. } => *position,
Self::ExpectedBoolean { position } => *position,
Self::ExpectedIdentifier { position } => *position,
Self::ExpectedIdentifierOrString { position } => *position,
Self::ExpectedIntegerOrRange { position } => *position,
Self::ExpectedInteger { position } => *position,
Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedList { position } => *position,
Self::ExpectedMap { position } => *position,
Self::ExpectedNumber { position } => *position,
Self::ExpectedValue { position } => *position,
Self::UndefinedVariable { identifier } => identifier.position,
Self::UndefinedProperty {
property_position, ..
} => *property_position,
}
}
}
impl From<ParseError> for VmError { impl From<ParseError> for VmError {
fn from(error: ParseError) -> Self { fn from(error: ParseError) -> Self {
Self::ParseError(error) Self::ParseError(error)