Add instantiating unit structs
This commit is contained in:
parent
7e7448fe52
commit
1d75bd6594
@ -11,7 +11,8 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
abstract_tree::{BinaryOperator, UnaryOperator},
|
||||
parse, AbstractSyntaxTree, Context, DustError, Identifier, Node, Span, Statement, Type,
|
||||
parse, AbstractSyntaxTree, Context, DustError, Identifier, Node, Span, Statement,
|
||||
StructDefinition, StructType, Type,
|
||||
};
|
||||
|
||||
/// Analyzes the abstract syntax tree for errors.
|
||||
@ -420,7 +421,18 @@ impl<'a> Analyzer<'a> {
|
||||
Statement::Nil(node) => {
|
||||
self.analyze_statement(node)?;
|
||||
}
|
||||
Statement::StructDefinition(_) => {}
|
||||
Statement::StructDefinition(struct_definition) => {
|
||||
let (name, r#type) = match struct_definition {
|
||||
StructDefinition::Unit { name } => (
|
||||
name.inner.clone(),
|
||||
Type::Struct(StructType::Unit {
|
||||
name: name.inner.clone(),
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
self.context.set_type(name, r#type, node.position);
|
||||
}
|
||||
Statement::UnaryOperation { operator, operand } => {
|
||||
self.analyze_statement(operand)?;
|
||||
|
||||
|
@ -24,7 +24,7 @@ pub use dust_error::DustError;
|
||||
pub use identifier::Identifier;
|
||||
pub use lexer::{lex, LexError, Lexer};
|
||||
pub use parser::{parse, ParseError, Parser};
|
||||
pub use r#type::Type;
|
||||
pub use r#type::{StructType, Type};
|
||||
pub use token::{Token, TokenKind, TokenOwned};
|
||||
pub use value::{Struct, Value, ValueError};
|
||||
pub use vm::{run, run_with_context, Vm, VmError};
|
||||
|
@ -912,7 +912,7 @@ impl Display for ParseError {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{abstract_tree::BinaryOperator, Identifier, StructDefinition, UnaryOperator};
|
||||
use crate::{BinaryOperator, Identifier, StructDefinition, UnaryOperator};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -16,7 +16,7 @@ use std::{
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Identifier;
|
||||
use crate::{Identifier, Struct};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct TypeConflict {
|
||||
@ -31,7 +31,6 @@ pub struct TypeConflict {
|
||||
pub enum Type {
|
||||
Any,
|
||||
Boolean,
|
||||
Defined(Identifier),
|
||||
Enum {
|
||||
name: Identifier,
|
||||
type_parameters: Option<Vec<Type>>,
|
||||
@ -252,7 +251,6 @@ impl Display for Type {
|
||||
match self {
|
||||
Type::Any => write!(f, "any"),
|
||||
Type::Boolean => write!(f, "bool"),
|
||||
Type::Defined(identifier) => write!(f, "{identifier}"),
|
||||
Type::Enum { variants, .. } => {
|
||||
write!(f, "enum ")?;
|
||||
|
||||
@ -354,6 +352,15 @@ pub enum StructType {
|
||||
},
|
||||
}
|
||||
|
||||
impl StructType {
|
||||
pub fn instantiate(&self) -> Struct {
|
||||
match self {
|
||||
StructType::Unit { name } => Struct::Unit { name: name.clone() },
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StructType {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -14,7 +14,7 @@ use serde::{
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
|
||||
use crate::{identifier::Identifier, AbstractSyntaxTree, Context, Type, Vm, VmError};
|
||||
use crate::{identifier::Identifier, AbstractSyntaxTree, Context, StructType, Type, Vm, VmError};
|
||||
|
||||
/// Dust value representation
|
||||
///
|
||||
@ -699,7 +699,11 @@ impl ValueInner {
|
||||
}
|
||||
ValueInner::Range(_) => Type::Range,
|
||||
ValueInner::String(_) => Type::String,
|
||||
ValueInner::Struct(r#struct) => Type::Defined(r#struct.name().clone()),
|
||||
ValueInner::Struct(r#struct) => match r#struct {
|
||||
Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }),
|
||||
Struct::Tuple { .. } => todo!(),
|
||||
Struct::Fields { .. } => todo!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
parse, value::ValueInner, AbstractSyntaxTree, Analyzer, BinaryOperator, BuiltInFunctionError,
|
||||
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition, Type,
|
||||
UnaryOperator, Value, ValueError,
|
||||
Context, DustError, Identifier, Node, ParseError, Span, Statement, StructDefinition,
|
||||
StructType, Type, UnaryOperator, Value, ValueError,
|
||||
};
|
||||
|
||||
/// Run the source code and return the result.
|
||||
@ -378,13 +378,21 @@ impl Vm {
|
||||
let value_option = self.context.get_value(&identifier);
|
||||
|
||||
if let Some(value) = value_option {
|
||||
Ok(Some(value.clone()))
|
||||
} else {
|
||||
return Ok(Some(value.clone()));
|
||||
}
|
||||
|
||||
let type_option = self.context.get_type(&identifier);
|
||||
|
||||
println!("{type_option:?}");
|
||||
|
||||
if let Some(Type::Struct(struct_type)) = type_option {
|
||||
return Ok(Some(Value::r#struct(struct_type.instantiate())));
|
||||
}
|
||||
|
||||
Err(VmError::UndefinedVariable {
|
||||
identifier: Node::new(Statement::Identifier(identifier), node.position),
|
||||
})
|
||||
}
|
||||
}
|
||||
Statement::If { condition, body } => {
|
||||
let condition_position = condition.position;
|
||||
let condition_value = if let Some(value) = self.run_statement(*condition)? {
|
||||
@ -578,9 +586,12 @@ impl Vm {
|
||||
}
|
||||
Statement::StructDefinition(struct_definition) => {
|
||||
let (type_name, r#type) = match struct_definition {
|
||||
StructDefinition::Unit { name } => {
|
||||
(name.inner.clone(), Type::Defined(name.inner.clone()))
|
||||
}
|
||||
StructDefinition::Unit { name } => (
|
||||
name.inner.clone(),
|
||||
Type::Struct(StructType::Unit {
|
||||
name: name.inner.clone(),
|
||||
}),
|
||||
),
|
||||
};
|
||||
|
||||
self.context.set_type(type_name, r#type, node.position);
|
||||
@ -797,8 +808,22 @@ impl Display for VmError {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Struct;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn define_and_instantiate_unit_struct() {
|
||||
let input = "struct Foo Foo";
|
||||
|
||||
assert_eq!(
|
||||
run(input),
|
||||
Ok(Some(Value::r#struct(Struct::Unit {
|
||||
name: Identifier::new("Foo")
|
||||
})))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_index_nested() {
|
||||
let input = "[[1, 2], [42, 4], [5, 6]][1][0]";
|
||||
|
Loading…
Reference in New Issue
Block a user