Pass VM test

This commit is contained in:
Jeff 2024-08-20 03:28:13 -04:00
parent fab66a4877
commit d5c2ae92c9
5 changed files with 98 additions and 29 deletions

View File

@ -31,7 +31,7 @@ impl Statement {
pub fn return_type(&self, context: &Context) -> Option<Type> { pub fn return_type(&self, context: &Context) -> Option<Type> {
match self { match self {
Statement::Expression(expression) => expression.return_type(context), Statement::Expression(expression) => expression.return_type(context),
Statement::ExpressionNullified(expression) => None, Statement::ExpressionNullified(_) => None,
Statement::Let(_) => None, Statement::Let(_) => None,
Statement::StructDefinition(_) => None, Statement::StructDefinition(_) => None,
} }
@ -42,9 +42,37 @@ impl Display for Statement {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Statement::Expression(expression) => write!(f, "{}", expression), Statement::Expression(expression) => write!(f, "{}", expression),
Statement::ExpressionNullified(expression) => write!(f, "{}", expression), Statement::ExpressionNullified(expression) => write!(f, "{};", expression),
Statement::Let(r#let) => write!(f, "{}", r#let), Statement::Let(r#let) => write!(f, "{};", r#let),
Statement::StructDefinition(definition) => write!(f, "{}", definition), Statement::StructDefinition(struct_definition) => match &struct_definition.inner {
StructDefinition::Unit { name } => write!(f, "struct {};", name),
StructDefinition::Tuple { name, items } => {
write!(f, "struct {name} {{ ")?;
for (index, item) in items.iter().enumerate() {
write!(f, "{}: {}", item, index)?;
if index < items.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " }}")
}
StructDefinition::Fields { name, fields } => {
write!(f, "struct {name} {{ ")?;
for (index, (field, r#type)) in fields.iter().enumerate() {
write!(f, "{}: {}", field, r#type)?;
if index < fields.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, " }}")
}
},
} }
} }
} }

View File

@ -1,4 +1,7 @@
use std::collections::HashMap; use std::{
collections::HashMap,
fmt::{self, Display, Formatter},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -11,6 +14,16 @@ pub enum Constructor {
Fields(FieldsConstructor), Fields(FieldsConstructor),
} }
impl Display for Constructor {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Constructor::Unit(unit) => write!(f, "{}", unit.name),
Constructor::Tuple(tuple) => write!(f, "{}", tuple.name),
Constructor::Fields(fields) => write!(f, "{}", fields.name),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct UnitConstructor { pub struct UnitConstructor {
pub name: Identifier, pub name: Identifier,

View File

@ -108,7 +108,7 @@ impl Context {
/// Associates a constructor with an identifier. /// Associates a constructor with an identifier.
pub fn set_constructor(&self, identifier: Identifier, constructor: Constructor) { pub fn set_constructor(&self, identifier: Identifier, constructor: Constructor) {
log::trace!("Setting {identifier} to constructor {constructor:?}"); log::trace!("Setting {identifier} to constructor {constructor}");
let mut variables = self.variables.write().unwrap(); let mut variables = self.variables.write().unwrap();
@ -130,7 +130,7 @@ impl Context {
struct_type: StructType, struct_type: StructType,
position: Span, position: Span,
) { ) {
log::trace!("Setting {identifier} to constructor of type {struct_type:?}"); log::trace!("Setting {identifier} to constructor of type {struct_type}");
let mut variables = self.variables.write().unwrap(); let mut variables = self.variables.write().unwrap();

View File

@ -13,14 +13,13 @@ use std::{
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::HashMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
rc::Weak,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
constructor::{FieldsConstructor, TupleConstructor, UnitConstructor}, constructor::{FieldsConstructor, TupleConstructor, UnitConstructor},
Constructor, Enum, Identifier, Struct, Value, Constructor, Identifier,
}; };
/// Description of a kind of value. /// Description of a kind of value.

View File

@ -7,7 +7,6 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
primitive,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -21,8 +20,8 @@ use crate::{
OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span,
Statement, StructDefinition, StructExpression, Statement, StructDefinition, StructExpression,
}, },
parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, Enum, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError,
EnumType, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -109,6 +108,8 @@ impl Vm {
statement: Statement, statement: Statement,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Option<Value>, RuntimeError> { ) -> Result<Option<Value>, RuntimeError> {
log::debug!("Running statement: {}", statement);
let position = statement.position(); let position = statement.position();
let result = match statement { let result = match statement {
Statement::Expression(expression) => self Statement::Expression(expression) => self
@ -211,6 +212,8 @@ impl Vm {
expression: Expression, expression: Expression,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
log::debug!("Running expression: {}", expression);
let position = expression.position(); let position = expression.position();
let evaluation_result = match expression { let evaluation_result = match expression {
Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage), Expression::Block(Node { inner, .. }) => self.run_block(*inner, collect_garbage),
@ -222,13 +225,19 @@ impl Vm {
self.run_expression(*expression.inner, collect_garbage) self.run_expression(*expression.inner, collect_garbage)
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
log::debug!("Running identifier: {}", identifier.inner);
let get_data = self.context.get_data(&identifier.inner); let get_data = self.context.get_data(&identifier.inner);
if let Some(ContextData::VariableValue(value)) = get_data { if let Some(ContextData::VariableValue(value)) = get_data {
return Ok(Evaluation::Return(Some(value.clone()))); return Ok(Evaluation::Return(Some(value)));
} }
if let Some(ContextData::Constructor(constructor)) = get_data { if let Some(ContextData::Constructor(constructor)) = get_data {
if let Constructor::Unit(unit_constructor) = constructor {
return Ok(Evaluation::Return(Some(unit_constructor.construct())));
}
return Ok(Evaluation::Constructor(constructor)); return Ok(Evaluation::Constructor(constructor));
} }
@ -270,6 +279,8 @@ impl Vm {
struct_expression: StructExpression, struct_expression: StructExpression,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
log::debug!("Running struct expression: {struct_expression}");
match struct_expression { match struct_expression {
StructExpression::Unit { name } => { StructExpression::Unit { name } => {
let position = name.position; let position = name.position;
@ -678,14 +689,19 @@ impl Vm {
call_expression: CallExpression, call_expression: CallExpression,
collect_garbage: bool, collect_garbage: bool,
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
log::debug!("Running call expression: {call_expression}");
let CallExpression { invoker, arguments } = call_expression; let CallExpression { invoker, arguments } = call_expression;
let invoker_position = invoker.position(); let invoker_position = invoker.position();
let run_invoker = self.run_expression(invoker, collect_garbage)?; let run_invoker = self.run_expression(invoker, collect_garbage)?;
match run_invoker { match run_invoker {
Evaluation::Constructor(constructor) => { Evaluation::Constructor(constructor) => match constructor {
if let Constructor::Tuple(tuple_constructor) = constructor { Constructor::Unit(unit_constructor) => {
Ok(Evaluation::Return(Some(unit_constructor.construct())))
}
Constructor::Tuple(tuple_constructor) => {
let mut fields = Vec::new(); let mut fields = Vec::new();
for argument in arguments { for argument in arguments {
@ -701,9 +717,12 @@ impl Vm {
let tuple = tuple_constructor.construct(fields); let tuple = tuple_constructor.construct(fields);
return Ok(Evaluation::Return(Some(tuple))); Ok(Evaluation::Return(Some(tuple)))
} }
Constructor::Fields(_) => {
todo!("Return an error")
} }
},
Evaluation::Return(Some(value)) => { Evaluation::Return(Some(value)) => {
let function = if let Value::Function(function) = value { let function = if let Value::Function(function) = value {
function function
@ -718,26 +737,23 @@ impl Vm {
for argument in arguments { for argument in arguments {
let position = argument.position(); let position = argument.position();
let value = self
.run_expression(argument, collect_garbage)?
.expect_value(position)?;
if let Some(value) = self.run_expression(argument, collect_garbage)?.value() {
value_arguments.push(value); value_arguments.push(value);
} else {
return Err(RuntimeError::ExpectedValue { position });
}
} }
let context = Context::new(); let context = Context::new();
return function function
.call(None, Some(value_arguments), &context) .call(None, Some(value_arguments), &context)
.map(Evaluation::Return); .map(Evaluation::Return)
} }
_ => (), _ => Err(RuntimeError::ExpectedValueOrConstructor {
}
Err(RuntimeError::ExpectedValue {
position: invoker_position, position: invoker_position,
}) }),
}
} }
fn run_field_access( fn run_field_access(
@ -998,6 +1014,9 @@ pub enum RuntimeError {
ExpectedValue { ExpectedValue {
position: Span, position: Span,
}, },
ExpectedValueOrConstructor {
position: Span,
},
InvalidRange { InvalidRange {
start_position: Span, start_position: Span,
end_position: Span, end_position: Span,
@ -1050,6 +1069,7 @@ impl RuntimeError {
} => (start_position.0, end_position.1), } => (start_position.0, end_position.1),
Self::UndefinedType { position, .. } => *position, Self::UndefinedType { position, .. } => *position,
Self::UndefinedValue { position, .. } => *position, Self::UndefinedValue { position, .. } => *position,
Self::ExpectedValueOrConstructor { position } => *position,
Self::UndefinedProperty { Self::UndefinedProperty {
property_position, .. property_position, ..
} => *property_position, } => *property_position,
@ -1169,6 +1189,13 @@ impl Display for RuntimeError {
Self::ExpectedValue { position } => { Self::ExpectedValue { position } => {
write!(f, "Expected a value at position: {:?}", position) write!(f, "Expected a value at position: {:?}", position)
} }
Self::ExpectedValueOrConstructor { position } => {
write!(
f,
"Expected a value or constructor at position: {:?}",
position
)
}
Self::InvalidRange { Self::InvalidRange {
start_position, start_position,
end_position, end_position,
@ -1291,6 +1318,8 @@ mod tests {
#[test] #[test]
fn assign_unit_struct_variable() { fn assign_unit_struct_variable() {
env_logger::builder().is_test(true).try_init().unwrap();
let input = " let input = "
struct Foo; struct Foo;
let x = Foo; let x = Foo;