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> {
match self {
Statement::Expression(expression) => expression.return_type(context),
Statement::ExpressionNullified(expression) => None,
Statement::ExpressionNullified(_) => None,
Statement::Let(_) => None,
Statement::StructDefinition(_) => None,
}
@ -42,9 +42,37 @@ impl Display for Statement {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Statement::Expression(expression) => write!(f, "{}", expression),
Statement::ExpressionNullified(expression) => write!(f, "{}", expression),
Statement::Let(r#let) => write!(f, "{}", r#let),
Statement::StructDefinition(definition) => write!(f, "{}", definition),
Statement::ExpressionNullified(expression) => write!(f, "{};", expression),
Statement::Let(r#let) => write!(f, "{};", r#let),
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};
@ -11,6 +14,16 @@ pub enum Constructor {
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)]
pub struct UnitConstructor {
pub name: Identifier,

View File

@ -108,7 +108,7 @@ impl Context {
/// Associates a constructor with an identifier.
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();
@ -130,7 +130,7 @@ impl Context {
struct_type: StructType,
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();

View File

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

View File

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