Pass VM test
This commit is contained in:
parent
e3d821a1c3
commit
fab66a4877
@ -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,52 +96,54 @@ 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.position,
|
||||||
|
),
|
||||||
|
StructDefinition::Tuple { name, items } => {
|
||||||
|
let fields = items.iter().map(|item| item.inner.clone()).collect();
|
||||||
|
|
||||||
|
self.context.set_constructor_type(
|
||||||
|
name.inner.clone(),
|
||||||
|
StructType::Tuple {
|
||||||
name: name.inner.clone(),
|
name: name.inner.clone(),
|
||||||
}),
|
fields,
|
||||||
),
|
},
|
||||||
StructDefinition::Tuple { name, items } => {
|
name.position,
|
||||||
let fields = items.iter().map(|item| item.inner.clone()).collect();
|
);
|
||||||
|
}
|
||||||
|
StructDefinition::Fields { name, fields } => {
|
||||||
|
let fields = fields
|
||||||
|
.iter()
|
||||||
|
.map(|(identifier, r#type)| {
|
||||||
|
(identifier.inner.clone(), r#type.inner.clone())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
(
|
self.context.set_constructor_type(
|
||||||
name,
|
name.inner.clone(),
|
||||||
Type::Struct(StructType::Tuple {
|
StructType::Fields {
|
||||||
name: name.inner.clone(),
|
name: name.inner.clone(),
|
||||||
fields,
|
fields,
|
||||||
}),
|
},
|
||||||
)
|
name.position,
|
||||||
}
|
);
|
||||||
StructDefinition::Fields { name, fields } => {
|
}
|
||||||
let fields = fields
|
},
|
||||||
.iter()
|
|
||||||
.map(|(identifier, r#type)| {
|
|
||||||
(identifier.inner.clone(), r#type.inner.clone())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(
|
|
||||||
name,
|
|
||||||
Type::Struct(StructType::Fields {
|
|
||||||
name: name.inner.clone(),
|
|
||||||
fields,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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, .. } => {
|
||||||
|
@ -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,
|
||||||
|
51
dust-lang/src/constructor.rs
Normal file
51
dust-lang/src/constructor.rs
Normal 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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -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>>;
|
||||||
|
@ -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};
|
||||||
|
@ -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),
|
..
|
||||||
..
|
} = self
|
||||||
} => concrete_type.concrete_type(),
|
{
|
||||||
_ => 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;
|
||||||
|
@ -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,16 +222,20 @@ 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(value) = get_value {
|
if let Some(ContextData::VariableValue(value)) = get_data {
|
||||||
Ok(Evaluation::Return(Some(value)))
|
return Ok(Evaluation::Return(Some(value.clone())));
|
||||||
} else {
|
|
||||||
Err(RuntimeError::UndefinedValue {
|
|
||||||
identifier: identifier.inner,
|
|
||||||
position: identifier.position,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ContextData::Constructor(constructor)) = get_data {
|
||||||
|
return Ok(Evaluation::Constructor(constructor));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(RuntimeError::UndefinedValue {
|
||||||
|
identifier: identifier.inner,
|
||||||
|
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) => {
|
||||||
@ -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,78 +683,61 @@ 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 {
|
for argument in arguments {
|
||||||
let mut values = Vec::with_capacity(arguments.len());
|
let position = argument.position();
|
||||||
|
|
||||||
|
if let Some(value) = self.run_expression(argument, collect_garbage)?.value()
|
||||||
|
{
|
||||||
|
fields.push(value);
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ExpectedValue { position });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ExpectedFunction {
|
||||||
|
actual: value.to_owned(),
|
||||||
|
position: invoker_position,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut value_arguments = Vec::new();
|
||||||
|
|
||||||
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() {
|
||||||
|
value_arguments.push(value);
|
||||||
|
} else {
|
||||||
|
return Err(RuntimeError::ExpectedValue { position });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let r#struct = Struct::Tuple {
|
let context = Context::new();
|
||||||
name: name.clone(),
|
|
||||||
fields: values,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(Evaluation::Return(Some(Value::Struct(r#struct))));
|
return function
|
||||||
|
.call(None, Some(value_arguments), &context)
|
||||||
|
.map(Evaluation::Return);
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let invoker_value = if let Some(value) = run_invoker.value() {
|
Err(RuntimeError::ExpectedValue {
|
||||||
value
|
position: invoker_position,
|
||||||
} else {
|
})
|
||||||
return Err(RuntimeError::ExpectedValue {
|
|
||||||
position: invoker_position,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let function = if let Value::Function(function) = invoker_value {
|
|
||||||
function
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::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, collect_garbage)?.value() {
|
|
||||||
value_arguments.push(value);
|
|
||||||
} else {
|
|
||||||
return Err(RuntimeError::ExpectedValue { position });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = Context::new();
|
|
||||||
|
|
||||||
function
|
|
||||||
.call(None, Some(value_arguments), &context)
|
|
||||||
.map(Evaluation::Return)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user