1
0

Pass VM test

This commit is contained in:
Jeff 2024-08-20 02:25:22 -04:00
parent e3d821a1c3
commit fab66a4877
7 changed files with 265 additions and 269 deletions

View File

@ -86,8 +86,6 @@ impl<'a> Analyzer<'a> {
Statement::Let(let_statement) => match &let_statement.inner { Statement::Let(let_statement) => match &let_statement.inner {
LetStatement::Let { identifier, value } LetStatement::Let { identifier, value }
| LetStatement::LetMut { identifier, value } => { | LetStatement::LetMut { identifier, value } => {
self.analyze_expression(value)?;
let r#type = value.return_type(self.context); let r#type = value.return_type(self.context);
if let Some(r#type) = r#type { if let Some(r#type) = r#type {
@ -98,31 +96,35 @@ impl<'a> Analyzer<'a> {
); );
} else { } else {
return Err(AnalysisError::ExpectedValueFromExpression { return Err(AnalysisError::ExpectedValueFromExpression {
actual: value.clone(), expression: value.clone(),
found_type: r#type,
}); });
} }
self.analyze_expression(value)?;
} }
LetStatement::LetType { .. } => todo!(), LetStatement::LetType { .. } => todo!(),
LetStatement::LetMutType { .. } => todo!(), LetStatement::LetMutType { .. } => todo!(),
}, },
Statement::StructDefinition(struct_definition) => { Statement::StructDefinition(struct_definition) => match &struct_definition.inner {
let (name, struct_type) = match &struct_definition.inner { StructDefinition::Unit { name } => self.context.set_constructor_type(
StructDefinition::Unit { name } => ( name.inner.clone(),
name, StructType::Unit {
Type::Struct(StructType::Unit {
name: name.inner.clone(), name: name.inner.clone(),
}), },
name.position,
), ),
StructDefinition::Tuple { name, items } => { StructDefinition::Tuple { name, items } => {
let fields = items.iter().map(|item| item.inner.clone()).collect(); let fields = items.iter().map(|item| item.inner.clone()).collect();
( self.context.set_constructor_type(
name, name.inner.clone(),
Type::Struct(StructType::Tuple { StructType::Tuple {
name: name.inner.clone(), name: name.inner.clone(),
fields, fields,
}), },
) name.position,
);
} }
StructDefinition::Fields { name, fields } => { StructDefinition::Fields { name, fields } => {
let fields = fields let fields = fields
@ -132,18 +134,16 @@ impl<'a> Analyzer<'a> {
}) })
.collect(); .collect();
( self.context.set_constructor_type(
name, name.inner.clone(),
Type::Struct(StructType::Fields { StructType::Fields {
name: name.inner.clone(), name: name.inner.clone(),
fields, fields,
}), },
) name.position,
} );
};
todo!("Set constructor")
} }
},
} }
Ok(()) Ok(())
@ -240,18 +240,20 @@ impl<'a> Analyzer<'a> {
if expected_type.is_none() { if expected_type.is_none() {
return Err(AnalysisError::ExpectedValueFromExpression { return Err(AnalysisError::ExpectedValueFromExpression {
actual: assignee.clone(), expression: assignee.clone(),
found_type: expected_type,
}); });
} }
if actual_type.is_none() { if actual_type.is_none() {
return Err(AnalysisError::ExpectedValueFromExpression { return Err(AnalysisError::ExpectedValueFromExpression {
actual: modifier.clone(), expression: modifier.clone(),
found_type: actual_type,
}); });
} }
if let (Some(expected_type), Some(actual_type)) = (expected_type, actual_type) { if let (Some(expected_type), Some(actual_type)) = (expected_type, actual_type) {
expected_type.check(&actual_type).map_err(|type_conflct| { expected_type.check(&actual_type).map_err(|_| {
AnalysisError::TypeConflict { AnalysisError::TypeConflict {
actual_expression: modifier.clone(), actual_expression: modifier.clone(),
actual_type, actual_type,
@ -288,14 +290,16 @@ impl<'a> Analyzer<'a> {
}, },
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() {
StructExpression::Unit { name } => { StructExpression::Unit { name } => {
todo!("Update constructor position"); self.context
.update_last_position(&name.inner, name.position);
} }
StructExpression::Fields { name, fields } => { StructExpression::Fields { name, fields } => {
todo!("Update constructor position"); self.context
.update_last_position(&name.inner, name.position);
// for (_, expression) in fields { for (_, expression) in fields {
// self.analyze_expression(expression)?; self.analyze_expression(expression)?;
// } }
} }
}, },
Expression::TupleAccess(tuple_access) => { Expression::TupleAccess(tuple_access) => {
@ -381,7 +385,8 @@ pub enum AnalysisError {
actual: Statement, actual: Statement,
}, },
ExpectedValueFromExpression { ExpectedValueFromExpression {
actual: Expression, expression: Expression,
found_type: Option<Type>,
}, },
ExpectedValueArgumentCount { ExpectedValueArgumentCount {
expected: usize, expected: usize,
@ -426,7 +431,7 @@ impl AnalysisError {
AnalysisError::ExpectedIntegerOrRange { actual } => actual.position(), AnalysisError::ExpectedIntegerOrRange { actual } => actual.position(),
AnalysisError::ExpectedList { actual } => actual.position(), AnalysisError::ExpectedList { actual } => actual.position(),
AnalysisError::ExpectedMap { actual } => actual.position(), AnalysisError::ExpectedMap { actual } => actual.position(),
AnalysisError::ExpectedValueFromExpression { actual } => actual.position(), AnalysisError::ExpectedValueFromExpression { expression, .. } => expression.position(),
AnalysisError::ExpectedValueFromStatement { actual } => actual.position(), AnalysisError::ExpectedValueFromStatement { actual } => actual.position(),
AnalysisError::ExpectedValueArgumentCount { position, .. } => *position, AnalysisError::ExpectedValueArgumentCount { position, .. } => *position,
AnalysisError::IndexOutOfBounds { index, .. } => index.position(), AnalysisError::IndexOutOfBounds { index, .. } => index.position(),
@ -461,11 +466,14 @@ impl Display for AnalysisError {
} }
AnalysisError::ExpectedList { actual } => write!(f, "Expected list, found {}", actual), AnalysisError::ExpectedList { actual } => write!(f, "Expected list, found {}", actual),
AnalysisError::ExpectedMap { actual } => write!(f, "Expected map, found {}", actual), AnalysisError::ExpectedMap { actual } => write!(f, "Expected map, found {}", actual),
AnalysisError::ExpectedValueFromExpression { actual, .. } => { AnalysisError::ExpectedValueFromExpression {
expression,
found_type,
} => {
write!( write!(
f, f,
"Expected expression to produce a value, found {}", "Expected {} to produce a value, found {:?}",
actual expression, found_type
) )
} }
AnalysisError::ExpectedValueFromStatement { actual, .. } => { AnalysisError::ExpectedValueFromStatement { actual, .. } => {

View File

@ -297,7 +297,7 @@ impl Expression {
} }
} }
Expression::Grouped(expression) => expression.inner.return_type(context), Expression::Grouped(expression) => expression.inner.return_type(context),
Expression::Identifier(identifier) => context.get_variable_type(&identifier.inner), Expression::Identifier(identifier) => context.get_type(&identifier.inner),
Expression::If(if_expression) => { Expression::If(if_expression) => {
return match if_expression.inner.as_ref() { return match if_expression.inner.as_ref() {
IfExpression::If { .. } => None, IfExpression::If { .. } => None,

View File

@ -0,0 +1,51 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::{Identifier, Struct, Value};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Constructor {
Unit(UnitConstructor),
Tuple(TupleConstructor),
Fields(FieldsConstructor),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct UnitConstructor {
pub name: Identifier,
}
impl UnitConstructor {
pub fn construct(self) -> Value {
Value::Struct(Struct::Unit { name: self.name })
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TupleConstructor {
pub name: Identifier,
}
impl TupleConstructor {
pub fn construct(self, fields: Vec<Value>) -> Value {
Value::Struct(Struct::Tuple {
name: self.name,
fields,
})
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct FieldsConstructor {
pub name: Identifier,
}
impl FieldsConstructor {
pub fn construct(self, fields: HashMap<Identifier, Value>) -> Value {
Value::Struct(Struct::Fields {
name: self.name,
fields,
})
}
}

View File

@ -4,9 +4,9 @@ use std::{
sync::{Arc, PoisonError as StdPoisonError, RwLock, RwLockWriteGuard}, sync::{Arc, PoisonError as StdPoisonError, RwLock, RwLockWriteGuard},
}; };
use crate::{ast::Span, Identifier, Type, Value}; use crate::{ast::Span, Constructor, Identifier, StructType, Type, Value};
pub type Variables = HashMap<Identifier, (VariableData, Span)>; pub type Variables = HashMap<Identifier, (ContextData, Span)>;
/// Garbage-collecting context for variables. /// Garbage-collecting context for variables.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -39,21 +39,24 @@ impl Context {
} }
/// Returns the full VariableData and Span if the context contains the given identifier. /// Returns the full VariableData and Span if the context contains the given identifier.
pub fn get(&self, identifier: &Identifier) -> Option<(VariableData, Span)> { pub fn get(&self, identifier: &Identifier) -> Option<(ContextData, Span)> {
self.variables.read().unwrap().get(identifier).cloned() self.variables.read().unwrap().get(identifier).cloned()
} }
/// Returns the type of the variable with the given identifier. /// Returns the type of the variable with the given identifier.
pub fn get_variable_type(&self, identifier: &Identifier) -> Option<Type> { pub fn get_type(&self, identifier: &Identifier) -> Option<Type> {
match self.variables.read().unwrap().get(identifier) { match self.variables.read().unwrap().get(identifier) {
Some((VariableData::Type(r#type), _)) => Some(r#type.clone()), Some((ContextData::VariableType(r#type), _)) => Some(r#type.clone()),
Some((VariableData::Value(value), _)) => Some(value.r#type()), Some((ContextData::VariableValue(value), _)) => Some(value.r#type()),
Some((ContextData::ConstructorType(struct_type), _)) => {
Some(Type::Struct(struct_type.clone()))
}
_ => None, _ => None,
} }
} }
/// Returns the VariableData of the variable with the given identifier. /// Returns the VariableData of the variable with the given identifier.
pub fn get_variable_data(&self, identifier: &Identifier) -> Option<VariableData> { pub fn get_data(&self, identifier: &Identifier) -> Option<ContextData> {
match self.variables.read().unwrap().get(identifier) { match self.variables.read().unwrap().get(identifier) {
Some((variable_data, _)) => Some(variable_data.clone()), Some((variable_data, _)) => Some(variable_data.clone()),
_ => None, _ => None,
@ -63,7 +66,15 @@ impl Context {
/// Returns the value of the variable with the given identifier. /// Returns the value of the variable with the given identifier.
pub fn get_variable_value(&self, identifier: &Identifier) -> Option<Value> { pub fn get_variable_value(&self, identifier: &Identifier) -> Option<Value> {
match self.variables.read().unwrap().get(identifier) { match self.variables.read().unwrap().get(identifier) {
Some((VariableData::Value(value), _)) => Some(value.clone()), Some((ContextData::VariableValue(value), _)) => Some(value.clone()),
_ => None,
}
}
/// Returns the constructor associated with the given identifier.
pub fn get_constructor(&self, identifier: &Identifier) -> Option<Constructor> {
match self.variables.read().unwrap().get(identifier) {
Some((ContextData::Constructor(constructor), _)) => Some(constructor.clone()),
_ => None, _ => None,
} }
} }
@ -75,7 +86,7 @@ impl Context {
self.variables self.variables
.write() .write()
.unwrap() .unwrap()
.insert(identifier, (VariableData::Type(r#type), position)); .insert(identifier, (ContextData::VariableType(r#type), position));
} }
/// Sets a variable to a value. /// Sets a variable to a value.
@ -89,7 +100,44 @@ impl Context {
.map(|(_, last_position)| *last_position) .map(|(_, last_position)| *last_position)
.unwrap_or_default(); .unwrap_or_default();
variables.insert(identifier, (VariableData::Value(value), last_position)); variables.insert(
identifier,
(ContextData::VariableValue(value), last_position),
);
}
/// Associates a constructor with an identifier.
pub fn set_constructor(&self, identifier: Identifier, constructor: Constructor) {
log::trace!("Setting {identifier} to constructor {constructor:?}");
let mut variables = self.variables.write().unwrap();
let last_position = variables
.get(&identifier)
.map(|(_, last_position)| *last_position)
.unwrap_or_default();
variables.insert(
identifier,
(ContextData::Constructor(constructor), last_position),
);
}
/// Associates a constructor type with an identifier.
pub fn set_constructor_type(
&self,
identifier: Identifier,
struct_type: StructType,
position: Span,
) {
log::trace!("Setting {identifier} to constructor of type {struct_type:?}");
let mut variables = self.variables.write().unwrap();
variables.insert(
identifier,
(ContextData::ConstructorType(struct_type), position),
);
} }
/// Collects garbage up to the given position, removing all variables with lesser positions. /// Collects garbage up to the given position, removing all variables with lesser positions.
@ -149,9 +197,11 @@ impl Default for Context {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum VariableData { pub enum ContextData {
Value(Value), Constructor(Constructor),
Type(Type), ConstructorType(StructType),
VariableValue(Value),
VariableType(Type),
} }
pub type ContextPoisonError<'err> = StdPoisonError<RwLockWriteGuard<'err, Variables>>; pub type ContextPoisonError<'err> = StdPoisonError<RwLockWriteGuard<'err, Variables>>;

View File

@ -18,6 +18,7 @@
pub mod analyzer; pub mod analyzer;
pub mod ast; pub mod ast;
pub mod built_in_function; pub mod built_in_function;
pub mod constructor;
pub mod context; pub mod context;
pub mod dust_error; pub mod dust_error;
pub mod identifier; pub mod identifier;
@ -31,7 +32,8 @@ pub mod vm;
pub use analyzer::{analyze, AnalysisError, Analyzer}; pub use analyzer::{analyze, AnalysisError, Analyzer};
pub use ast::{AbstractSyntaxTree, Expression, Statement}; pub use ast::{AbstractSyntaxTree, Expression, Statement};
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError}; pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
pub use context::{Context, VariableData}; pub use constructor::Constructor;
pub use context::{Context, ContextData};
pub use dust_error::DustError; pub use dust_error::DustError;
pub use identifier::Identifier; pub use identifier::Identifier;
pub use lexer::{lex, LexError, Lexer}; pub use lexer::{lex, LexError, Lexer};

View File

@ -13,11 +13,15 @@ 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::{Enum, Identifier, Struct, Value}; use crate::{
constructor::{FieldsConstructor, TupleConstructor, UnitConstructor},
Constructor, Enum, Identifier, Struct, Value,
};
/// Description of a kind of value. /// Description of a kind of value.
/// ///
@ -59,12 +63,14 @@ pub enum Type {
impl Type { impl Type {
/// Returns a concrete type, either the type itself or the concrete type of a generic type. /// Returns a concrete type, either the type itself or the concrete type of a generic type.
pub fn concrete_type(&self) -> &Type { pub fn concrete_type(&self) -> &Type {
match self { if let Type::Generic {
Type::Generic {
concrete_type: Some(concrete_type), concrete_type: Some(concrete_type),
.. ..
} => concrete_type.concrete_type(), } = self
_ => self, {
concrete_type.concrete_type()
} else {
self
} }
} }
@ -435,20 +441,16 @@ impl StructType {
} }
} }
pub fn constructor(&self) -> Option<Constructor> { pub fn constructor(&self) -> Constructor {
let constructor = match self { match self {
StructType::Unit { name } => Constructor::Unit { name: name.clone() }, StructType::Unit { name } => Constructor::Unit(UnitConstructor { name: name.clone() }),
StructType::Tuple { name, fields } => Constructor::Tuple(TupleConstructor { StructType::Tuple { name, .. } => {
name: name.clone(), Constructor::Tuple(TupleConstructor { name: name.clone() })
tuple_arguments: Vec::with_capacity(fields.len()), }
}), StructType::Fields { name, .. } => {
StructType::Fields { name, fields } => Constructor::Fields { Constructor::Fields(FieldsConstructor { name: name.clone() })
name: name.clone(), }
field_arguments: HashMap::with_capacity(fields.len()), }
},
};
Some(constructor)
} }
} }
@ -547,116 +549,12 @@ impl Ord for StructType {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Constructor {
Unit {
name: Identifier,
},
Tuple(TupleConstructor),
Fields {
name: Identifier,
field_arguments: HashMap<Identifier, Value>,
},
Enum {
name: Identifier,
r#type: EnumType,
variant_constructor: Box<Constructor>,
},
}
impl Constructor {
pub fn construct(self) -> Value {
match self {
Constructor::Unit { name } => Value::Struct(Struct::Unit { name }),
Constructor::Tuple(tuple_constructor) => tuple_constructor.construct(),
Constructor::Fields {
name,
field_arguments,
} => Value::Struct(Struct::Fields {
name,
fields: field_arguments,
}),
Constructor::Enum {
name,
r#type,
variant_constructor,
} => Value::Enum(Enum {
name,
r#type,
variant_data: Self::make_struct(*variant_constructor),
}),
}
}
fn make_struct(this: Self) -> Struct {
match this {
Constructor::Unit { name } => Struct::Unit { name },
Constructor::Tuple(TupleConstructor {
name,
tuple_arguments,
}) => Struct::Tuple {
name,
fields: tuple_arguments,
},
Constructor::Fields {
name,
field_arguments,
} => Struct::Fields {
name,
fields: field_arguments,
},
Constructor::Enum {
variant_constructor,
..
} => Self::make_struct(*variant_constructor),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TupleConstructor {
pub name: Identifier,
pub tuple_arguments: Vec<Value>,
}
impl TupleConstructor {
pub fn push_argument(&mut self, value: Value) {
self.tuple_arguments.push(value);
}
pub fn construct(self) -> Value {
Value::Struct(Struct::Tuple {
name: self.name,
fields: self.tuple_arguments,
})
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumType { pub struct EnumType {
pub name: Identifier, pub name: Identifier,
pub variants: Vec<StructType>, pub variants: Vec<StructType>,
} }
impl EnumType {
pub fn constructor(&self) -> Option<Constructor> {
let get_variant_constructor = self
.variants
.iter()
.find_map(|struct_type| struct_type.constructor());
if let Some(variant_constructor) = get_variant_constructor {
Some(Constructor::Enum {
name: self.name.clone(),
r#type: self.clone(),
variant_constructor: Box::new(variant_constructor),
})
} else {
None
}
}
}
impl Display for EnumType { impl Display for EnumType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let EnumType { name, variants } = self; let EnumType { name, variants } = self;

View File

@ -21,9 +21,8 @@ use crate::{
OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span,
Statement, StructDefinition, StructExpression, Statement, StructDefinition, StructExpression,
}, },
parse, Analyzer, BuiltInFunctionError, Constructor, Context, DustError, Enum, EnumType, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, Enum,
Expression, Identifier, ParseError, Struct, StructType, TupleConstructor, Type, Value, EnumType, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError,
ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -156,8 +155,9 @@ impl Vm {
) )
} }
}; };
let constructor = struct_type.constructor();
todo!("Set constructor"); self.context.set_constructor(name, constructor);
Ok(None) Ok(None)
} }
@ -222,17 +222,21 @@ impl Vm {
self.run_expression(*expression.inner, collect_garbage) self.run_expression(*expression.inner, collect_garbage)
} }
Expression::Identifier(identifier) => { Expression::Identifier(identifier) => {
let get_value = self.context.get_variable_value(&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())));
}
if let Some(ContextData::Constructor(constructor)) = get_data {
return Ok(Evaluation::Constructor(constructor));
}
if let Some(value) = get_value {
Ok(Evaluation::Return(Some(value)))
} else {
Err(RuntimeError::UndefinedValue { Err(RuntimeError::UndefinedValue {
identifier: identifier.inner, identifier: identifier.inner,
position: identifier.position, position,
}) })
} }
}
Expression::If(if_expression) => self.run_if(*if_expression.inner, collect_garbage), Expression::If(if_expression) => self.run_if(*if_expression.inner, collect_garbage),
Expression::List(list_expression) => { Expression::List(list_expression) => {
self.run_list(*list_expression.inner, collect_garbage) self.run_list(*list_expression.inner, collect_garbage)
@ -269,7 +273,7 @@ impl Vm {
match struct_expression { match struct_expression {
StructExpression::Unit { name } => { StructExpression::Unit { name } => {
let position = name.position; let position = name.position;
let r#type = self.context.get_variable_type(&name.inner).ok_or_else(|| { let r#type = self.context.get_type(&name.inner).ok_or_else(|| {
RuntimeError::UndefinedType { RuntimeError::UndefinedType {
identifier: name.inner.clone(), identifier: name.inner.clone(),
position, position,
@ -293,7 +297,7 @@ impl Vm {
fields: expressions, fields: expressions,
} => { } => {
let position = name.position; let position = name.position;
let r#type = self.context.get_variable_type(&name.inner).ok_or_else(|| { let r#type = self.context.get_type(&name.inner).ok_or_else(|| {
RuntimeError::UndefinedType { RuntimeError::UndefinedType {
identifier: name.inner.clone(), identifier: name.inner.clone(),
position, position,
@ -679,57 +683,33 @@ impl Vm {
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)?;
if let Evaluation::Constructor(Type::Struct(StructType::Tuple { name, fields })) = match run_invoker {
&run_invoker Evaluation::Constructor(constructor) => {
{ if let Constructor::Tuple(tuple_constructor) = constructor {
let struct_type = fields let mut fields = Vec::new();
.iter()
.find(|r#type| {
if let Type::Struct(struct_type) = r#type {
struct_type.name() == name
} else {
false
}
})
.ok_or(RuntimeError::EnumVariantNotFound {
identifier: name.clone(),
position: invoker_position,
})?;
if let Type::Struct(StructType::Tuple { name, fields }) = struct_type {
let mut values = Vec::with_capacity(arguments.len());
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)?;
values.push(value); if let Some(value) = self.run_expression(argument, collect_garbage)?.value()
} {
fields.push(value);
let r#struct = Struct::Tuple {
name: name.clone(),
fields: values,
};
return Ok(Evaluation::Return(Some(Value::Struct(r#struct))));
}
}
let invoker_value = if let Some(value) = run_invoker.value() {
value
} else { } else {
return Err(RuntimeError::ExpectedValue { return Err(RuntimeError::ExpectedValue { position });
position: invoker_position, }
}); }
};
let function = if let Value::Function(function) = invoker_value { let tuple = tuple_constructor.construct(fields);
return Ok(Evaluation::Return(Some(tuple)));
}
}
Evaluation::Return(Some(value)) => {
let function = if let Value::Function(function) = value {
function function
} else { } else {
return Err(RuntimeError::ExpectedFunction { return Err(RuntimeError::ExpectedFunction {
actual: invoker_value, actual: value.to_owned(),
position: invoker_position, position: invoker_position,
}); });
}; };
@ -748,9 +728,16 @@ impl Vm {
let context = Context::new(); let context = Context::new();
function return function
.call(None, Some(value_arguments), &context) .call(None, Some(value_arguments), &context)
.map(Evaluation::Return) .map(Evaluation::Return);
}
_ => (),
}
Err(RuntimeError::ExpectedValue {
position: invoker_position,
})
} }
fn run_field_access( fn run_field_access(
@ -923,7 +910,7 @@ impl Vm {
enum Evaluation { enum Evaluation {
Break, Break,
Constructor(Type), Constructor(Constructor),
Return(Option<Value>), Return(Option<Value>),
} }