diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index 28856bd..ca3cbea 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -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)?; diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 12d77bc..cc5f3d7 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -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}; diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 6c7ad98..f5b2667 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -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::*; diff --git a/dust-lang/src/type.rs b/dust-lang/src/type.rs index f76f60f..6a6b6e0 100644 --- a/dust-lang/src/type.rs +++ b/dust-lang/src/type.rs @@ -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>, @@ -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 { diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index df546dd..0de3d8a 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -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!(), + }, } } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index c6cfd7c..a12b537 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -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,12 +378,20 @@ impl Vm { let value_option = self.context.get_value(&identifier); if let Some(value) = value_option { - Ok(Some(value.clone())) - } else { - Err(VmError::UndefinedVariable { - identifier: Node::new(Statement::Identifier(identifier), node.position), - }) + 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; @@ -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]";