Implement VM
This commit is contained in:
parent
26348fb82e
commit
bfb07047a5
@ -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,
|
||||||
|
@ -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(),
|
||||||
|
@ -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)),
|
||||||
|
@ -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, "{{ ")?;
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
@ -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,146 +128,230 @@ 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),
|
||||||
|
|
||||||
let invoker_position = invoker.position();
|
|
||||||
let invoker_value = if let Some(value) = self.run_expression(invoker)? {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(VmError::ExpectedValue {
|
|
||||||
position: invoker_position,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let function = if let Some(function) = invoker_value.as_function() {
|
|
||||||
function
|
|
||||||
} else {
|
|
||||||
return Err(VmError::ExpectedFunction {
|
|
||||||
actual: invoker_value,
|
|
||||||
position: invoker_position,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut value_arguments = Vec::new();
|
|
||||||
|
|
||||||
for argument in arguments {
|
|
||||||
let position = argument.position();
|
|
||||||
|
|
||||||
if let Some(value) = self.run_expression(argument)? {
|
|
||||||
value_arguments.push(value);
|
|
||||||
} else {
|
|
||||||
return Err(VmError::ExpectedValue { position });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = Context::new();
|
|
||||||
|
|
||||||
function.call(None, Some(value_arguments), &context)
|
|
||||||
}
|
|
||||||
Expression::FieldAccess(Node { inner, .. }) => {
|
|
||||||
let FieldAccess { container, field } = *inner;
|
|
||||||
|
|
||||||
let container_position = container.position();
|
|
||||||
let container_value = if let Some(value) = self.run_expression(container)? {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return Err(VmError::ExpectedValue {
|
|
||||||
position: container_position,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(container_value.get_field(&field.inner))
|
|
||||||
}
|
|
||||||
Expression::Grouped(expression) => self.run_expression(*expression.inner),
|
Expression::Grouped(expression) => self.run_expression(*expression.inner),
|
||||||
Expression::Identifier(identifier) => {
|
Expression::Identifier(identifier) => self.run_identifier(identifier.inner),
|
||||||
let value_option = self.context.get_value(&identifier.inner);
|
|
||||||
|
|
||||||
if let Some(value) = value_option {
|
|
||||||
Ok(Some(value))
|
|
||||||
} else {
|
|
||||||
Err(VmError::UndefinedVariable { identifier })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression::If(if_expression) => self.run_if(*if_expression.inner),
|
Expression::If(if_expression) => self.run_if(*if_expression.inner),
|
||||||
Expression::List(list_expression) => self.run_list(*list_expression.inner),
|
Expression::List(list_expression) => self.run_list(*list_expression.inner),
|
||||||
Expression::ListIndex(_) => todo!(),
|
Expression::ListIndex(list_index) => self.run_list_index(*list_index.inner),
|
||||||
Expression::Literal(_) => todo!(),
|
Expression::Literal(literal) => self.run_literal(*literal.inner),
|
||||||
Expression::Loop(_) => todo!(),
|
Expression::Loop(loop_expression) => self.run_loop(*loop_expression.inner),
|
||||||
Expression::Operator(_) => todo!(),
|
Expression::Operator(_) => todo!(),
|
||||||
Expression::Range(_) => todo!(),
|
Expression::Range(_) => todo!(),
|
||||||
Expression::Struct(_) => todo!(),
|
Expression::Struct(_) => todo!(),
|
||||||
Expression::TupleAccess(_) => todo!(),
|
Expression::TupleAccess(_) => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
result.map_err(|error| VmError::Trace {
|
evaluation_result.map_err(|error| VmError::Trace {
|
||||||
error: Box::new(error),
|
error: Box::new(error),
|
||||||
position,
|
position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_list(&self, list_expression: ListExpression) -> Result<Option<Value>, VmError> {
|
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_value = if let Some(value) = self.run_expression(invoker)?.value() {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: invoker_position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let function = if let Some(function) = invoker_value.as_function() {
|
||||||
|
function
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedFunction {
|
||||||
|
actual: invoker_value,
|
||||||
|
position: invoker_position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut value_arguments = Vec::new();
|
||||||
|
|
||||||
|
for argument in arguments {
|
||||||
|
let position = argument.position();
|
||||||
|
|
||||||
|
if let Some(value) = self.run_expression(argument)?.value() {
|
||||||
|
value_arguments.push(value);
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue { position });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
|
function
|
||||||
|
.call(None, Some(value_arguments), &context)
|
||||||
|
.map(|value_option| Evaluation::Return(value_option))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_field_access(&self, field_access: FieldAccessExpression) -> Result<Evaluation, VmError> {
|
||||||
|
let FieldAccessExpression { container, field } = field_access;
|
||||||
|
|
||||||
|
let container_position = container.position();
|
||||||
|
let container_value = if let Some(value) = self.run_expression(container)?.value() {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: container_position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Evaluation::Return(container_value.get_field(&field.inner)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_identifier(&self, identifier: Identifier) -> Result<Evaluation, VmError> {
|
||||||
|
let value_option = self.context.get_value(&identifier);
|
||||||
|
|
||||||
|
if let Some(value) = value_option {
|
||||||
|
Ok(Evaluation::Return(Some(value)))
|
||||||
|
} else {
|
||||||
|
Err(VmError::UndefinedVariable { identifier })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_list(&self, list_expression: ListExpression) -> Result<Evaluation, 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,60 +362,44 @@ 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 {
|
||||||
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user