Begin reimplementing the VM

This commit is contained in:
Jeff 2024-08-15 23:17:49 -04:00
parent 40b5d15b96
commit b48b5d4369
3 changed files with 281 additions and 209 deletions

View File

@ -11,60 +11,52 @@ use super::{Node, Statement};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Expression {
WithBlock(Node<Box<ExpressionWithBlock>>),
WithoutBlock(Node<Box<ExpressionWithoutBlock>>),
Block(Node<Box<Block>>),
Call(Node<Box<CallExpression>>),
FieldAccess(Node<Box<FieldAccess>>),
Grouped(Node<Box<Expression>>),
Identifier(Node<Identifier>),
If(Node<Box<If>>),
List(Node<Box<ListExpression>>),
ListIndex(Node<Box<ListIndex>>),
Literal(Node<Box<LiteralExpression>>),
Loop(Node<Box<Loop>>),
Operator(Node<Box<OperatorExpression>>),
Range(Node<Box<Range>>),
Struct(Node<Box<StructExpression>>),
TupleAccess(Node<Box<TupleAccess>>),
}
impl Expression {
pub fn operator(operator_expression: OperatorExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(operator_expression)),
position,
))
Self::Operator(Node::new(Box::new(operator_expression), position))
}
pub fn range(start: Expression, end: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Range(Range { start, end })),
position,
))
Self::Range(Node::new(Box::new(Range { start, end }), position))
}
pub fn call(invoker: Expression, arguments: Vec<Expression>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Call(CallExpression {
invoker,
arguments,
})),
Self::Call(Node::new(
Box::new(CallExpression { invoker, arguments }),
position,
))
}
pub fn field_access(container: Expression, field: Node<Identifier>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::FieldAccess(FieldAccess {
container,
field,
})),
Self::FieldAccess(Node::new(
Box::new(FieldAccess { container, field }),
position,
))
}
pub fn tuple_access(tuple: Expression, index: Node<usize>, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::TupleAccess(TupleAccess {
tuple,
index,
})),
position,
))
Self::TupleAccess(Node::new(Box::new(TupleAccess { tuple, index }), position))
}
pub fn assignment(assignee: Expression, value: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Assignment { assignee, value },
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::Assignment { assignee, value }),
position,
))
}
@ -75,14 +67,12 @@ impl Expression {
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Comparison {
left,
operator,
right,
},
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::Comparison {
left,
operator,
right,
}),
position,
))
}
@ -93,14 +83,12 @@ impl Expression {
modifier: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::CompoundAssignment {
assignee,
operator,
modifier,
},
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::CompoundAssignment {
assignee,
operator,
modifier,
}),
position,
))
}
@ -111,30 +99,26 @@ impl Expression {
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Math {
Self::Operator(Node::new(
Box::new(OperatorExpression::Math {
left,
operator,
right,
})),
}),
position,
))
}
pub fn negation(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Negation(expression),
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::Negation(expression)),
position,
))
}
pub fn not(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(OperatorExpression::Not(
expression,
))),
Self::Operator(Node::new(
Box::new(OperatorExpression::Not(expression)),
position,
))
}
@ -145,37 +129,30 @@ impl Expression {
right: Expression,
position: Span,
) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::Logic {
left,
operator,
right,
},
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::Logic {
left,
operator,
right,
}),
position,
))
}
pub fn error_propagation(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Operator(
OperatorExpression::ErrorPropagation(expression),
)),
Self::Operator(Node::new(
Box::new(OperatorExpression::ErrorPropagation(expression)),
position,
))
}
pub fn infinite_loop(block: Node<Block>, position: Span) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(Loop::Infinite { block })),
position,
))
Self::Loop(Node::new(Box::new(Loop::Infinite { block }), position))
}
pub fn while_loop(condition: Expression, block: Node<Block>, position: Span) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(Loop::While { condition, block })),
Self::Loop(Node::new(
Box::new(Loop::While { condition, block }),
position,
))
}
@ -186,82 +163,51 @@ impl Expression {
block: Node<Block>,
position: Span,
) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Loop(Loop::For {
Self::Loop(Node::new(
Box::new(Loop::For {
identifier,
iterator,
block,
})),
}),
position,
))
}
pub fn block(block: Block, position: Span) -> Self {
Expression::WithBlock(Node::new(
Box::new(ExpressionWithBlock::Block(block)),
position,
))
Self::Block(Node::new(Box::new(block), position))
}
pub fn grouped(expression: Expression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Grouped(expression)),
position,
))
Self::Grouped(Node::new(Box::new(expression), position))
}
pub fn r#struct(struct_expression: StructExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Struct(struct_expression)),
position,
))
Self::Struct(Node::new(Box::new(struct_expression), position))
}
pub fn identifier(identifier: Identifier, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Identifier(identifier)),
position,
))
Self::Identifier(Node::new(identifier, position))
}
pub fn list(list_expression: ListExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::List(list_expression)),
position,
))
Self::List(Node::new(Box::new(list_expression), position))
}
pub fn list_index(list_index: ListIndex, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::ListIndex(list_index)),
position,
))
Self::ListIndex(Node::new(Box::new(list_index), position))
}
pub fn r#if(r#if: If, position: Span) -> Self {
Expression::WithBlock(Node::new(Box::new(ExpressionWithBlock::If(r#if)), position))
Self::If(Node::new(Box::new(r#if), position))
}
pub fn literal(literal: LiteralExpression, position: Span) -> Self {
Expression::WithoutBlock(Node::new(
Box::new(ExpressionWithoutBlock::Literal(literal)),
position,
))
Self::Literal(Node::new(Box::new(literal), position))
}
pub fn as_identifier(&self) -> Option<&Identifier> {
if let Expression::WithoutBlock(Node {
inner: expression_without_block,
..
}) = self
{
if let ExpressionWithoutBlock::Identifier(identifier) =
expression_without_block.as_ref()
{
Some(identifier)
} else {
None
}
if let Expression::Identifier(identifier) = self {
Some(&identifier.inner)
} else {
None
}
@ -269,8 +215,20 @@ impl Expression {
pub fn position(&self) -> Span {
match self {
Expression::WithBlock(expression_node) => expression_node.position,
Expression::WithoutBlock(expression_node) => expression_node.position,
Expression::Block(block) => block.position,
Expression::Call(call) => call.position,
Expression::FieldAccess(field_access) => field_access.position,
Expression::Grouped(grouped) => grouped.position,
Expression::Identifier(identifier) => identifier.position,
Expression::If(r#if) => r#if.position,
Expression::List(list) => list.position,
Expression::ListIndex(list_index) => list_index.position,
Expression::Literal(literal) => literal.position,
Expression::Loop(r#loop) => r#loop.position,
Expression::Operator(operator) => operator.position,
Expression::Range(range) => range.position,
Expression::Struct(r#struct) => r#struct.position,
Expression::TupleAccess(tuple_access) => tuple_access.position,
}
}
}
@ -278,58 +236,20 @@ impl Expression {
impl Display for Expression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Expression::WithBlock(expression) => write!(f, "{}", expression),
Expression::WithoutBlock(expression) => write!(f, "{}", expression),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ExpressionWithBlock {
Block(Block),
Loop(Loop),
If(If),
}
impl Display for ExpressionWithBlock {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
ExpressionWithBlock::Block(block) => write!(f, "{}", block),
ExpressionWithBlock::Loop(r#loop) => write!(f, "{}", r#loop),
ExpressionWithBlock::If(r#if) => write!(f, "{}", r#if),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ExpressionWithoutBlock {
Call(CallExpression),
List(ListExpression),
Literal(LiteralExpression),
Identifier(Identifier),
Operator(OperatorExpression),
Struct(StructExpression),
Grouped(Expression),
FieldAccess(FieldAccess),
ListIndex(ListIndex),
Range(Range),
TupleAccess(TupleAccess),
}
impl Display for ExpressionWithoutBlock {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
ExpressionWithoutBlock::Call(call_expression) => write!(f, "{}", call_expression),
ExpressionWithoutBlock::List(list) => write!(f, "{}", list),
ExpressionWithoutBlock::Literal(literal) => write!(f, "{}", literal),
ExpressionWithoutBlock::Identifier(identifier) => write!(f, "{}", identifier),
ExpressionWithoutBlock::Operator(expression) => write!(f, "{}", expression),
ExpressionWithoutBlock::Struct(struct_expression) => write!(f, "{}", struct_expression),
ExpressionWithoutBlock::Grouped(expression) => write!(f, "({})", expression),
ExpressionWithoutBlock::FieldAccess(field_access) => write!(f, "{}", field_access),
ExpressionWithoutBlock::ListIndex(list_index) => write!(f, "{}", list_index),
ExpressionWithoutBlock::Range(range) => write!(f, "{}", range),
ExpressionWithoutBlock::TupleAccess(tuple_access) => write!(f, "{}", tuple_access),
Expression::Block(block) => write!(f, "{}", block.inner),
Expression::Call(call) => write!(f, "{}", call.inner),
Expression::FieldAccess(field_access) => write!(f, "{}", field_access.inner),
Expression::Grouped(grouped) => write!(f, "({})", grouped.inner),
Expression::Identifier(identifier) => write!(f, "{}", identifier.inner),
Expression::If(r#if) => write!(f, "{}", r#if.inner),
Expression::List(list) => write!(f, "{}", list.inner),
Expression::ListIndex(list_index) => write!(f, "{}", list_index.inner),
Expression::Literal(literal) => write!(f, "{}", literal.inner),
Expression::Loop(r#loop) => write!(f, "{}", r#loop.inner),
Expression::Operator(operator) => write!(f, "{}", operator.inner),
Expression::Range(range) => write!(f, "{}", range),
Expression::Struct(r#struct) => write!(f, "{}", r#struct.inner),
Expression::TupleAccess(tuple_access) => write!(f, "{}", tuple_access),
}
}
}

View File

@ -5,7 +5,7 @@ use std::{
error::Error,
fmt::{self, Display, Formatter},
ops::Range,
sync::{Arc, RwLock},
sync::{Arc, RwLock, RwLockWriteGuard},
};
use serde::{
@ -135,13 +135,6 @@ impl Value {
}
}
pub fn get_property(&self, property: &Identifier) -> Option<Value> {
match self {
Value::Immutable(inner) => inner.get_property(property),
Value::Mutable(inner_locked) => inner_locked.read().unwrap().get_property(property),
}
}
pub fn as_boolean(&self) -> Option<bool> {
match self {
Value::Immutable(arc) => match arc.as_ref() {
@ -211,16 +204,6 @@ impl Value {
}
}
pub fn as_range(&self) -> Option<&Range<i64>> {
if let Value::Immutable(arc) = self {
if let ValueData::Range(range) = arc.as_ref() {
return Some(range);
}
}
None
}
pub fn as_string(&self) -> Option<&String> {
if let Value::Immutable(arc) = self {
if let ValueData::String(string) = arc.as_ref() {
@ -231,6 +214,46 @@ impl Value {
None
}
pub fn as_struct(&self) -> Option<&Struct> {
if let Value::Immutable(arc) = self {
if let ValueData::Struct(r#struct) = arc.as_ref() {
return Some(r#struct);
}
}
None
}
pub fn value_data_immutable(&self) -> Option<&ValueData> {
if let Value::Immutable(inner) = self {
Some(inner.as_ref())
} else {
None
}
}
pub fn value_data_mutable(&self) -> Option<RwLockWriteGuard<ValueData>> {
if let Value::Mutable(inner) = self {
Some(inner.write().unwrap())
} else {
None
}
}
pub fn get_field(&self, field: &Identifier) -> Option<Value> {
return match self {
Value::Immutable(inner) => inner.get_field(field),
Value::Mutable(inner) => inner.read().unwrap().get_field(field),
};
}
pub fn get_index(&self, index: usize) -> Option<Value> {
return match self {
Value::Immutable(inner) => inner.get_index(index),
Value::Mutable(inner) => inner.read().unwrap().get_index(index),
};
}
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) {
(Value::Immutable(left), Value::Immutable(right)) => {
@ -998,19 +1021,44 @@ impl ValueData {
}
}
fn get_property(&self, property: &Identifier) -> Option<Value> {
match self {
ValueData::List(list) => {
if property.as_str() == "length" {
Some(Value::integer(list.len() as i64))
fn get_field(&self, property: &Identifier) -> Option<Value> {
if let ValueData::Struct(Struct::Fields { fields, .. }) = self {
fields.iter().find_map(|(identifier, value)| {
if identifier == property {
Some(value.clone())
} else {
None
}
}
ValueData::Map(value_map) => value_map.get(property).cloned(),
_ => None,
})
} else {
None
}
}
fn get_index(&self, index: usize) -> Option<Value> {
if let ValueData::List(list) = self {
return list.get(index).cloned();
}
if let ValueData::Range(range) = self {
if range.contains(&(index as i64)) {
return Some(Value::integer(index as i64));
}
}
if let ValueData::String(string) = self {
return string
.chars()
.nth(index)
.map(|character| Value::string(character.to_string()));
}
if let ValueData::Struct(Struct::Tuple { fields, .. }) = self {
return fields.get(index).cloned();
}
None
}
}
impl Display for ValueData {
@ -1407,7 +1455,7 @@ pub struct Function {
impl Function {
pub fn call(
self,
&self,
_type_arguments: Option<Vec<Type>>,
value_arguments: Option<Vec<Value>>,
context: &Context,
@ -1415,14 +1463,14 @@ impl Function {
let new_context = Context::with_variables_from(context);
if let (Some(value_parameters), Some(value_arguments)) =
(self.value_parameters, value_arguments)
(&self.value_parameters, value_arguments)
{
for ((identifier, _), value) in value_parameters.into_iter().zip(value_arguments) {
new_context.set_value(identifier, value);
new_context.set_value(identifier.clone(), value);
}
}
let mut vm = Vm::new(self.body, new_context);
let mut vm = Vm::new(self.body.clone(), new_context);
vm.run()
}

View File

@ -9,10 +9,12 @@ use std::{
fmt::{self, Display, Formatter},
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::{
abstract_tree::{AbstractSyntaxTree, Node, Statement},
parse, Analyzer, BuiltInFunctionError, Context, DustError, Identifier, ParseError, Span,
Struct, StructType, Type, Value, ValueError,
abstract_tree::{AbstractSyntaxTree, Block, CallExpression, FieldAccess, Node, Statement},
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Struct, StructType, Type, Value, ValueError,
};
/// Run the source code and return the result.
@ -101,8 +103,110 @@ impl Vm {
Ok(previous_value)
}
fn run_statement(&self, node: Statement) -> Result<Option<Value>, VmError> {
todo!()
fn run_statement(&self, statement: Statement) -> Result<Option<Value>, VmError> {
match statement {
Statement::Expression(expression) => self.run_expression(expression),
Statement::ExpressionNullified(expression) => {
self.run_expression(expression.inner)?;
Ok(None)
}
Statement::Let(_) => todo!(),
Statement::StructDefinition(_) => todo!(),
}
}
fn run_expression(&self, expression: Expression) -> Result<Option<Value>, VmError> {
match expression {
Expression::Block(Node { inner, position }) => match *inner {
Block::Async(statements) => {
let error_option = statements
.into_par_iter()
.find_map_any(|statement| self.run_statement(statement).err());
if let Some(error) = error_option {
Err(error)
} else {
Ok(None)
}
}
Block::Sync(statements) => {
let mut previous_value = None;
for statement in statements {
let position = statement.position();
previous_value = self.run_statement(statement)?;
self.context.collect_garbage(position.1);
}
Ok(previous_value)
}
},
Expression::Call(Node { inner, .. }) => {
let CallExpression { invoker, arguments } = *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(_) => todo!(),
Expression::Identifier(_) => todo!(),
Expression::If(_) => todo!(),
Expression::List(_) => todo!(),
Expression::ListIndex(_) => todo!(),
Expression::Literal(_) => todo!(),
Expression::Loop(_) => todo!(),
Expression::Operator(_) => todo!(),
Expression::Range(_) => todo!(),
Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(),
}
}
}