From 8974fc6327df1e890aa5aa7430ac8eac189b84a5 Mon Sep 17 00:00:00 2001 From: Benedikt Strehle Date: Thu, 27 Nov 2025 00:52:48 +0100 Subject: [PATCH 01/10] :boom: refactoring (WIP) --- src/ast/structs/expression.rs | 3 +- src/ast/structs/type.rs | 4 +- src/compiler/precompiler/mod.rs | 4 +- src/compiler/precompiler/precompiled_ast.rs | 4 +- src/compiler/workspace.rs | 4 +- src/core_compiler/type_compiler.rs | 58 ++++++++++ src/core_compiler/value_compiler.rs | 5 +- src/dif/mod.rs | 14 +-- src/dif/reference.rs | 6 +- src/dif/representation.rs | 43 ++++---- src/dif/type.rs | 111 +++++--------------- src/dif/value.rs | 22 ++-- src/libs/core.rs | 65 +++++------- src/references/observers.rs | 4 +- src/references/reference.rs | 7 +- src/references/type_reference.rs | 2 +- src/references/value_reference.rs | 8 +- src/runtime/execution.rs | 4 +- src/type_inference/error.rs | 10 +- src/type_inference/mod.rs | 10 +- src/types/definition.rs | 104 ++++++++++++++++-- src/types/structural_type_definition.rs | 6 +- src/types/type_container.rs | 22 ++-- src/values/core_value.rs | 13 ++- src/values/core_values/type.rs | 106 +++---------------- src/values/value.rs | 14 +-- src/values/value_container.rs | 52 ++++----- 27 files changed, 347 insertions(+), 358 deletions(-) diff --git a/src/ast/structs/expression.rs b/src/ast/structs/expression.rs index 00ce62148..62b5e7b74 100644 --- a/src/ast/structs/expression.rs +++ b/src/ast/structs/expression.rs @@ -9,7 +9,6 @@ use crate::global::operators::assignment::AssignmentOperator; use crate::global::operators::{ArithmeticUnaryOperator, UnaryOperator}; use crate::references::reference::ReferenceMutability; use crate::stdlib::vec::Vec; -use crate::types::type_container::TypeContainer; use crate::values::core_value::CoreValue; use crate::values::core_values::decimal::Decimal; use crate::values::core_values::decimal::typed_decimal::TypedDecimal; @@ -29,7 +28,7 @@ pub struct DatexExpression { pub data: DatexExpressionData, pub span: Range, pub wrapped: Option, // number of wrapping parentheses - pub ty: Option, + pub ty: Option, } impl Default for DatexExpression { fn default() -> Self { diff --git a/src/ast/structs/type.rs b/src/ast/structs/type.rs index 2bf246a65..b010265af 100644 --- a/src/ast/structs/type.rs +++ b/src/ast/structs/type.rs @@ -3,12 +3,12 @@ use core::ops::Range; use crate::ast::spanned::Spanned; use crate::ast::structs::ResolvedVariable; use crate::ast::structs::expression::VariableAccess; -use crate::types::type_container::TypeContainer; use crate::values::core_values::decimal::Decimal; use crate::values::core_values::decimal::typed_decimal::TypedDecimal; use crate::values::core_values::endpoint::Endpoint; use crate::values::core_values::integer::Integer; use crate::values::core_values::integer::typed_integer::TypedInteger; +use crate::values::core_values::r#type::Type; use crate::values::pointer::PointerAddress; #[derive(Clone, Debug, PartialEq)] @@ -92,7 +92,7 @@ pub struct TypeExpression { pub data: TypeExpressionData, pub span: Range, pub wrapped: Option, // number of wrapping parentheses - pub ty: Option, + pub ty: Option, } impl TypeExpression { pub fn new(data: TypeExpressionData, span: Range) -> Self { diff --git a/src/compiler/precompiler/mod.rs b/src/compiler/precompiler/mod.rs index 3acc8b0bf..44535d4c4 100644 --- a/src/compiler/precompiler/mod.rs +++ b/src/compiler/precompiler/mod.rs @@ -34,7 +34,6 @@ use crate::{ global::operators::{BinaryOperator, binary::ArithmeticOperator}, libs::core::CoreLibPointerId, references::type_reference::{NominalTypeDeclaration, TypeReference}, - types::type_container::TypeContainer, values::core_values::r#type::Type, visitor::{ VisitAction, @@ -48,6 +47,7 @@ use precompiled_ast::RichAst; use precompiled_ast::VariableShape; use scope::NewScopeType; use scope_stack::PrecompilerScopeStack; +use crate::types::definition::TypeDefinition; pub struct Precompiler<'a> { ast_metadata: Rc>, @@ -303,7 +303,7 @@ impl<'a> Precompiler<'a> { }; // register placeholder ref in metadata - let type_def = TypeContainer::TypeReference(reference.clone()); + let type_def = Type::new(TypeDefinition::reference(reference), None); { self.ast_metadata .borrow_mut() diff --git a/src/compiler/precompiler/precompiled_ast.rs b/src/compiler/precompiler/precompiled_ast.rs index e449917c8..0802b8b3d 100644 --- a/src/compiler/precompiler/precompiled_ast.rs +++ b/src/compiler/precompiler/precompiled_ast.rs @@ -1,16 +1,16 @@ use crate::stdlib::{cell::RefCell, rc::Rc}; use crate::{ ast::structs::expression::{DatexExpression, VariableKind}, - types::type_container::TypeContainer, }; use core::fmt::Display; +use crate::values::core_values::r#type::Type; #[derive(Clone, Debug)] pub struct VariableMetadata { pub original_realm_index: usize, pub is_cross_realm: bool, pub shape: VariableShape, - pub var_type: Option, + pub var_type: Option, pub name: String, } diff --git a/src/compiler/workspace.rs b/src/compiler/workspace.rs index d4bdf9373..3cec438f1 100644 --- a/src/compiler/workspace.rs +++ b/src/compiler/workspace.rs @@ -8,14 +8,14 @@ use crate::compiler::{ CompileOptions, parse_datex_script_to_rich_ast_detailed_errors, }; use crate::runtime::Runtime; -use crate::types::type_container::TypeContainer; +use crate::values::core_values::r#type::Type; /// Represents a file in the compiler workspace with its URL, cached content and AST. pub struct WorkspaceFile { pub url: Url, pub content: String, pub rich_ast: Option, - pub return_type: Option, + pub return_type: Option, pub errors: Option, } diff --git a/src/core_compiler/type_compiler.rs b/src/core_compiler/type_compiler.rs index 8b1378917..21b4771ba 100644 --- a/src/core_compiler/type_compiler.rs +++ b/src/core_compiler/type_compiler.rs @@ -1 +1,59 @@ +use crate::values::core_values::r#type::Type; +/// Compiles a given type container to a DXB body +pub fn compile_type_container(ty: &Type) -> Vec { + let mut buffer = Vec::with_capacity(256); + append_type_container(&mut buffer, ty); + buffer +} + +/*** + +$123123123 +"txt" +$x = () + + */ + +pub fn append_type_container( + buffer: &mut Vec, + ty: &Type, +) { + match ty { + // TypeContainer::Type(ty) => append_type(buffer, ty), + // // nominal type (e.g. integer, User) + // TypeContainer::TypeReference(reference) => { + // // add CREATE_REF/CREATE_REF_MUT instruction + // if reference.mutability() == ReferenceMutability::Mutable { + // append_instruction_code( + // buffer, + // InstructionCode::CREATE_REF_MUT, + // ); + // } else { + // append_instruction_code(buffer, InstructionCode::CREATE_REF); + // } + // // insert pointer id + value or only id + // // add pointer to memory if not there yet + // append_value(buffer, &reference.collapse_to_value().borrow()) + // } + _ => unreachable!() + } +} + +pub fn append_type(buffer: &mut Vec, ty: &Type) { + + // INSTRUCTION + // &mut (integer + js.undefed) + // function (x: null) { + // + // } + // + // match &ty.type_definition { + // TypeDefinition::MarkedType(ty) => { + // // ... + // } + // _ => todo!() + // } +} + +// pub fn get_type_definition_ \ No newline at end of file diff --git a/src/core_compiler/value_compiler.rs b/src/core_compiler/value_compiler.rs index 42fdf8ac1..838ee3053 100644 --- a/src/core_compiler/value_compiler.rs +++ b/src/core_compiler/value_compiler.rs @@ -22,8 +22,7 @@ use core::prelude::rust_2024::*; use datex_core::utils::buffers::{ append_i32, append_i64, append_i128, append_u16, append_u64, }; -use datex_core::values::core_values::r#type::Type; -use crate::types::type_container::TypeContainer; +use crate::types::definition::TypeDefinition; /// Compiles a given value container to a DXB body pub fn compile_value_container(value_container: &ValueContainer) -> Vec { @@ -105,7 +104,7 @@ pub fn append_value(buffer: &mut Vec, value: &Value) { } } -pub fn append_type_cast(buffer: &mut Vec, ty: &TypeContainer) { +pub fn append_type_cast(buffer: &mut Vec, ty: &TypeDefinition) { append_instruction_code(buffer, InstructionCode::TYPED_VALUE); // TODO } diff --git a/src/dif/mod.rs b/src/dif/mod.rs index 4cb512b5a..22dab9b40 100644 --- a/src/dif/mod.rs +++ b/src/dif/mod.rs @@ -90,14 +90,7 @@ mod tests { fn dif_value_serialization() { let value = DIFValue { value: DIFValueRepresentation::Null, - ty: Some( - DIFType { - mutability: None, - name: None, - type_definition: DIFTypeDefinition::Unit, - } - .as_container(), - ), + ty: Some(DIFTypeDefinition::Unit), }; let serialized = value.as_json(); println!("Serialized DIFValue: {}", serialized); @@ -112,9 +105,8 @@ mod tests { assert_eq!(dif_value.value, DIFValueRepresentation::Number(42f64)); assert_eq!( dif_value.ty, - Some(DIFTypeContainer::Reference( - CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32)) - .into() + Some(DIFTypeDefinition::Reference( + CoreLibPointerId::Integer(Some(IntegerTypeVariant::I32)).into() )) ); } else { diff --git a/src/dif/reference.rs b/src/dif/reference.rs index 294ba394d..ef0e73d45 100644 --- a/src/dif/reference.rs +++ b/src/dif/reference.rs @@ -6,10 +6,12 @@ use core::cell::RefCell; use core::prelude::rust_2024::*; use datex_core::dif::value::DIFValueContainer; use serde::{Deserialize, Serialize}; +use datex_core::dif::r#type::DIFTypeDefinition; + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DIFReference { pub value: DIFValueContainer, - pub allowed_type: DIFTypeContainer, + pub allowed_type: DIFTypeDefinition, #[serde(rename = "mut")] #[serde(with = "mutability_as_int")] pub mutability: ReferenceMutability, @@ -24,7 +26,7 @@ impl DIFReference { &reference.value_container(), memory, ); - let allowed_type = DIFTypeContainer::from_type_container( + let allowed_type = DIFTypeDefinition::from_type_container( &reference.allowed_type(), memory, ); diff --git a/src/dif/representation.rs b/src/dif/representation.rs index 4e6089def..4c1ad4cd7 100644 --- a/src/dif/representation.rs +++ b/src/dif/representation.rs @@ -1,6 +1,6 @@ -use crate::dif::r#type::{DIFTypeContainer, DIFTypeDefinition}; +use crate::dif::r#type::{DIFType, DIFTypeContainer, DIFTypeDefinition}; use crate::dif::value::{DIFReferenceNotFoundError, DIFValueContainer}; -use crate::libs::core::{CoreLibPointerId, get_core_lib_type}; +use crate::libs::core::{CoreLibPointerId, get_core_lib_type, get_core_lib_type_definition}; use crate::runtime::memory::Memory; use crate::std_random::RandomState; use crate::stdlib::boxed::Box; @@ -25,7 +25,6 @@ use ordered_float::OrderedFloat; use serde::de::{MapAccess, SeqAccess, Visitor}; use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; -use datex_core::types::type_container::TypeContainer; use crate::values::core_values::map::Map; #[derive(Clone, Debug, PartialEq)] @@ -55,11 +54,11 @@ pub enum DIFTypeRepresentation { /// Represents a number in DIF. Number(f64), /// Represents a array of DIF values. - Array(Vec), + Array(Vec), /// Represents a map of DIF values. - Map(Vec<(DIFTypeContainer, DIFTypeContainer)>), + Map(Vec<(DIFType, DIFType)>), /// Represents a struct value in DIF. - Object(Vec<(String, DIFTypeContainer)>), + Object(Vec<(String, DIFType)>), } impl DIFValueRepresentation { @@ -72,19 +71,19 @@ impl DIFValueRepresentation { Ok(match self { DIFValueRepresentation::Null => Value::null(), DIFValueRepresentation::String(str) => Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::Text, )), inner: CoreValue::Text(str.clone().into()), }, DIFValueRepresentation::Boolean(b) => Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::Boolean, )), inner: CoreValue::Boolean((*b).into()), }, DIFValueRepresentation::Number(n) => Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64)), )), inner: CoreValue::TypedDecimal(TypedDecimal::F64( @@ -92,7 +91,7 @@ impl DIFValueRepresentation { )), }, DIFValueRepresentation::Array(array) => Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::List, )), inner: CoreValue::List( @@ -112,7 +111,7 @@ impl DIFValueRepresentation { ); } Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::Map, )), inner: CoreValue::Map(map.into()), @@ -127,7 +126,7 @@ impl DIFValueRepresentation { ); } Value { - actual_type: Box::new(get_core_lib_type( + actual_type: Box::new(get_core_lib_type_definition( CoreLibPointerId::Map, )), inner: CoreValue::Map(core_map.into()), @@ -145,10 +144,10 @@ impl DIFValueRepresentation { /// Returns an error if a reference cannot be resolved. pub fn to_value_with_type( &self, - type_container: &DIFTypeContainer, + type_definition: &DIFTypeDefinition, memory: &RefCell, ) -> Result { - Ok(match type_container { + Ok(match type_definition { DIFTypeContainer::Reference(r) => { if let Ok(core_lib_ptr_id) = CoreLibPointerId::try_from(r) { match core_lib_ptr_id { @@ -193,7 +192,7 @@ impl DIFValueRepresentation { let val = self.to_default_value(memory)?; let ty = dif_type.to_type(memory); Value { - actual_type: Box::new(TypeContainer::Type(ty)), + actual_type: Box::new(ty), ..val } } @@ -241,7 +240,7 @@ impl DIFTypeRepresentation { DIFTypeRepresentation::Array( arr.iter() .map(|v| { - DIFTypeContainer::from_type_container(v, memory) + DIFType::from_type(v, memory) }) .collect(), ) @@ -252,10 +251,10 @@ impl DIFTypeRepresentation { .iter() .map(|(k, v)| { ( - DIFTypeContainer::from_type_container( + DIFType::from_type( k, memory, ), - DIFTypeContainer::from_type_container( + DIFType::from_type( v, memory, ), ) @@ -481,13 +480,13 @@ impl<'de> Deserialize<'de> for DIFTypeRepresentation { A: SeqAccess<'de>, { let first_entry = seq - .next_element::>( + .next_element::>( )?; match first_entry { Some(DeserializeMapOrArray::ArrayEntry(first)) => { let mut elements = vec![first]; while let Some(elem) = - seq.next_element::()? + seq.next_element::()? { elements.push(elem); } @@ -496,8 +495,8 @@ impl<'de> Deserialize<'de> for DIFTypeRepresentation { Some(DeserializeMapOrArray::MapEntry(k, v)) => { let mut elements = vec![(k, v)]; while let Some((k, v)) = seq.next_element::<( - DIFTypeContainer, - DIFTypeContainer, + DIFType, + DIFType, )>( )? { elements.push((k, v)); diff --git a/src/dif/type.rs b/src/dif/type.rs index 2ea9a229d..9aba023e0 100644 --- a/src/dif/type.rs +++ b/src/dif/type.rs @@ -9,7 +9,6 @@ use crate::stdlib::string::String; use crate::stdlib::vec::Vec; use crate::types::definition::TypeDefinition; use crate::types::structural_type_definition::StructuralTypeDefinition; -use crate::types::type_container::TypeContainer; use crate::values::core_values::r#type::Type; use crate::values::pointer::PointerAddress; use core::cell::RefCell; @@ -26,12 +25,12 @@ pub enum DIFTypeDefinition { Type(Box), // e.g. A & B & C - Intersection(Vec), + Intersection(Vec), // e.g. A | B | C - Union(Vec), + Union(Vec), - MarkedType(Box, Vec), + MarkedType(Box, Vec), // () Unit, @@ -41,8 +40,8 @@ pub enum DIFTypeDefinition { Unknown, Function { - parameters: Vec<(String, DIFTypeContainer)>, - return_type: Box, + parameters: Vec<(String, DIFType)>, + return_type: Box, }, } @@ -50,7 +49,7 @@ pub enum DIFTypeDefinition { pub struct DIFStructuralTypeDefinition { pub value: DIFTypeRepresentation, #[serde(skip_serializing_if = "Option::is_none", rename = "type")] - pub ty: Option, + pub ty: Option, } impl DIFStructuralTypeDefinition { @@ -65,7 +64,11 @@ impl DIFStructuralTypeDefinition { PointerAddress::from(struct_def.get_core_lib_type_pointer_id()); DIFStructuralTypeDefinition { value, - ty: Some(DIFTypeContainer::Reference(type_def)), + ty: Some(DIFType { + type_definition: DIFTypeDefinition::Reference(type_def), + mutability: None, + name: None, + }), } } } @@ -99,7 +102,7 @@ impl DIFTypeDefinition { types .iter() .map(|t| { - DIFTypeContainer::from_type_container(t, memory) + DIFType::from_type(t, memory) }) .collect(), ) @@ -107,12 +110,12 @@ impl DIFTypeDefinition { TypeDefinition::Union(types) => DIFTypeDefinition::Union( types .iter() - .map(|t| DIFTypeContainer::from_type_container(t, memory)) + .map(|t| DIFType::from_type(t, memory)) .collect(), ), TypeDefinition::MarkedType(ty, markers) => { DIFTypeDefinition::MarkedType( - Box::new(DIFTypeContainer::from_type_container(ty, memory)), + Box::new(DIFType::from_type(ty, memory)), markers.clone(), ) } @@ -128,11 +131,11 @@ impl DIFTypeDefinition { .map(|(name, ty)| { ( name.clone(), - DIFTypeContainer::from_type_container(ty, memory), + DIFType::from_type(ty, memory), ) }) .collect(), - return_type: Box::new(DIFTypeContainer::from_type_container( + return_type: Box::new(DIFType::from_type( return_type, memory, )), @@ -150,7 +153,7 @@ impl DIFTypeDefinition { types .iter() .map(|t| { - t.to_type_container(memory) + t.to_type(memory) }) .collect(), ) @@ -158,7 +161,7 @@ impl DIFTypeDefinition { DIFTypeDefinition::Union(types) => TypeDefinition::Union( types .iter() - .map(|t| t.to_type_container(memory)) + .map(|t| t.to_type(memory)) .collect(), ), DIFTypeDefinition::Reference(type_ref_addr) => { @@ -174,7 +177,7 @@ impl DIFTypeDefinition { }, DIFTypeDefinition::MarkedType(ty, markers) => { TypeDefinition::MarkedType( - Box::new(ty.to_type_container(memory)), + Box::new(ty.to_type(memory)), markers.clone(), ) } @@ -219,7 +222,7 @@ impl DIFType { DIFTypeContainer::Type(self) } - fn from_type(ty: &Type, memory: &RefCell) -> Self { + pub(crate) fn from_type(ty: &Type, memory: &RefCell) -> Self { DIFType { name: None, mutability: ty.reference_mutability.clone(), @@ -255,57 +258,6 @@ impl From for DIFType { } } -impl DIFTypeContainer { - pub fn from_type_container( - type_container: &TypeContainer, - memory: &RefCell, - ) -> Self { - match type_container { - TypeContainer::Type(ty) => { - DIFTypeContainer::Type(DIFType::from_type(ty, memory)) - } - TypeContainer::TypeReference(type_ref) => { - let type_ref_borrow = type_ref.borrow(); - let address = if let Some(ref address) = - type_ref_borrow.pointer_address - { - address - } else { - &memory.borrow_mut().register_reference( - &Reference::TypeReference(type_ref.clone()), - ) - }; - DIFTypeContainer::Reference(address.clone()) - } - TypeContainer::TypeAlias(type_alias) => { - core::todo!( - "DIFTypeContainer::from_type_container for TypeAlias is not implemented yet" - ) - } - } - } - - pub fn to_type_container( - &self, - memory: &RefCell, - ) -> TypeContainer { - match self { - DIFTypeContainer::Type(dif_type) => { - TypeContainer::Type(dif_type.to_type(memory)) - } - DIFTypeContainer::Reference(addr) => { - TypeContainer::TypeReference( - memory - .borrow_mut() - .get_type_reference(addr) - .expect("Reference not found in memory") - .clone() - ) - } - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -333,12 +285,10 @@ mod tests { ( "field1".to_string(), DIFType::from(DIFTypeRepresentation::Null) - .as_container(), ), ( "field2".to_string(), DIFType::from(DIFTypeRepresentation::Number(42.0)) - .as_container(), ), ]), ty: None, @@ -361,16 +311,12 @@ mod tests { ( DIFType::from(DIFTypeRepresentation::String( "key1".to_string(), - )) - .as_container(), - DIFType::from(DIFTypeRepresentation::Number(42.0)) - .as_container(), + )), + DIFType::from(DIFTypeRepresentation::Number(42.0)), ), ( - DIFType::from(DIFTypeRepresentation::Number(1.0)) - .as_container(), - DIFType::from(DIFTypeRepresentation::Number(3.5)) - .as_container(), + DIFType::from(DIFTypeRepresentation::Number(1.0)), + DIFType::from(DIFTypeRepresentation::Number(3.5)), ), ]), ty: None, @@ -390,12 +336,9 @@ mod tests { type_definition: DIFTypeDefinition::Structural(Box::new( DIFStructuralTypeDefinition { value: DIFTypeRepresentation::Array(vec![ - DIFType::from(DIFTypeRepresentation::Number(1.0)) - .as_container(), - DIFType::from(DIFTypeRepresentation::Number(2.0)) - .as_container(), - DIFType::from(DIFTypeRepresentation::Number(3.0)) - .as_container(), + DIFType::from(DIFTypeRepresentation::Number(1.0)), + DIFType::from(DIFTypeRepresentation::Number(2.0)), + DIFType::from(DIFTypeRepresentation::Number(3.0)), ]), ty: None, }, diff --git a/src/dif/value.rs b/src/dif/value.rs index fe1c387e2..48cfbd74c 100644 --- a/src/dif/value.rs +++ b/src/dif/value.rs @@ -4,7 +4,6 @@ use crate::dif::{ }; use crate::libs::core::CoreLibPointerId; use crate::stdlib::string::ToString; -use crate::types::type_container::TypeContainer; use crate::values::core_values::decimal::typed_decimal::{ DecimalTypeVariant, TypedDecimal, }; @@ -19,6 +18,8 @@ use core::result::Result; use datex_core::runtime::memory::Memory; use datex_core::values::core_value::CoreValue; use serde::{Deserialize, Serialize}; +use crate::dif::r#type::DIFTypeDefinition; +use crate::types::definition::TypeDefinition; #[derive(Debug)] pub struct DIFReferenceNotFoundError; @@ -28,7 +29,7 @@ pub struct DIFReferenceNotFoundError; pub struct DIFValue { pub value: DIFValueRepresentation, #[serde(skip_serializing_if = "Option::is_none", rename = "type")] - pub ty: Option, + pub ty: Option, } impl DIFConvertible for DIFValue {} @@ -50,7 +51,7 @@ impl DIFValue { impl DIFValue { pub fn new( value: DIFValueRepresentation, - ty: Option>, + ty: Option>, ) -> Self { DIFValue { value, @@ -257,11 +258,11 @@ impl DIFValue { /// - List /// - Map (if not empty, otherwise we cannot distinguish between empty map and empty list since both are represented as [] in DIF) fn get_type_if_non_default( - type_container: &TypeContainer, + type_definition: &TypeDefinition, memory: &RefCell, is_empty_map: bool, -) -> Option { - match type_container { +) -> Option { + match type_definition { TypeContainer::TypeReference(inner) => { if let Some(Ok(address)) = inner .borrow() @@ -284,13 +285,13 @@ fn get_type_if_non_default( None } else { Some(DIFTypeContainer::from_type_container( - type_container, + type_definition, memory, )) } } _ => Some(DIFTypeContainer::from_type_container( - type_container, + type_definition, memory, )), } @@ -310,6 +311,7 @@ mod tests { }; use core::cell::RefCell; use datex_core::values::value::Value; + use crate::dif::r#type::DIFTypeDefinition; fn get_mock_memory() -> RefCell { RefCell::new(Memory::new(Endpoint::default())) @@ -351,7 +353,7 @@ mod tests { let memory = get_mock_memory(); let dif = DIFValue::from_value(&Value::from(123u16), &memory); assert!(dif.ty.is_some()); - if let DIFTypeContainer::Reference(reference) = dif.ty.unwrap() { + if let DIFTypeDefinition::Reference(reference) = dif.ty.unwrap() { assert_eq!( reference, CoreLibPointerId::Integer(Some(IntegerTypeVariant::U16)).into() @@ -362,7 +364,7 @@ mod tests { let dif = DIFValue::from_value(&Value::from(123i64), &memory); assert!(dif.ty.is_some()); - if let DIFTypeContainer::Reference(reference) = dif.ty.unwrap() { + if let DIFTypeDefinition::Reference(reference) = dif.ty.unwrap() { assert_eq!( reference, CoreLibPointerId::Integer(Some(IntegerTypeVariant::I64)).into() diff --git a/src/libs/core.rs b/src/libs/core.rs index ee4816da3..552033658 100644 --- a/src/libs/core.rs +++ b/src/libs/core.rs @@ -11,7 +11,6 @@ use crate::stdlib::string::ToString; use crate::stdlib::vec; use crate::stdlib::vec::Vec; use crate::types::definition::TypeDefinition; -use crate::types::type_container::TypeContainer; use crate::values::core_values::decimal::typed_decimal::DecimalTypeVariant; use crate::values::core_values::integer::typed_integer::IntegerTypeVariant; use crate::values::core_values::r#type::Type; @@ -25,7 +24,7 @@ use datex_core::values::value_container::ValueContainer; use datex_macros::LibTypeString; use strum::IntoEnumIterator; -type CoreLibTypes = HashMap; +type CoreLibTypes = HashMap; #[cfg_attr(not(feature = "embassy_runtime"), thread_local)] pub static mut CORE_LIB_TYPES: Option = None; @@ -151,7 +150,7 @@ impl TryFrom<&PointerAddress> for CoreLibPointerId { } } -pub fn get_core_lib_type(id: impl Into) -> TypeContainer { +pub fn get_core_lib_type(id: impl Into) -> Type { with_core_lib(|core_lib_types| { core_lib_types.get(&id.into()).unwrap().clone() }) @@ -161,12 +160,19 @@ pub fn get_core_lib_type_reference( id: impl Into, ) -> Rc> { let type_container = get_core_lib_type(id); - match type_container { - TypeContainer::TypeReference(tr) => tr, + match type_container.type_definition { + TypeDefinition::Reference(tr) => tr, _ => core::panic!("Core lib type is not a TypeReference"), } } +pub fn get_core_lib_type_definition( + id: impl Into, +) -> TypeDefinition { + get_core_lib_type(id).type_definition +} + + fn has_core_lib_type(id: T) -> bool where T: Into, @@ -179,15 +185,15 @@ pub fn load_core_lib(memory: &mut Memory) { with_core_lib(|core_lib_types| { let structure = core_lib_types .values() - .map(|def| match def { - TypeContainer::TypeReference(def) => { - let name = def + .map(|ty| match ty.type_definition { + TypeDefinition::Reference(type_reference) => { + let name = type_reference .borrow() .nominal_type_declaration .as_ref() .unwrap() .to_string(); - let reference = Reference::TypeReference(def.clone()); + let reference = Reference::TypeReference(type_reference.clone()); memory.register_reference(&reference); (name, ValueContainer::Reference(reference)) } @@ -206,7 +212,7 @@ pub fn load_core_lib(memory: &mut Memory) { /// Creates a new instance of the core library as a ValueContainer /// including all core types as properties. -pub fn create_core_lib() -> HashMap { +pub fn create_core_lib() -> HashMap { let integer = integer(); let decimal = decimal(); vec![ @@ -232,10 +238,10 @@ pub fn create_core_lib() -> HashMap { DecimalTypeVariant::iter() .map(|variant| decimal_variant(decimal.1.clone(), variant)), ) - .collect::>() + .collect::>() } -type CoreLibTypeDefinition = (CoreLibPointerId, TypeContainer); +type CoreLibTypeDefinition = (CoreLibPointerId, Type); pub fn ty() -> CoreLibTypeDefinition { create_core_type("type", None, None, CoreLibPointerId::Type) } @@ -270,7 +276,7 @@ pub fn decimal() -> CoreLibTypeDefinition { } pub fn decimal_variant( - base_type: TypeContainer, + base_type: Type, variant: DecimalTypeVariant, ) -> CoreLibTypeDefinition { let variant_name = variant.as_ref().to_string(); @@ -294,7 +300,7 @@ pub fn integer() -> CoreLibTypeDefinition { } pub fn integer_variant( - base_type: TypeContainer, + base_type: Type, variant: IntegerTypeVariant, ) -> CoreLibTypeDefinition { let variant_name = variant.as_ref().to_string(); @@ -310,19 +316,19 @@ pub fn integer_variant( fn create_core_type( name: &str, variant: Option, - base_type: Option, + base_type: Option, pointer_id: CoreLibPointerId, ) -> CoreLibTypeDefinition { let base_type_ref = match base_type { - Some(TypeContainer::TypeReference(reference)) => Some(reference), - Some(TypeContainer::Type(_) | TypeContainer::TypeAlias(_)) => { - core::panic!("Base type must be a TypeReference") + Some(Type {type_definition: TypeDefinition::Reference(reference), ..}) => Some(reference), + Some(_) => { + core::panic!("Base type must be a Reference") } None => None, }; ( pointer_id.clone(), - TypeContainer::TypeReference(Rc::new(RefCell::new(TypeReference { + Type::new(TypeDefinition::reference(Rc::new(RefCell::new(TypeReference { nominal_type_declaration: Some(NominalTypeDeclaration { name: name.to_string(), variant, @@ -333,7 +339,7 @@ fn create_core_type( type_definition: TypeDefinition::Unit, }, pointer_address: Some(PointerAddress::from(pointer_id)), - }))), + }))), None), ) } @@ -465,14 +471,7 @@ mod tests { // integer -> integer -> integer ... let integer_type = get_core_lib_type(CoreLibPointerId::Integer(None)); let integer_base = integer_type.base_type(); - assert_matches!(integer_base, TypeContainer::TypeReference(_)); - assert_eq!(integer_base.to_string(), "integer"); - - let base = integer_base.base_type(); - assert_matches!(base, TypeContainer::TypeReference(_)); - assert_eq!(base.to_string(), "integer"); - - assert_eq!(integer_base, base); + assert_eq!(integer_base.unwrap().borrow().to_string(), "integer"); } #[test] @@ -481,18 +480,10 @@ mod tests { let integer_u8_type = get_core_lib_type(CoreLibPointerId::Integer( Some(IntegerTypeVariant::U8), )); - assert_matches!(integer_u8_type, TypeContainer::TypeReference(_)); assert_eq!(integer_u8_type.to_string(), "integer/u8"); let integer = integer_u8_type.base_type(); - assert_matches!(integer, TypeContainer::TypeReference(_)); - assert_eq!(integer.to_string(), "integer"); - assert_ne!(integer, integer_u8_type); - - let integer_again = integer.base_type(); - assert_matches!(integer_again, TypeContainer::TypeReference(_)); - assert_eq!(integer_again.to_string(), "integer"); - assert_eq!(integer_again, integer); + assert_eq!(integer.unwrap().borrow().to_string(), "integer"); } #[ignore] diff --git a/src/references/observers.rs b/src/references/observers.rs index c1c5b38da..e1436dd24 100644 --- a/src/references/observers.rs +++ b/src/references/observers.rs @@ -195,7 +195,7 @@ mod tests { values::value_container::ValueContainer, }; use datex_core::references::observers::Observer; - + use crate::dif::r#type::DIFTypeDefinition; /// Helper function to record DIF updates observed on a reference /// Returns a Rc>> that contains all observed updates @@ -375,7 +375,7 @@ mod tests { "a", DIFValue::new( DIFValueRepresentation::String("val".to_string()), - None as Option, + None as Option, ), )), }; diff --git a/src/references/reference.rs b/src/references/reference.rs index 3d8085f07..a7b5fe90a 100644 --- a/src/references/reference.rs +++ b/src/references/reference.rs @@ -30,6 +30,7 @@ use core::unreachable; use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; use core::write; +use crate::types::definition::TypeDefinition; #[derive(Debug)] pub struct IndexOutOfBoundsError { @@ -479,7 +480,7 @@ impl Reference { /// Creates a new reference from a value container pub fn try_new_from_value_container( value_container: ValueContainer, - allowed_type: Option, + allowed_type: Option, maybe_pointer_id: Option, mutability: ReferenceMutability, ) -> Result { @@ -633,14 +634,14 @@ impl Reference { } } - pub fn allowed_type(&self) -> TypeContainer { + pub fn allowed_type(&self) -> TypeDefinition { match self { Reference::ValueReference(vr) => vr.borrow().allowed_type.clone(), Reference::TypeReference(_) => core::todo!("#293 type Type"), } } - pub fn actual_type(&self) -> TypeContainer { + pub fn actual_type(&self) -> TypeDefinition { match self { Reference::ValueReference(vr) => vr .borrow() diff --git a/src/references/type_reference.rs b/src/references/type_reference.rs index d485fac0d..9264c9f93 100644 --- a/src/references/type_reference.rs +++ b/src/references/type_reference.rs @@ -109,7 +109,7 @@ impl TypeReference { } } pub fn mutability(&self) -> Option { - self.type_value.mutability() + self.type_value.reference_mutability() } } diff --git a/src/references/value_reference.rs b/src/references/value_reference.rs index 389267d54..0d46191b7 100644 --- a/src/references/value_reference.rs +++ b/src/references/value_reference.rs @@ -10,6 +10,8 @@ use crate::values::value_container::ValueContainer; use core::cell::RefCell; use core::fmt::Debug; use core::prelude::rust_2024::*; +use crate::types::definition::TypeDefinition; +use crate::types::structural_type_definition::StructuralTypeDefinition; pub struct ValueReference { /// the value that this reference points to @@ -17,7 +19,7 @@ pub struct ValueReference { /// pointer id, can be initialized as None for local pointers pub pointer_address: Option, /// custom type for the pointer that the Datex value is allowed to reference - pub allowed_type: TypeContainer, + pub allowed_type: TypeDefinition, /// list of observer callbacks pub observers: FreeHashMap, pub mutability: ReferenceMutability, @@ -28,7 +30,7 @@ impl Default for ValueReference { ValueReference { value_container: ValueContainer::Value(Value::null()), pointer_address: None, - allowed_type: TypeContainer::null(), + allowed_type: TypeDefinition::Unknown, observers: FreeHashMap::new(), mutability: ReferenceMutability::Immutable, } @@ -39,7 +41,7 @@ impl ValueReference { pub fn new( value_container: ValueContainer, pointer_address: Option, - allowed_type: TypeContainer, + allowed_type: TypeDefinition, mutability: ReferenceMutability, ) -> Self { ValueReference { diff --git a/src/runtime/execution.rs b/src/runtime/execution.rs index 62887775a..f7bf95425 100644 --- a/src/runtime/execution.rs +++ b/src/runtime/execution.rs @@ -1145,7 +1145,7 @@ fn handle_value( } let result_value = match &mut scope_container.scope { - + Scope::KeyValuePair => { let key = &scope_container.active_value; match key { @@ -1496,7 +1496,7 @@ fn handle_comparison_operation( } ComparisonOperator::Matches => { // TODO #407: Fix matches, rhs will always be a type, so actual_type() call is wrong - let v_type = value_container.actual_type(); // Type::try_from(value_container)?; + let v_type = value_container.actual_container_type(); // Type::try_from(value_container)?; let val = v_type.value_matches(active_value_container); Ok(ValueContainer::from(val)) } diff --git a/src/type_inference/error.rs b/src/type_inference/error.rs index 417e404e6..09734c8ac 100644 --- a/src/type_inference/error.rs +++ b/src/type_inference/error.rs @@ -3,24 +3,24 @@ use core::{fmt::Display, ops::Range}; use crate::{ compiler::error::ErrorCollector, global::operators::binary::ArithmeticOperator, - types::type_container::TypeContainer, }; +use crate::values::core_values::r#type::Type; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeError { SubvariantNotFound(String, String), // only for debugging purposes - InvalidDerefType(TypeContainer), + InvalidDerefType(Type), Unimplemented(String), - MismatchedOperands(ArithmeticOperator, TypeContainer, TypeContainer), + MismatchedOperands(ArithmeticOperator, Type, Type), AssignmentToImmutableReference(String), AssignmentToImmutableValue(String), AssignmentToConstant(String), // can not assign value to variable of different type AssignmentTypeMismatch { - annotated_type: TypeContainer, - assigned_type: TypeContainer, + annotated_type: Type, + assigned_type: Type, }, } diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 4c83906bc..9bea18e35 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -207,9 +207,9 @@ impl TypeInference { fn infer_expression( &mut self, expr: &mut DatexExpression, - ) -> Result { + ) -> Result { self.visit_datex_expression(expr)?; - Ok(expr.ty.clone().unwrap_or(TypeContainer::never())) + Ok(expr.ty.clone().unwrap_or(Type::never())) } fn infer_type_expression( @@ -540,11 +540,11 @@ impl ExpressionVisitor for TypeInference { ) -> ExpressionVisitResult { let inner_type = self.infer_expression(&mut create_ref.expression)?; mark_type(match &inner_type { - TypeContainer::Type(t) => TypeContainer::Type(Type { + TypeContainer::Type(t) => Type { type_definition: TypeDefinition::Type(Box::new(t.clone())), reference_mutability: Some(create_ref.mutability.clone()), base_type: None, - }), + }, // TODO #490: check if defined mutability of type reference matches TypeContainer::TypeReference(r) => TypeContainer::Type(Type { type_definition: TypeDefinition::Reference(r.clone()), @@ -1154,7 +1154,7 @@ impl ExpressionVisitor for TypeInference { // span: Some(span.clone()), // }); // } - if expression_type.mutability() != Some(ReferenceMutability::Mutable) { + if expression_type.reference_mutability() != Some(ReferenceMutability::Mutable) { return Err(SpannedTypeError { error: TypeError::AssignmentToImmutableReference( "".to_string(), diff --git a/src/types/definition.rs b/src/types/definition.rs index 210a6a610..d3828add5 100644 --- a/src/types/definition.rs +++ b/src/types/definition.rs @@ -10,13 +10,14 @@ use crate::{ types::{ collection_type_definition::CollectionTypeDefinition, structural_type_definition::StructuralTypeDefinition, - type_container::TypeContainer, }, }; use core::fmt::Display; use core::prelude::rust_2024::*; use datex_core::references::type_reference::TypeReference; +use crate::references::reference::ReferenceMutability; use crate::values::pointer::PointerAddress; +use crate::values::value_container::ValueContainer; #[derive(Debug, Clone, PartialEq, Eq)] pub enum TypeDefinition { @@ -28,16 +29,16 @@ pub enum TypeDefinition { Collection(CollectionTypeDefinition), /// type A = B - Reference(Rc>), + Reference(Rc>), // integer - /// type + /// type, used for nested types with references (e.g. &mut & x) Type(Box), /// a function type definition (function signature) Function { // FIXME #372: Include error type definition - parameters: Vec<(String, TypeContainer)>, - return_type: Box, + parameters: Vec<(String, Type)>, + return_type: Box, }, /// innerType + Marker1 + Marker2 @@ -46,16 +47,16 @@ pub enum TypeDefinition { /// The type is treated as equivalent to `innerType` for most operations, /// but the markers can be used to enforce additional constraints during /// type checking or runtime behavior. - MarkedType(Box, Vec), + MarkedType(Box, Vec), /// NOTE: all the types below can never exist as actual types of a runtime value - they are only /// relevant for type space definitions and type checking. - + /// A & B & C - Intersection(Vec), + Intersection(Vec), /// A | B | C - Union(Vec), + Union(Vec), /// () - e.g. if a function has no return type Unit, @@ -141,7 +142,7 @@ impl Display for TypeDefinition { TypeDefinition::Union(types) => { let is_level_zero = types.iter().all(|t| { core::matches!( - t.as_type().type_definition, + t.type_definition, TypeDefinition::Structural(_) | TypeDefinition::Reference(_) ) @@ -199,3 +200,86 @@ impl StructuralEq for TypeDefinition { } } } + + +impl TypeDefinition { + /// Creates a new structural type. + pub fn structural( + structural_type: impl Into, + ) -> Self { + TypeDefinition::Structural(structural_type.into()) + } + + /// Creates a new structural list type. + pub fn list(element_types: Vec) -> Self { + TypeDefinition::Structural( + StructuralTypeDefinition::List(element_types), + ) + } + + /// Creates a new union type. + pub fn union(types: Vec) -> Self + where + T: Into, + { + let types = types.into_iter().map(|t| t.into()).collect(); + TypeDefinition::Union(types) + } + + /// Creates a new intersection type. + pub fn intersection(types: Vec) -> Self + where + T: Into, + { + let types = types.into_iter().map(|t| t.into()).collect(); + TypeDefinition::Intersection(types) + } + + /// Creates a new reference type. + pub fn reference( + reference: Rc>, + ) -> Self { + TypeDefinition::Reference(reference.into()) + } + + /// Creates a new function type. + pub fn function( + parameters: Vec<(String, Type)>, + return_type: impl Into, + ) -> Self { + TypeDefinition::Function { + parameters, + return_type: Box::new(return_type.into()), + } + } + + /// Creates a new marked type. + pub fn marked( + ty: impl Into, + markers: Vec, + ) -> Self { + TypeDefinition::MarkedType( + Box::new(ty.into()), + markers, + ) + } + + pub fn into_type(self, reference_mutability: Option) -> Type { + Type { + type_definition: self, + base_type: None, + reference_mutability, + } + } +} + + +impl From for Type { + fn from(type_definition: TypeDefinition) -> Self { + Type { + type_definition, + base_type: None, + reference_mutability: None, + } + } +} \ No newline at end of file diff --git a/src/types/structural_type_definition.rs b/src/types/structural_type_definition.rs index 9dee0591a..1c38bb5f4 100644 --- a/src/types/structural_type_definition.rs +++ b/src/types/structural_type_definition.rs @@ -4,7 +4,6 @@ use crate::stdlib::string::String; use crate::stdlib::string::ToString; use crate::stdlib::vec::Vec; use crate::traits::structural_eq::StructuralEq; -use crate::types::type_container::TypeContainer; use crate::values::core_value::CoreValue; use crate::values::core_values::boolean::Boolean; use crate::values::core_values::decimal::Decimal; @@ -18,6 +17,7 @@ use core::prelude::rust_2024::*; use core::unimplemented; use datex_core::values::core_values::endpoint::Endpoint; use datex_core::values::core_values::integer::Integer; +use crate::values::core_values::r#type::Type; #[derive(Debug, Clone, PartialEq, Hash, Eq)] pub enum StructuralTypeDefinition { @@ -29,8 +29,8 @@ pub enum StructuralTypeDefinition { Boolean(Boolean), // FIXME #374 use bool Endpoint(Endpoint), Null, - List(Vec), - Map(Vec<(TypeContainer, TypeContainer)>), + List(Vec), // e.g. [&mut integer, text, boolean] + Map(Vec<(Type, Type)>), } macro_rules! impl_from_typed_int { diff --git a/src/types/type_container.rs b/src/types/type_container.rs index 9c4dcd8a5..b164a0e75 100644 --- a/src/types/type_container.rs +++ b/src/types/type_container.rs @@ -13,17 +13,17 @@ use core::fmt::Display; use core::hash::Hash; use core::prelude::rust_2024::*; -// TODO #376: move match logic and other type stuff here -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum TypeContainer { - Type(Type), - TypeReference(Rc>), - // FIXME either to this, or move the type alias as a TypeDefinition, - // which would allow for pointer id storage as well but would make - // the type matching more complex, then just storing the "transparency" - // in the most top-level type container - TypeAlias(Rc>), -} +// // TODO #376: move match logic and other type stuff here +// #[derive(Debug, Clone, PartialEq, Eq)] +// pub enum TypeContainer { +// Type(Type), +// TypeReference(Rc>), +// // FIXME either to this, or move the type alias as a TypeDefinition, +// // which would allow for pointer id storage as well but would make +// // the type matching more complex, then just storing the "transparency" +// // in the most top-level type container +// TypeAlias(Rc>), +// } impl Display for TypeContainer { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/src/values/core_value.rs b/src/values/core_value.rs index 92ff07f87..86587fd53 100644 --- a/src/values/core_value.rs +++ b/src/values/core_value.rs @@ -2,7 +2,7 @@ use core::prelude::rust_2024::*; use core::result::Result; use datex_macros::FromCoreValue; -use crate::libs::core::{CoreLibPointerId, get_core_lib_type}; +use crate::libs::core::{CoreLibPointerId, get_core_lib_type, get_core_lib_type_reference}; use crate::stdlib::string::String; use crate::stdlib::string::ToString; use crate::stdlib::vec::Vec; @@ -26,6 +26,9 @@ use crate::values::core_values::r#type::Type; use crate::values::value_container::{ValueContainer, ValueError}; use core::fmt::{Display, Formatter}; use core::ops::{Add, AddAssign, Neg, Not, Sub}; +use std::cell::RefCell; +use std::rc::Rc; +use datex_core::types::definition::TypeDefinition; #[derive(Clone, Debug, PartialEq, Eq, Hash, FromCoreValue)] pub enum CoreValue { @@ -241,8 +244,8 @@ impl CoreValue { /// This method uses the CoreLibPointerId to retrieve the corresponding /// type reference from the core library. /// For example, a CoreValue::TypedInteger(i32) will return the type ref integer/i32 - pub fn default_type(&self) -> TypeContainer { - get_core_lib_type(CoreLibPointerId::from(self)) + pub fn default_type_definition(&self) -> TypeDefinition { + TypeDefinition::Reference(get_core_lib_type_reference(CoreLibPointerId::from(self))) } // TODO #313: allow cast of any CoreValue to Type, as structural type can always be constructed? @@ -771,8 +774,8 @@ mod tests { fn type_construct() { init_logger_debug(); let a = CoreValue::from(42i32); - assert_eq!(a.default_type().to_string(), "integer/i32"); - assert_eq!(a.default_type().base_type().to_string(), "integer"); + assert_eq!(a.default_type_definition().to_string(), "integer/i32"); + assert_eq!(a.default_type_definition().base_type().to_string(), "integer"); } #[test] diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index 226b73472..1d4bdcb58 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -12,7 +12,6 @@ use crate::stdlib::vec::Vec; use crate::traits::structural_eq::StructuralEq; use crate::types::definition::TypeDefinition; use crate::types::structural_type_definition::StructuralTypeDefinition; -use crate::types::type_container::TypeContainer; use crate::values::core_value::CoreValue; use crate::values::core_value_trait::CoreValueTrait; use crate::values::core_values::boolean::Boolean; @@ -33,6 +32,8 @@ pub struct Type { pub reference_mutability: Option, } +// x: &User; Type {reference: } + impl Hash for Type { fn hash(&self, state: &mut H) { self.type_definition.hash(state); @@ -44,12 +45,6 @@ impl Hash for Type { } } -impl Type { - pub fn as_type_container(self) -> TypeContainer { - TypeContainer::Type(self) - } -} - impl Type { pub const UNIT: Type = Type { type_definition: TypeDefinition::Unit, @@ -75,101 +70,26 @@ impl Type { None } } - pub fn mutability(&self) -> Option { + pub fn reference_mutability(&self) -> Option { self.reference_mutability.clone() } -} - -impl Type { - /// Creates a new structural type. - pub fn structural( - structural_type: impl Into, - ) -> Self { - Type { - type_definition: TypeDefinition::Structural(structural_type.into()), - base_type: None, - reference_mutability: None, - } - } - - /// Creates a new structural list type. - pub fn list(element_types: Vec) -> Self { - Type { - type_definition: TypeDefinition::Structural( - StructuralTypeDefinition::List(element_types), - ), - base_type: None, - reference_mutability: None, - } - } - - /// Creates a new union type. - pub fn union(types: Vec) -> Self - where - T: Into, - { - let types = types.into_iter().map(|t| t.into()).collect(); - Type { - type_definition: TypeDefinition::Union(types), - base_type: None, - reference_mutability: None, - } - } - - /// Creates a new intersection type. - pub fn intersection(types: Vec) -> Self - where - T: Into, - { - let types = types.into_iter().map(|t| t.into()).collect(); - Type { - type_definition: TypeDefinition::Intersection(types), - base_type: None, - reference_mutability: None, - } - } - - /// Creates a new reference type. - pub fn reference( - reference: impl Into>>, - mutability: Option, - ) -> Self { - Type { - type_definition: TypeDefinition::Reference(reference.into()), - base_type: None, - reference_mutability: mutability, - } - } - /// Creates a new function type. - pub fn function( - parameters: Vec<(String, TypeContainer)>, - return_type: impl Into, - ) -> Self { - Type { - type_definition: TypeDefinition::Function { - parameters, - return_type: Box::new(return_type.into()), - }, - base_type: None, - reference_mutability: None, - } + pub fn is_reference_type(&self) -> bool { + self.reference_mutability.is_some() } +} - /// Creates a new marked type. - pub fn marked( - ty: impl Into, - markers: Vec, - ) -> Self { +impl Type { + + pub fn new(type_definition: TypeDefinition, reference_mutability: Option) -> Self { Type { - type_definition: TypeDefinition::MarkedType( - Box::new(ty.into()), - markers, - ), + type_definition, base_type: None, - reference_mutability: None, + reference_mutability, } } + + } impl Type { diff --git a/src/values/value.rs b/src/values/value.rs index c5d533336..9d00fcd7c 100644 --- a/src/values/value.rs +++ b/src/values/value.rs @@ -1,7 +1,6 @@ use crate::stdlib::boxed::Box; use crate::traits::structural_eq::StructuralEq; use crate::traits::value_eq::ValueEq; -use crate::types::type_container::TypeContainer; use crate::values::core_value::CoreValue; use crate::values::core_values::integer::typed_integer::TypedInteger; use crate::values::value_container::ValueError; @@ -12,11 +11,12 @@ use core::result::Result; use log::error; use crate::libs::core::CoreLibPointerId; use crate::references::type_reference::TypeReference; +use crate::types::definition::TypeDefinition; #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct Value { pub inner: CoreValue, - pub actual_type: Box, + pub actual_type: Box, } /// Two values are structurally equal, if their inner values are structurally equal, regardless @@ -46,7 +46,7 @@ impl Deref for Value { impl> From for Value { fn from(inner: T) -> Self { let inner = inner.into(); - let new_type = inner.default_type(); + let new_type = inner.default_type_definition(); Value { inner, actual_type: Box::new(new_type), @@ -84,7 +84,7 @@ impl Value { pub fn is_list(&self) -> bool { core::matches!(self.inner, CoreValue::List(_)) } - pub fn actual_type(&self) -> &TypeContainer { + pub fn actual_type(&self) -> &TypeDefinition { self.actual_type.as_ref() } @@ -98,7 +98,7 @@ impl Value { /// the variant must be included in the compiler output - so we need to handle theses cases as well. /// Generally speaking, all variants except the few integer variants should never be considered default types. pub fn has_default_type(&self) -> bool { - if let TypeContainer::TypeReference(type_reference) = self.actual_type.as_ref() && + if let TypeDefinition::Reference(type_reference) = self.actual_type.as_ref() && let TypeReference {pointer_address: Some(pointer_address), ..} = &*type_reference.borrow() && let Ok(actual_type_core_ptr_id) = CoreLibPointerId::try_from(pointer_address) { // actual_type has core type pointer id which is equal to the default core type pointer id of self.inner @@ -206,7 +206,7 @@ mod tests { use core::str::FromStr; use std::rc::Rc; use log::{debug, info}; - use datex_core::libs::core::get_core_lib_type_reference; + use datex_core::libs::core::{get_core_lib_type, get_core_lib_type_reference}; use crate::types::structural_type_definition::StructuralTypeDefinition; use crate::values::core_values::r#type::Type; @@ -377,7 +377,7 @@ mod tests { let val = Value { inner: CoreValue::Integer(Integer::from(42)), - actual_type: Box::new(TypeContainer::Type(Type::marked(get_core_lib_type_reference(CoreLibPointerId::Integer(None)), vec![]))), + actual_type: Box::new(TypeDefinition::MarkedType(get_core_lib_type(CoreLibPointerId::Integer(None)), vec![])), }; assert!(!val.has_default_type()); diff --git a/src/values/value_container.rs b/src/values/value_container.rs index 985c336c1..ecb4f0603 100644 --- a/src/values/value_container.rs +++ b/src/values/value_container.rs @@ -1,6 +1,5 @@ use crate::traits::identity::Identity; use crate::traits::structural_eq::StructuralEq; -use crate::types::type_container::TypeContainer; use core::cell::RefCell; use core::prelude::rust_2024::*; use core::result::Result; @@ -17,7 +16,9 @@ use core::ops::FnOnce; use core::ops::{Add, Neg, Sub}; use datex_core::references::reference::Reference; use serde::Deserialize; +use crate::types::definition::TypeDefinition; use crate::values::core_value::CoreValue; +use crate::values::core_values::r#type::Type; #[derive(Debug, Clone, PartialEq)] pub enum ValueError { @@ -261,23 +262,36 @@ impl ValueContainer { } } - /// Returns the allowed type of the value container - pub fn allowed_type(&self) -> TypeContainer { + /// Returns the actual type of the contained value, resolving references if necessary. + pub fn actual_value_type(&self) -> TypeDefinition { match self { - // If it's a Value, return its actual type ValueContainer::Value(value) => value.actual_type().clone(), ValueContainer::Reference(reference) => { - reference.allowed_type().clone() + reference.actual_type().clone() } } } - /// Returns the actual type of the contained value, resolving references if necessary. - pub fn actual_type(&self) -> TypeContainer { + /// Returns the actual type that describes the value container (e.g. integer or &&mut integer). + pub fn actual_container_type(&self) -> Type { match self { - ValueContainer::Value(value) => value.actual_type().clone(), + ValueContainer::Value(value) => Type::new( + *value.actual_type.clone(), + None, + ), ValueContainer::Reference(reference) => { - reference.actual_type().clone() + let inner_type = reference.value_container().actual_container_type(); + Type::new( + // when nesting references, we need to keep the reference information + if inner_type.is_reference_type() { + TypeDefinition::Type(Box::new(inner_type)) + } + // for simple non-ref type, we can collapse the definition + else { + inner_type.type_definition + }, + Some(reference.mutability()), + ) } } } @@ -352,26 +366,6 @@ impl> From for ValueContainer { } } -impl From for ValueContainer { - fn from(type_container: TypeContainer) -> Self { - match type_container { - TypeContainer::Type(type_value) => { - ValueContainer::Value(Value::from(type_value)) - } - TypeContainer::TypeReference(type_reference) => { - ValueContainer::Reference(Reference::TypeReference( - type_reference, - )) - } - TypeContainer::TypeAlias(type_alias) => { - unreachable!( - "Cannot convert TypeAlias directly to ValueContainer" - ) - } - } - } -} - impl Add for ValueContainer { type Output = Result; From a7115bf6545d461216552947fd66ef99d92723aa Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 12:51:40 +0100 Subject: [PATCH 02/10] refactoring on types (WIP) --- src/lsp/mod.rs | 14 +++---- src/lsp/utils.rs | 4 +- src/references/reference.rs | 34 +++++++--------- src/values/core_values/endpoint.rs | 1 + src/values/core_values/type.rs | 63 +++++++++++++++++++++++++++--- 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/lsp/mod.rs b/src/lsp/mod.rs index 1f0abed96..e77a5c7b3 100644 --- a/src/lsp/mod.rs +++ b/src/lsp/mod.rs @@ -8,13 +8,13 @@ use crate::runtime::Runtime; use crate::stdlib::borrow::Cow; use crate::stdlib::cell::RefCell; use crate::stdlib::collections::HashMap; +use crate::values::core_values::r#type::Type; use datex_core::ast::structs::expression::{ DatexExpressionData, VariableAccess, VariableAssignment, VariableDeclaration, }; use datex_core::compiler::precompiler::precompiled_ast::RichAst; use datex_core::compiler::workspace::CompilerWorkspace; -use datex_core::types::type_container::TypeContainer; use datex_core::visitor::expression::ExpressionVisitor; use realhydroper_lsp::jsonrpc::{Error, ErrorCode}; use realhydroper_lsp::{Client, LanguageServer, Server}; @@ -187,13 +187,11 @@ impl LanguageServer for LanguageServerBackend { let variable_metadata = self.get_variable_by_id(id).unwrap(); Some(self.get_language_string_hover(&format!( - "{} {}: {}", - variable_metadata.shape, - name, - variable_metadata - .var_type - .unwrap_or(TypeContainer::unknown()) - ))) + "{} {}: {}", + variable_metadata.shape, + name, + variable_metadata.var_type.unwrap_or(Type::unknown()) + ))) } // show value info on hover for literals diff --git a/src/lsp/utils.rs b/src/lsp/utils.rs index abee828ce..895180cee 100644 --- a/src/lsp/utils.rs +++ b/src/lsp/utils.rs @@ -1,13 +1,13 @@ use crate::lsp::LanguageServerBackend; use crate::lsp::errors::SpannedLSPCompilerError; use crate::lsp::type_hint_collector::TypeHintCollector; +use crate::values::core_values::r#type::Type; use datex_core::ast::structs::expression::{ DatexExpression, DatexExpressionData, List, Map, Statements, VariableAccess, VariableAssignment, VariableDeclaration, }; use datex_core::compiler::error::DetailedCompilerErrors; use datex_core::compiler::precompiler::precompiled_ast::VariableMetadata; -use datex_core::types::type_container::TypeContainer; use datex_core::values::core_values::decimal::Decimal; use datex_core::values::core_values::decimal::typed_decimal::TypedDecimal; use datex_core::values::core_values::endpoint::Endpoint; @@ -55,7 +55,7 @@ impl LanguageServerBackend { pub(crate) fn get_type_hints( &self, url: Url, - ) -> Option)>> { + ) -> Option)>> { let mut workspace = self.compiler_workspace.borrow_mut(); let file = workspace.get_file_mut(&url).unwrap(); if let Some(rich_ast) = &mut file.rich_ast { diff --git a/src/references/reference.rs b/src/references/reference.rs index a7b5fe90a..deb1d3a29 100644 --- a/src/references/reference.rs +++ b/src/references/reference.rs @@ -1,7 +1,6 @@ use crate::references::type_reference::{ NominalTypeDeclaration, TypeReference, }; -use crate::types::type_container::TypeContainer; use crate::values::core_value::CoreValue; use core::prelude::rust_2024::*; use core::result::Result; @@ -16,6 +15,7 @@ use crate::traits::apply::Apply; use crate::traits::identity::Identity; use crate::traits::structural_eq::StructuralEq; use crate::traits::value_eq::ValueEq; +use crate::types::definition::TypeDefinition; use crate::values::core_values::map::MapAccessError; use crate::values::core_values::r#type::Type; use crate::values::pointer::PointerAddress; @@ -27,10 +27,9 @@ use core::hash::{Hash, Hasher}; use core::ops::FnOnce; use core::option::Option; use core::unreachable; +use core::write; use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; -use core::write; -use crate::types::definition::TypeDefinition; #[derive(Debug)] pub struct IndexOutOfBoundsError { @@ -54,7 +53,6 @@ impl Display for KeyNotFoundError { } } - #[derive(Debug)] pub enum AccessError { ImmutableReference, @@ -110,10 +108,7 @@ impl Display for AccessError { #[derive(Debug)] pub enum TypeError { - TypeMismatch { - expected: TypeContainer, - found: TypeContainer, - }, + TypeMismatch { expected: Type, found: Type }, } impl Display for TypeError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -121,8 +116,7 @@ impl Display for TypeError { TypeError::TypeMismatch { expected, found } => write!( f, "Type mismatch: expected {}, found {}", - expected, - found + expected, found ), } } @@ -510,7 +504,7 @@ impl Reference { } Reference::TypeReference( TypeReference::anonymous( - Type::reference(tr.clone(), Some(mutability)), + Type::reference(tr.clone(), mutability), maybe_pointer_id, ) .as_ref_cell(), @@ -710,19 +704,18 @@ impl Reference { // -> we could avoid some clones if so (as get, addition, set would all be a clone) pub fn try_get_property<'a>( &self, - key: impl Into> + key: impl Into>, ) -> Result { self.with_value(|value| { match value.inner { CoreValue::Map(ref mut map) => { // If the value is a map, get the property Ok(map.get(key)?.clone()) - }, + } CoreValue::List(ref mut list) => { if let Some(index) = key.into().try_as_index() { Ok(list.get(index)?.clone()) - } - else { + } else { Err(AccessError::InvalidIndexKey) } } @@ -730,8 +723,7 @@ impl Reference { if let Some(index) = key.into().try_as_index() { let char = text.char_at(index)?; Ok(ValueContainer::from(char.to_string())) - } - else { + } else { Err(AccessError::InvalidIndexKey) } } @@ -865,7 +857,9 @@ mod tests { assert_matches!( reference.try_get_property(100), - Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError { index: 100 })) + Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError { + index: 100 + })) ); let text_ref = Reference::from(ValueContainer::from("hello")); @@ -876,7 +870,9 @@ mod tests { assert!(text_ref.try_get_property(5).is_err()); assert_matches!( text_ref.try_get_property(100), - Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError { index: 100 })) + Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError { + index: 100 + })) ); } diff --git a/src/values/core_values/endpoint.rs b/src/values/core_values/endpoint.rs index ad26b5159..b56cbe4ca 100644 --- a/src/values/core_values/endpoint.rs +++ b/src/values/core_values/endpoint.rs @@ -85,6 +85,7 @@ impl> TryFrom> for Endpoint { Err(ValueError::TypeConversionError) } } + // also for ref // impl> TryFrom<&Option> for Endpoint { // type Error = ValueError; diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index 1d4bdcb58..7a2e79d50 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -1,5 +1,7 @@ #[cfg(feature = "compiler")] use crate::ast::structs::expression::DatexExpressionData; +use crate::libs::core::CoreLibPointerId; +use crate::libs::core::get_core_lib_type; use crate::libs::core::get_core_lib_type_reference; use crate::references::reference::ReferenceMutability; use crate::references::type_reference::TypeReference; @@ -15,7 +17,10 @@ use crate::types::structural_type_definition::StructuralTypeDefinition; use crate::values::core_value::CoreValue; use crate::values::core_value_trait::CoreValueTrait; use crate::values::core_values::boolean::Boolean; +use crate::values::core_values::decimal::typed_decimal::DecimalTypeVariant; +use crate::values::core_values::integer::typed_integer::IntegerTypeVariant; use crate::values::core_values::text::Text; +use crate::values::pointer::PointerAddress; use crate::values::value_container::ValueContainer; use core::cell::RefCell; use core::fmt::Display; @@ -23,7 +28,6 @@ use core::hash::{Hash, Hasher}; use core::prelude::rust_2024::*; use core::result::Result; use core::unimplemented; -use crate::values::pointer::PointerAddress; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Type { @@ -45,6 +49,45 @@ impl Hash for Type { } } +impl Type { + pub fn unit() -> Self { + get_core_lib_type(CoreLibPointerId::Unit) + } + pub fn null() -> Self { + get_core_lib_type(CoreLibPointerId::Null) + } + pub fn never() -> Self { + get_core_lib_type(CoreLibPointerId::Never) + } + pub fn unknown() -> Self { + get_core_lib_type(CoreLibPointerId::Unknown) + } + pub fn text() -> Self { + get_core_lib_type(CoreLibPointerId::Text) + } + pub fn integer() -> Self { + get_core_lib_type(CoreLibPointerId::Integer(None)) + } + pub fn typed_integer(variant: IntegerTypeVariant) -> Self { + get_core_lib_type(CoreLibPointerId::Integer(Some(variant))) + } + pub fn decimal() -> Self { + get_core_lib_type(CoreLibPointerId::Decimal(None)) + } + pub fn typed_decimal(variant: DecimalTypeVariant) -> Self { + get_core_lib_type(CoreLibPointerId::Decimal(Some(variant))) + } + pub fn boolean() -> Self { + get_core_lib_type(CoreLibPointerId::Boolean) + } + pub fn endpoint() -> Self { + get_core_lib_type(CoreLibPointerId::Endpoint) + } + pub fn ty() -> Self { + get_core_lib_type(CoreLibPointerId::Type) + } +} + impl Type { pub const UNIT: Type = Type { type_definition: TypeDefinition::Unit, @@ -80,16 +123,26 @@ impl Type { } impl Type { - - pub fn new(type_definition: TypeDefinition, reference_mutability: Option) -> Self { + pub fn new( + type_definition: TypeDefinition, + reference_mutability: Option, + ) -> Self { Type { type_definition, base_type: None, reference_mutability, } } - - + pub fn reference( + type_definition: Rc>, + reference_mutability: ReferenceMutability, + ) -> Self { + Type { + type_definition: TypeDefinition::Reference(type_definition), + base_type: None, + reference_mutability: Some(reference_mutability), + } + } } impl Type { From 0fa8006221e07889360342a138c35dc896fa414e Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 12:56:13 +0100 Subject: [PATCH 03/10] refactoring on types (WIP) --- src/values/core_value.rs | 12 ++++++------ src/values/core_values/type.rs | 33 ++++++++++++++++---------------- src/values/value.rs | 35 ++++++++++++++++++++++------------ src/visitor/mod.rs | 6 +++--- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/src/values/core_value.rs b/src/values/core_value.rs index 86587fd53..5b65ec453 100644 --- a/src/values/core_value.rs +++ b/src/values/core_value.rs @@ -2,13 +2,12 @@ use core::prelude::rust_2024::*; use core::result::Result; use datex_macros::FromCoreValue; -use crate::libs::core::{CoreLibPointerId, get_core_lib_type, get_core_lib_type_reference}; +use crate::libs::core::{CoreLibPointerId, get_core_lib_type_reference}; use crate::stdlib::string::String; use crate::stdlib::string::ToString; use crate::stdlib::vec::Vec; use crate::traits::structural_eq::StructuralEq; use crate::traits::value_eq::ValueEq; -use crate::types::type_container::TypeContainer; use crate::values::core_values::boolean::Boolean; use crate::values::core_values::decimal::Decimal; use crate::values::core_values::decimal::typed_decimal::{ @@ -26,9 +25,9 @@ use crate::values::core_values::r#type::Type; use crate::values::value_container::{ValueContainer, ValueError}; use core::fmt::{Display, Formatter}; use core::ops::{Add, AddAssign, Neg, Not, Sub}; +use datex_core::types::definition::TypeDefinition; use std::cell::RefCell; use std::rc::Rc; -use datex_core::types::definition::TypeDefinition; #[derive(Clone, Debug, PartialEq, Eq, Hash, FromCoreValue)] pub enum CoreValue { @@ -240,12 +239,14 @@ impl CoreValue { core::matches!(self, CoreValue::List(_) | CoreValue::Map(_)) } - /// Get the default type of the CoreValue as a TypeContainer. + /// Get the default type of the CoreValue type definition. /// This method uses the CoreLibPointerId to retrieve the corresponding /// type reference from the core library. /// For example, a CoreValue::TypedInteger(i32) will return the type ref integer/i32 pub fn default_type_definition(&self) -> TypeDefinition { - TypeDefinition::Reference(get_core_lib_type_reference(CoreLibPointerId::from(self))) + TypeDefinition::Reference(get_core_lib_type_reference( + CoreLibPointerId::from(self), + )) } // TODO #313: allow cast of any CoreValue to Type, as structural type can always be constructed? @@ -775,7 +776,6 @@ mod tests { init_logger_debug(); let a = CoreValue::from(42i32); assert_eq!(a.default_type_definition().to_string(), "integer/i32"); - assert_eq!(a.default_type_definition().base_type().to_string(), "integer"); } #[test] diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index 7a2e79d50..b4d7f93e6 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -143,6 +143,15 @@ impl Type { reference_mutability: Some(reference_mutability), } } + pub fn structural( + structural_type: impl Into, + ) -> Self { + Type { + type_definition: TypeDefinition::Structural(structural_type.into()), + base_type: None, + reference_mutability: None, + } + } } impl Type { @@ -210,7 +219,7 @@ impl Type { TypeDefinition::Intersection(members) => { // If self is an intersection, all members must match the other type for member in members { - if !member.as_type().matches_type(other) { + if !member.matches_type(other) { return false; } } @@ -246,15 +255,11 @@ impl Type { // e.g. 1 matches 1 | 2 TypeDefinition::Union(types) => { // value must match at least one of the union types - types - .iter() - .any(|t| Type::value_matches_type(value, &t.as_type())) + types.iter().any(|t| Type::value_matches_type(value, &t)) } TypeDefinition::Intersection(types) => { // value must match all of the intersection types - types - .iter() - .all(|t| Type::value_matches_type(value, &t.as_type())) + types.iter().all(|t| Type::value_matches_type(value, &t)) } TypeDefinition::Structural(structural_type) => { structural_type.value_matches(value) @@ -280,7 +285,7 @@ impl Type { TypeDefinition::Never => false, TypeDefinition::Unknown => false, TypeDefinition::MarkedType(ty, _) => { - Type::value_matches_type(value, &ty.as_type()) + Type::value_matches_type(value, &ty) } } } @@ -340,25 +345,21 @@ impl From<&CoreValue> for Type { .iter() .map(|v| Type::from(v.to_value().borrow().inner.clone())) .collect::>(); - Type::structural(StructuralTypeDefinition::List( - types.into_iter().map(TypeContainer::from).collect(), - )) + Type::structural(StructuralTypeDefinition::List(types)) } CoreValue::Map(map) => { let struct_types = map .into_iter() .map(|(key, value)| { ( - TypeContainer::from(Type::from( + Type::from( ValueContainer::from(key) .to_value() .borrow() .inner .clone(), - )), - TypeContainer::from(Type::from( - value.to_value().borrow().inner.clone(), - )), + ), + Type::from(value.to_value().borrow().inner.clone()), ) }) .collect::>(); diff --git a/src/values/value.rs b/src/values/value.rs index 9d00fcd7c..1d5e63ee5 100644 --- a/src/values/value.rs +++ b/src/values/value.rs @@ -1,6 +1,9 @@ +use crate::libs::core::CoreLibPointerId; +use crate::references::type_reference::TypeReference; use crate::stdlib::boxed::Box; use crate::traits::structural_eq::StructuralEq; use crate::traits::value_eq::ValueEq; +use crate::types::definition::TypeDefinition; use crate::values::core_value::CoreValue; use crate::values::core_values::integer::typed_integer::TypedInteger; use crate::values::value_container::ValueError; @@ -9,9 +12,6 @@ use core::ops::{Add, AddAssign, Deref, Neg, Not, Sub}; use core::prelude::rust_2024::*; use core::result::Result; use log::error; -use crate::libs::core::CoreLibPointerId; -use crate::references::type_reference::TypeReference; -use crate::types::definition::TypeDefinition; #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct Value { @@ -98,14 +98,20 @@ impl Value { /// the variant must be included in the compiler output - so we need to handle theses cases as well. /// Generally speaking, all variants except the few integer variants should never be considered default types. pub fn has_default_type(&self) -> bool { - if let TypeDefinition::Reference(type_reference) = self.actual_type.as_ref() && - let TypeReference {pointer_address: Some(pointer_address), ..} = &*type_reference.borrow() && - let Ok(actual_type_core_ptr_id) = CoreLibPointerId::try_from(pointer_address) { + if let TypeDefinition::Reference(type_reference) = + self.actual_type.as_ref() + && let TypeReference { + pointer_address: Some(pointer_address), + .. + } = &*type_reference.borrow() + && let Ok(actual_type_core_ptr_id) = + CoreLibPointerId::try_from(pointer_address) + { // actual_type has core type pointer id which is equal to the default core type pointer id of self.inner let self_default_type_ptr_id = CoreLibPointerId::from(&self.inner); self_default_type_ptr_id == actual_type_core_ptr_id } else { - false + false } } } @@ -194,6 +200,8 @@ where /// The value is a holder for a combination of a CoreValue representation and its actual type. mod tests { use super::*; + use crate::types::structural_type_definition::StructuralTypeDefinition; + use crate::values::core_values::r#type::Type; use crate::{ assert_structural_eq, datex_list, logger::init_logger_debug, @@ -204,11 +212,11 @@ mod tests { }, }; use core::str::FromStr; - use std::rc::Rc; + use datex_core::libs::core::{ + get_core_lib_type, get_core_lib_type_reference, + }; use log::{debug, info}; - use datex_core::libs::core::{get_core_lib_type, get_core_lib_type_reference}; - use crate::types::structural_type_definition::StructuralTypeDefinition; - use crate::values::core_values::r#type::Type; + use std::rc::Rc; #[test] fn endpoint() { @@ -377,7 +385,10 @@ mod tests { let val = Value { inner: CoreValue::Integer(Integer::from(42)), - actual_type: Box::new(TypeDefinition::MarkedType(get_core_lib_type(CoreLibPointerId::Integer(None)), vec![])), + actual_type: Box::new(TypeDefinition::MarkedType( + Box::new(get_core_lib_type(CoreLibPointerId::Integer(None))), + vec![], + )), }; assert!(!val.has_default_type()); diff --git a/src/visitor/mod.rs b/src/visitor/mod.rs index 9bb7c9004..e39b761a4 100644 --- a/src/visitor/mod.rs +++ b/src/visitor/mod.rs @@ -1,4 +1,4 @@ -use crate::types::type_container::TypeContainer; +use crate::values::core_values::r#type::Type; pub mod expression; pub mod type_expression; @@ -17,9 +17,9 @@ pub enum VisitAction { /// Replace the current node with a new one, and recurse into it ReplaceRecurse(T), /// Set the type annotation of the current node, and recurse into child nodes - SetTypeRecurseChildNodes(TypeContainer), + SetTypeRecurseChildNodes(Type), /// Set the type annotation of the current node, skipping child nodes - SetTypeSkipChildren(TypeContainer), + SetTypeSkipChildren(Type), /// Convert the current node to a no-op ToNoop, } From 929c5fdb2a64e2cb5f15730aeb758b83af91ce74 Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 13:28:34 +0100 Subject: [PATCH 04/10] refactoring on types (WIP) --- src/references/type_reference.rs | 15 +- src/references/value_reference.rs | 4 +- src/runtime/execution.rs | 6 +- src/runtime/memory.rs | 18 +- src/type_inference/mod.rs | 272 ++++++++++++------------------ src/values/core_values/type.rs | 52 +++++- 6 files changed, 176 insertions(+), 191 deletions(-) diff --git a/src/references/type_reference.rs b/src/references/type_reference.rs index 9264c9f93..55e17bfe1 100644 --- a/src/references/type_reference.rs +++ b/src/references/type_reference.rs @@ -13,7 +13,6 @@ use crate::stdlib::{ string::String, }; use crate::traits::apply::Apply; -use crate::types::type_container::TypeContainer; use crate::values::pointer::PointerAddress; use crate::values::value_container::ValueContainer; use crate::{ @@ -92,8 +91,12 @@ impl TypeReference { pub fn as_ref_cell(self) -> Rc> { Rc::new(RefCell::new(self)) } - pub fn as_type_container(self) -> TypeContainer { - TypeContainer::TypeReference(self.as_ref_cell()) + + /// Convert this TypeReference into a Type representing a reference to the underlying type + pub fn as_type(self) -> Type { + let mutability = + self.mutability().unwrap_or(ReferenceMutability::Immutable); + Type::reference(self.as_ref_cell(), mutability) } pub fn collapse_reference_chain(&self) -> TypeReference { @@ -114,9 +117,9 @@ impl TypeReference { } impl TypeReference { - pub fn as_type(&self) -> &Type { - &self.type_value - } + // pub fn as_type(&self) -> &Type { + // &self.type_value + // } pub fn base_type(&self) -> Option>> { self.type_value.base_type() diff --git a/src/references/value_reference.rs b/src/references/value_reference.rs index 0d46191b7..40cd6d69a 100644 --- a/src/references/value_reference.rs +++ b/src/references/value_reference.rs @@ -2,7 +2,7 @@ use crate::references::observers::Observer; use crate::references::reference::ReferenceMutability; use crate::stdlib::rc::Rc; use crate::traits::value_eq::ValueEq; -use crate::types::type_container::TypeContainer; +use crate::types::definition::TypeDefinition; use crate::utils::freemap::FreeHashMap; use crate::values::pointer::PointerAddress; use crate::values::value::Value; @@ -10,8 +10,6 @@ use crate::values::value_container::ValueContainer; use core::cell::RefCell; use core::fmt::Debug; use core::prelude::rust_2024::*; -use crate::types::definition::TypeDefinition; -use crate::types::structural_type_definition::StructuralTypeDefinition; pub struct ValueReference { /// the value that this reference points to diff --git a/src/runtime/execution.rs b/src/runtime/execution.rs index f7bf95425..b9b993724 100644 --- a/src/runtime/execution.rs +++ b/src/runtime/execution.rs @@ -35,7 +35,6 @@ use crate::traits::identity::Identity; use crate::traits::structural_eq::StructuralEq; use crate::traits::value_eq::ValueEq; use crate::types::error::IllegalTypeError; -use crate::types::type_container::TypeContainer; use crate::utils::buffers::append_u32; use crate::values::core_value::CoreValue; use crate::values::core_values::decimal::Decimal; @@ -565,7 +564,7 @@ impl Display for ExecutionError { #[derive(Debug)] pub enum ExecutionStep { InternalReturn(Option), - InternalTypeReturn(Option), + InternalTypeReturn(Option), Return(Option), ResolvePointer(RawFullPointerAddress), ResolveLocalPointer(RawLocalPointerAddress), @@ -1123,7 +1122,7 @@ fn iterate_type_instructions( } TypeInstruction::LiteralInteger(integer) => { yield Ok(ExecutionStep::InternalTypeReturn(Some( - TypeContainer::Type(Type::structural(integer.0)), + Type::structural(integer.0), ))); } _ => core::todo!("#405 Undescribed by author."), @@ -1145,7 +1144,6 @@ fn handle_value( } let result_value = match &mut scope_container.scope { - Scope::KeyValuePair => { let key = &scope_container.active_value; match key { diff --git a/src/runtime/memory.rs b/src/runtime/memory.rs index 8a9468d80..f32a67b98 100644 --- a/src/runtime/memory.rs +++ b/src/runtime/memory.rs @@ -6,8 +6,8 @@ use crate::references::value_reference::ValueReference; use crate::stdlib::rc::Rc; use crate::stdlib::vec::Vec; use crate::types::error::IllegalTypeError; -use crate::types::type_container::TypeContainer; use crate::utils::time::Time; +use crate::values::core_values::r#type::Type; use crate::values::pointer::PointerAddress; use binrw::io::Cursor; use core::cell::RefCell; @@ -104,29 +104,27 @@ impl Memory { } /// Helper function to get a core type directly from memory if it can be used as a type - pub fn get_core_type( + pub fn get_core_type_reference( &self, pointer_id: CoreLibPointerId, - ) -> Result { + ) -> Result>, IllegalTypeError> { let reference = self .get_reference(&pointer_id.into()) .ok_or(IllegalTypeError::TypeNotFound)?; - match &reference { - Reference::TypeReference(def) => { - Ok(TypeContainer::TypeReference(def.clone())) - } + match reference { + Reference::TypeReference(def) => Ok(def.clone()), _ => Err(IllegalTypeError::TypeNotFound), } } /// Helper function to get a core type directly from memory, asserting that is can be used as a type /// Panics if the core type is not found or cannot be used as a type. - pub fn get_core_type_unchecked( + pub fn get_core_type_reference_unchecked( &self, pointer_id: CoreLibPointerId, - ) -> TypeContainer { + ) -> Rc> { // FIXME #415: Mark as unchecked - self.get_core_type(pointer_id) + self.get_core_type_reference(pointer_id) .expect("core type not found or cannot be used as a type") } diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 9bea18e35..5273e9ae5 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -16,7 +16,9 @@ use crate::{ AssignmentOperator, BinaryOperator, LogicalUnaryOperator, UnaryOperator, }, libs::core::get_core_lib_type_reference, - references::reference::ReferenceMutability, + references::{ + reference::ReferenceMutability, type_reference::TypeReference, + }, stdlib::rc::Rc, type_inference::{error::TypeError, options::ErrorHandling}, types::definition::TypeDefinition, @@ -42,10 +44,7 @@ use crate::{ }, options::InferExpressionTypeOptions, }, - types::{ - structural_type_definition::StructuralTypeDefinition, - type_container::TypeContainer, - }, + types::structural_type_definition::StructuralTypeDefinition, values::{ core_values::{ boolean::Boolean, @@ -71,13 +70,13 @@ pub mod options; // TODO: refactor InferOutcome to a struct containing type, errors and warnings pub enum InferOutcome { - Ok(TypeContainer), + Ok(Type), OkWithErrors { - ty: TypeContainer, + ty: Type, errors: DetailedTypeErrors, }, } -impl From for TypeContainer { +impl From for Type { fn from(outcome: InferOutcome) -> Self { match outcome { InferOutcome::Ok(ty) => ty, @@ -88,7 +87,7 @@ impl From for TypeContainer { pub fn infer_expression_type_simple_error( rich_ast: &mut RichAst, -) -> Result { +) -> Result { match infer_expression_type( rich_ast, InferExpressionTypeOptions { @@ -105,7 +104,7 @@ pub fn infer_expression_type_simple_error( pub fn infer_expression_type_detailed_errors( rich_ast: &mut RichAst, -) -> Result { +) -> Result { match infer_expression_type( rich_ast, InferExpressionTypeOptions { @@ -191,7 +190,7 @@ impl TypeInference { } ErrorHandling::CollectAndReturnType => { - let ty = result.unwrap_or_else(|_| TypeContainer::never()); + let ty = result.unwrap_or_else(|_| Type::never()); if has_errors { Ok(InferOutcome::OkWithErrors { ty, @@ -215,18 +214,18 @@ impl TypeInference { fn infer_type_expression( &mut self, type_expr: &mut TypeExpression, - ) -> Result { + ) -> Result { self.visit_type_expression(type_expr)?; - Ok(type_expr.ty.clone().unwrap_or(TypeContainer::never())) + Ok(type_expr.ty.clone().unwrap_or(Type::never())) } - fn variable_type(&self, id: usize) -> Option { + fn variable_type(&self, id: usize) -> Option { self.metadata .borrow() .variable_metadata(id) .and_then(|meta| meta.var_type.clone()) } - fn update_variable_type(&mut self, id: usize, var_type: TypeContainer) { + fn update_variable_type(&mut self, id: usize, var_type: Type) { if let Some(var_meta) = self.metadata.borrow_mut().variable_metadata_mut(id) { @@ -242,9 +241,9 @@ impl TypeInference { if let Some(collected_errors) = &mut self.errors { let action = match error.error { TypeError::Unimplemented(_) => { - VisitAction::SetTypeRecurseChildNodes(TypeContainer::never()) + VisitAction::SetTypeRecurseChildNodes(Type::never()) } - _ => VisitAction::SetTypeSkipChildren(TypeContainer::never()), + _ => VisitAction::SetTypeSkipChildren(Type::never()), }; collected_errors.errors.push(error); Ok(action) @@ -257,12 +256,10 @@ impl TypeInference { fn mark_structural_type( definition: StructuralTypeDefinition, ) -> Result, SpannedTypeError> { - mark_type(Type::structural(definition).as_type_container()) + mark_type(Type::structural(definition)) } -fn mark_type( - type_container: TypeContainer, -) -> Result, SpannedTypeError> { - Ok(VisitAction::SetTypeSkipChildren(type_container)) +fn mark_type(ty: Type) -> Result, SpannedTypeError> { + Ok(VisitAction::SetTypeSkipChildren(ty)) } impl TypeExpressionVisitor for TypeInference { @@ -341,7 +338,7 @@ impl TypeExpressionVisitor for TypeInference { .iter_mut() .map(|member| self.infer_type_expression(member)) .collect::, _>>()?; - mark_type(Type::union(members).as_type_container()) + mark_type(Type::union(members)) } fn visit_intersection_type( &mut self, @@ -353,7 +350,7 @@ impl TypeExpressionVisitor for TypeInference { .iter_mut() .map(|member| self.infer_type_expression(member)) .collect::, _>>()?; - mark_type(Type::intersection(members).as_type_container()) + mark_type(Type::intersection(members)) } fn visit_structural_map_type( &mut self, @@ -403,10 +400,7 @@ impl TypeExpressionVisitor for TypeInference { var_access: &mut VariableAccess, _: &Range, ) -> TypeExpressionVisitResult { - mark_type( - self.variable_type(var_access.id) - .unwrap_or(TypeContainer::never()), - ) + mark_type(self.variable_type(var_access.id).unwrap_or(Type::never())) } fn visit_fixed_size_list_type( &mut self, @@ -435,9 +429,7 @@ impl TypeExpressionVisitor for TypeInference { Ok((key.clone(), param_type)) }) .collect::, SpannedTypeError>>()?; - mark_type( - Type::function(parameter_types, assigned_type).as_type_container(), - ) + mark_type(Type::function(parameter_types, assigned_type)) } fn visit_generic_access_type( &mut self, @@ -539,22 +531,14 @@ impl ExpressionVisitor for TypeInference { _: &Range, ) -> ExpressionVisitResult { let inner_type = self.infer_expression(&mut create_ref.expression)?; - mark_type(match &inner_type { - TypeContainer::Type(t) => Type { - type_definition: TypeDefinition::Type(Box::new(t.clone())), - reference_mutability: Some(create_ref.mutability.clone()), - base_type: None, - }, - // TODO #490: check if defined mutability of type reference matches - TypeContainer::TypeReference(r) => TypeContainer::Type(Type { - type_definition: TypeDefinition::Reference(r.clone()), - reference_mutability: Some(create_ref.mutability.clone()), - base_type: None, - }), - TypeContainer::TypeAlias(_) => { - unimplemented!("CreateRef for TypeAlias is not implemented yet") - } - }) + let ref_type = match inner_type.type_definition { + TypeDefinition::Reference(reference) => reference, + _ => Rc::new(RefCell::new(TypeReference::anonymous( + inner_type, None, + ))), + }; + + mark_type(Type::reference(ref_type, create_ref.mutability.clone())) } fn handle_expression_error( @@ -570,7 +554,7 @@ impl ExpressionVisitor for TypeInference { statements: &mut Statements, _: &Range, ) -> ExpressionVisitResult { - let mut inferred_type = TypeContainer::unit(); + let mut inferred_type = Type::unit(); // Infer type for each statement in order for statement in statements.statements.iter_mut() { @@ -580,7 +564,7 @@ impl ExpressionVisitor for TypeInference { // If the statements block ends with a terminator (semicolon, etc.), // it returns the unit type, otherwise, it returns the last inferred type. if statements.is_terminated { - inferred_type = TypeContainer::unit(); + inferred_type = Type::unit(); } Ok(VisitAction::SetTypeSkipChildren(inferred_type)) @@ -591,10 +575,7 @@ impl ExpressionVisitor for TypeInference { var_access: &mut VariableAccess, _: &Range, ) -> ExpressionVisitResult { - mark_type( - self.variable_type(var_access.id) - .unwrap_or(TypeContainer::never()), - ) + mark_type(self.variable_type(var_access.id).unwrap_or(Type::never())) } fn visit_property_assignment( @@ -646,8 +627,7 @@ impl ExpressionVisitor for TypeInference { let assigned_type = self.infer_expression(&mut variable_assignment.expression)?; - let annotated_type = - self.variable_type(id).unwrap_or(TypeContainer::never()); + let annotated_type = self.variable_type(id).unwrap_or(Type::never()); match variable_assignment.operator { AssignmentOperator::Assign => { @@ -776,8 +756,15 @@ impl ExpressionVisitor for TypeInference { match binary_operation.operator { BinaryOperator::Arithmetic(op) => { // if base types are the same, use that as result type - if left_type.base_type() == right_type.base_type() { - mark_type(left_type.base_type()) + if let Some(left) = left_type.base_type() + && let Some(right) = right_type.base_type() + && left == right + { + // FIXME is this correct? + mark_type(Type::new( + left.borrow().type_value.type_definition, + None, + )) } else { Err(SpannedTypeError { error: TypeError::MismatchedOperands( @@ -795,7 +782,7 @@ impl ExpressionVisitor for TypeInference { ), span: Some(span.clone()), })?; - mark_type(TypeContainer::never()) + mark_type(Type::never()) } } } @@ -812,29 +799,25 @@ impl ExpressionVisitor for TypeInference { let type_def = var_type .as_ref() .expect("TypeDeclaration type should have been inferred already"); - let reference = match &type_def { - TypeContainer::TypeReference(r) => r, - _ => { - panic!("TypeDeclaration var_type should be a TypeReference") - } - }; + + let reference = type_def + .inner_reference() + .expect("TypeDeclaration var_type should be a TypeReference"); let inferred_type_def = self.infer_type_expression(&mut type_declaration.value)?; if type_declaration.kind.is_nominal() { - match inferred_type_def { - TypeContainer::Type(t) => { - reference.borrow_mut().type_value = t; + match &inferred_type_def.inner_reference() { + None => { + reference.borrow_mut().type_value = inferred_type_def; } - TypeContainer::TypeReference(r) => { - reference.borrow_mut().type_value = - Type::reference(r, None); - } - TypeContainer::TypeAlias(_) => { - unimplemented!( - "TypeDeclaration for TypeAlias is not implemented yet" - ) + Some(r) => { + // FIXME is this necesarry? + reference.borrow_mut().type_value = Type::reference( + r.clone(), + ReferenceMutability::Immutable, + ); } } mark_type(type_def.clone()) @@ -936,7 +919,7 @@ impl ExpressionVisitor for TypeInference { TypeContainer::Type(t) => { if let TypeDefinition::Reference(r) = &t.type_definition { let bor = r.borrow(); - mark_type(bor.type_value.clone().as_type_container()) + mark_type(bor.type_value.clone()) } else { self.record_error(SpannedTypeError { error: TypeError::InvalidDerefType(inner_type), @@ -946,7 +929,7 @@ impl ExpressionVisitor for TypeInference { } TypeContainer::TypeReference(r) => { let bor = r.borrow(); - mark_type(bor.type_value.clone().as_type_container()) + mark_type(bor.type_value.clone()) } TypeContainer::TypeAlias(_) => { unimplemented!("Deref for TypeAlias is not implemented yet") @@ -984,10 +967,7 @@ impl ExpressionVisitor for TypeInference { if let Some(annotated_type) = annotated_return_type { // If they match, use the annotated type if annotated_type.matches_type(&inferred_return_type) { - return mark_type( - Type::function(parameters, annotated_type) - .as_type_container(), - ); + return mark_type(Type::function(parameters, annotated_type)); } // If they don't match, record an error self.record_error(SpannedTypeError { @@ -998,14 +978,9 @@ impl ExpressionVisitor for TypeInference { span: Some(span.clone()), })?; // Use the annotated type despite the mismatch - mark_type( - Type::function(parameters, annotated_type).as_type_container(), - ) + mark_type(Type::function(parameters, annotated_type)) } else { - mark_type( - Type::function(parameters, inferred_return_type) - .as_type_container(), - ) + mark_type(Type::function(parameters, inferred_return_type)) } } @@ -1122,7 +1097,7 @@ impl ExpressionVisitor for TypeInference { TypeContainer::Type(t) => { if let TypeDefinition::Reference(r) = &t.type_definition { let bor = r.borrow(); - bor.type_value.clone().as_type_container() + bor.type_value.clone() } else { return Err(SpannedTypeError { error: TypeError::InvalidDerefType(expression_type), @@ -1132,7 +1107,7 @@ impl ExpressionVisitor for TypeInference { } TypeContainer::TypeReference(r) => { let bor = r.borrow(); - bor.type_value.clone().as_type_container() + bor.type_value.clone() } TypeContainer::TypeAlias(_) => { unimplemented!( @@ -1154,7 +1129,9 @@ impl ExpressionVisitor for TypeInference { // span: Some(span.clone()), // }); // } - if expression_type.reference_mutability() != Some(ReferenceMutability::Mutable) { + if expression_type.reference_mutability() + != Some(ReferenceMutability::Mutable) + { return Err(SpannedTypeError { error: TypeError::AssignmentToImmutableReference( "".to_string(), @@ -1259,7 +1236,6 @@ mod tests { types::{ definition::TypeDefinition, structural_type_definition::StructuralTypeDefinition, - type_container::TypeContainer, }, values::{ core_value::CoreValue, @@ -1351,7 +1327,7 @@ mod tests { /// for "var x = 42; x", it returns the type of "x", as this is the last expression of the statements. /// For "var x = 42;", it returns the never type, as the statement is terminated. /// For "10 + 32", it returns the type of the binary operation. - fn infer_from_script(src: &str) -> TypeContainer { + fn infer_from_script(src: &str) -> Type { let ast = parse(src).unwrap(); let mut scope_stack = PrecompilerScopeStack::default(); let ast_metadata = Rc::new(RefCell::new(AstMetadata::default())); @@ -1365,7 +1341,7 @@ mod tests { /// Infers the type of the given expression. /// Panics if type inference fails. - fn infer_from_expression(expr: &mut DatexExpression) -> TypeContainer { + fn infer_from_expression(expr: &mut DatexExpression) -> Type { let mut scope_stack = PrecompilerScopeStack::default(); let ast_metadata = Rc::new(RefCell::new(AstMetadata::default())); @@ -1463,7 +1439,7 @@ mod tests { let res = infer_from_script(src); assert_eq!( - res.as_type(), + res, Type::function( vec![ ( @@ -1487,7 +1463,7 @@ mod tests { let res = infer_from_script(src); assert_eq!( - res.as_type(), + res, Type::function( vec![ ( @@ -1502,7 +1478,6 @@ mod tests { Type::structural(StructuralTypeDefinition::Integer( Integer::from(42) )) - .as_type_container() ) ); } @@ -1512,24 +1487,21 @@ mod tests { assert_eq!( infer_from_expression( &mut DatexExpressionData::Boolean(true).with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Boolean(Boolean(true))) ); assert_eq!( infer_from_expression( &mut DatexExpressionData::Boolean(false).with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Boolean(Boolean(false))) ); assert_eq!( infer_from_expression( &mut DatexExpressionData::Null.with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Null) ); @@ -1537,8 +1509,7 @@ mod tests { infer_from_expression( &mut DatexExpressionData::Decimal(Decimal::from(1.23)) .with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Decimal(Decimal::from( 1.23 ))) @@ -1548,8 +1519,7 @@ mod tests { infer_from_expression( &mut DatexExpressionData::Integer(Integer::from(42)) .with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Integer(Integer::from( 42 ))) @@ -1565,18 +1535,11 @@ mod tests { .with_default_span() ])) .with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::List(vec![ - TypeContainer::Type(Type::from(CoreValue::from( - Integer::from(1) - ))), - TypeContainer::Type(Type::from(CoreValue::from( - Integer::from(2) - ))), - TypeContainer::Type(Type::from(CoreValue::from( - Integer::from(3) - ))) + Type::from(CoreValue::from(Integer::from(1))), + Type::from(CoreValue::from(Integer::from(2))), + Type::from(CoreValue::from(Integer::from(3))) ])) ); @@ -1589,13 +1552,11 @@ mod tests { .with_default_span() )])) .with_default_span() - ) - .as_type(), + ), Type::structural(StructuralTypeDefinition::Map(vec![( Type::structural(StructuralTypeDefinition::Text( "a".to_string().into() - )) - .as_type_container(), + )), TypeContainer::Type(Type::from(CoreValue::from( Integer::from(1) ))) @@ -1620,7 +1581,7 @@ mod tests { NominalTypeDeclaration::from("A"), None, ); - assert_eq!(var_a.var_type, Some(nominal_ref.as_type_container())); + assert_eq!(var_a.var_type, Some(nominal_ref)); } #[test] @@ -1696,8 +1657,7 @@ mod tests { _ => unreachable!(), }; let bor = var_type_ref.borrow(); - let structural_type_definition = - bor.as_type().structural_type().unwrap(); + let structural_type_definition = bor.structural_type().unwrap(); let fields = match structural_type_definition { StructuralTypeDefinition::Map(fields) => fields, _ => unreachable!(), @@ -1724,7 +1684,6 @@ mod tests { assert_eq!( inferred, Type::structural(StructuralTypeDefinition::Integer(42.into())) - .as_type_container() ); let inferred = infer_from_script("@endpoint"); @@ -1733,7 +1692,6 @@ mod tests { Type::structural(StructuralTypeDefinition::Endpoint( Endpoint::from_str("@endpoint").unwrap() )) - .as_type_container() ); let inferred = infer_from_script("'hello world'"); @@ -1742,22 +1700,16 @@ mod tests { Type::structural(StructuralTypeDefinition::Text( "hello world".into() )) - .as_type_container() ); let inferred = infer_from_script("true"); assert_eq!( inferred, Type::structural(StructuralTypeDefinition::Boolean(true.into())) - .as_type_container() ); let inferred = infer_from_script("null"); - assert_eq!( - inferred, - Type::structural(StructuralTypeDefinition::Null) - .as_type_container() - ); + assert_eq!(inferred, Type::structural(StructuralTypeDefinition::Null)); } #[test] @@ -1766,7 +1718,6 @@ mod tests { assert_eq!( inferred, Type::structural(StructuralTypeDefinition::Integer(30.into())) - .as_type_container() ); let inferred = infer_from_script("10; 20; 30;"); @@ -1779,7 +1730,6 @@ mod tests { assert_eq!( inferred, Type::structural(StructuralTypeDefinition::Integer(42.into())) - .as_type_container() ); } @@ -1789,7 +1739,6 @@ mod tests { assert_eq!( inferred, Type::structural(StructuralTypeDefinition::Integer(42.into())) - .as_type_container() ); let inferred = infer_from_script("var y: integer = 100u8; y"); @@ -1822,7 +1771,7 @@ mod tests { var a = { b: 42 }; a.b = 100 "#; - let inferred_type = infer_from_script(src).as_type(); // should be 100 of b property type + let inferred_type = infer_from_script(src); // should be 100 of b property type assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Integer(Integer::from( @@ -1843,7 +1792,7 @@ mod tests { let var = metadata.variable_metadata(0).unwrap(); let var_type = var.var_type.as_ref().unwrap(); assert_eq!( - var_type.as_type(), + var_type, Type::union(vec![ get_core_lib_type(CoreLibPointerId::Text), get_core_lib_type(CoreLibPointerId::Integer(None)) @@ -1866,7 +1815,7 @@ mod tests { annotated_type, assigned_type } if *annotated_type == get_core_lib_type(CoreLibPointerId::Integer(None)) - && assigned_type.as_type() == Type::structural(StructuralTypeDefinition::Text("hello".to_string().into())) + && assigned_type == Type::structural(StructuralTypeDefinition::Text("hello".to_string().into())) ); } @@ -1881,7 +1830,7 @@ mod tests { #[test] fn infer_typed_literal() { - let inferred_type = infer_from_script("type X = 42u8").as_type(); + let inferred_type = infer_from_script("type X = 42u8"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedInteger( @@ -1889,7 +1838,7 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = 42i32").as_type(); + let inferred_type = infer_from_script("type X = 42i32"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedInteger( @@ -1897,7 +1846,7 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = 42.69f32").as_type(); + let inferred_type = infer_from_script("type X = 42.69f32"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedDecimal( @@ -1908,7 +1857,7 @@ mod tests { #[test] fn infer_type_simple_literal() { - let inferred_type = infer_from_script("type X = 42").as_type(); + let inferred_type = infer_from_script("type X = 42"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Integer(Integer::from( @@ -1916,7 +1865,7 @@ mod tests { ))) ); - let inferred_type = infer_from_script("type X = 3/4").as_type(); + let inferred_type = infer_from_script("type X = 3/4"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Decimal( @@ -1924,19 +1873,19 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = true").as_type(); + let inferred_type = infer_from_script("type X = true"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Boolean(Boolean(true))) ); - let inferred_type = infer_from_script("type X = false").as_type(); + let inferred_type = infer_from_script("type X = false"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Boolean(Boolean(false))) ); - let inferred_type = infer_from_script(r#"type X = "hello""#).as_type(); + let inferred_type = infer_from_script(r#"type X = "hello""#); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Text( @@ -1949,8 +1898,7 @@ mod tests { // TODO #451 resolve intersection and union types properly // by merging the member types if one is base (one level higher) than the other fn infer_intersection_type_expression() { - let inferred_type = - infer_from_script("type X = integer/u8 & 42").as_type(); + let inferred_type = infer_from_script("type X = integer/u8 & 42"); assert_eq!( inferred_type, Type::intersection(vec![ @@ -1960,15 +1908,13 @@ mod tests { Type::structural(StructuralTypeDefinition::Integer( Integer::from(42) )) - .as_type_container() ]) ); } #[test] fn infer_union_type_expression() { - let inferred_type = - infer_from_script("type X = integer/u8 | decimal").as_type(); + let inferred_type = infer_from_script("type X = integer/u8 | decimal"); assert_eq!( inferred_type, Type::union(vec![ @@ -1982,7 +1928,7 @@ mod tests { #[test] fn infer_empty_struct_type_expression() { - let inferred_type = infer_from_script("type X = {}").as_type(); + let inferred_type = infer_from_script("type X = {}"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Map(vec![])) @@ -1992,16 +1938,14 @@ mod tests { #[test] fn infer_struct_type_expression() { let inferred_type = - infer_from_script("type X = { a: integer/u8, b: decimal }") - .as_type(); + infer_from_script("type X = { a: integer/u8, b: decimal }"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Map(vec![ ( Type::structural(StructuralTypeDefinition::Text( "a".to_string().into() - )) - .as_type_container(), + )), get_core_lib_type(CoreLibPointerId::Integer(Some( IntegerTypeVariant::U8 ))) @@ -2009,8 +1953,7 @@ mod tests { ( Type::structural(StructuralTypeDefinition::Text( "b".to_string().into() - )) - .as_type_container(), + )), get_core_lib_type(CoreLibPointerId::Decimal(None)) ) ])) @@ -2042,12 +1985,9 @@ mod tests { let var_metadata = metadata.variable_metadata(0).unwrap(); assert_eq!( var_metadata.var_type, - Some( - Type::structural(StructuralTypeDefinition::Integer( - Integer::from(10) - )) - .as_type_container() - ), + Some(Type::structural(StructuralTypeDefinition::Integer( + Integer::from(10) + ))), ); } diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index b4d7f93e6..5e3d1ed0c 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -106,6 +106,14 @@ impl Type { pub fn is_reference(&self) -> bool { core::matches!(self.type_definition, TypeDefinition::Reference(_)) } + pub fn inner_reference(&self) -> Option>> { + if let TypeDefinition::Reference(reference) = &self.type_definition { + Some(reference.clone()) + } else { + None + } + } + pub fn structural_type(&self) -> Option<&StructuralTypeDefinition> { if let TypeDefinition::Structural(s) = &self.type_definition { Some(s) @@ -123,6 +131,9 @@ impl Type { } impl Type { + /// Creates a new Type with the given TypeDefinition and optional ReferenceMutability + /// FIXME: If the TypeDefinition is a Reference, the ReferenceMutability must be Some, + /// otherwise it must be None. pub fn new( type_definition: TypeDefinition, reference_mutability: Option, @@ -133,6 +144,8 @@ impl Type { reference_mutability, } } + + /// Creates a reference type pointing to the given TypeReference with the specified mutability pub fn reference( type_definition: Rc>, reference_mutability: ReferenceMutability, @@ -143,11 +156,46 @@ impl Type { reference_mutability: Some(reference_mutability), } } + + /// Creates a structural type from the given structural type definition pub fn structural( structural_type: impl Into, ) -> Self { Type { - type_definition: TypeDefinition::Structural(structural_type.into()), + type_definition: TypeDefinition::structural(structural_type), + base_type: None, + reference_mutability: None, + } + } + + /// Creates a union type from the given member types + pub fn union(types: Vec) -> Self + where + T: Into, + { + Type { + type_definition: TypeDefinition::union(types), + base_type: None, + reference_mutability: None, + } + } + + /// Creates an intersection type from the given member types + pub fn intersection>(members: Vec) -> Self { + Type { + type_definition: TypeDefinition::intersection(members), + base_type: None, + reference_mutability: None, + } + } + + /// Creates a function type from the given parameter types and return type + pub fn function( + parameters: Vec<(String, Type)>, + return_type: impl Into, + ) -> Self { + Type { + type_definition: TypeDefinition::function(parameters, return_type), base_type: None, reference_mutability: None, } @@ -204,7 +252,7 @@ impl Type { let other_base_type = other.base_type().expect("other type has no base type"); let other_base_type = other_base_type.borrow(); - let other_base_type = other_base_type.clone().as_type_container(); + let other_base_type = other_base_type.clone().as_type(); match &self.type_definition { TypeDefinition::Union(members) => { From 24d3e3bb8fde12df1ba30c5efcd33accd75d4b17 Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 13:34:11 +0100 Subject: [PATCH 05/10] refactoring on types (WIP) --- src/type_inference/mod.rs | 53 ++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 5273e9ae5..13d53590b 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -762,7 +762,7 @@ impl ExpressionVisitor for TypeInference { { // FIXME is this correct? mark_type(Type::new( - left.borrow().type_value.type_definition, + left.borrow().type_value.type_definition.clone(), None, )) } else { @@ -873,7 +873,7 @@ impl ExpressionVisitor for TypeInference { comparison_operation: &mut ComparisonOperation, span: &Range, ) -> ExpressionVisitResult { - mark_type(TypeContainer::boolean()) + mark_type(Type::boolean()) } fn visit_conditional( &mut self, @@ -893,20 +893,19 @@ impl ExpressionVisitor for TypeInference { span: &Range, ) -> ExpressionVisitResult { let inner_type = self.infer_expression(datex_expression)?; - mark_type(match &inner_type { - TypeContainer::Type(t) => TypeContainer::Type(Type { - type_definition: TypeDefinition::Type(Box::new(t.clone())), + mark_type(match &inner_type.inner_reference() { + None => Type { + type_definition: TypeDefinition::Type(Box::new( + inner_type.clone(), + )), reference_mutability: Some(ReferenceMutability::Mutable), base_type: None, - }), - TypeContainer::TypeReference(r) => TypeContainer::Type(Type { + }, + Some(r) => Type { type_definition: TypeDefinition::Reference(r.clone()), reference_mutability: Some(ReferenceMutability::Mutable), base_type: None, - }), - TypeContainer::TypeAlias(_) => { - unimplemented!("CreateMut for TypeAlias is not implemented yet") - } + }, }) } fn visit_deref( @@ -915,27 +914,19 @@ impl ExpressionVisitor for TypeInference { span: &Range, ) -> ExpressionVisitResult { let inner_type = self.infer_expression(&mut deref.expression)?; - match &inner_type { - TypeContainer::Type(t) => { - if let TypeDefinition::Reference(r) = &t.type_definition { - let bor = r.borrow(); - mark_type(bor.type_value.clone()) - } else { - self.record_error(SpannedTypeError { - error: TypeError::InvalidDerefType(inner_type), - span: Some(span.clone()), - }) - } - } - TypeContainer::TypeReference(r) => { - let bor = r.borrow(); - mark_type(bor.type_value.clone()) - } - TypeContainer::TypeAlias(_) => { - unimplemented!("Deref for TypeAlias is not implemented yet") - } - } + let deref_type = if let Some(reference) = inner_type.inner_reference() { + reference.borrow().type_value.clone() + } else { + self.record_error(SpannedTypeError { + error: TypeError::InvalidDerefType(inner_type), + span: Some(span.clone()), + })?; + Type::never() + }; + + mark_type(deref_type) } + fn visit_function_declaration( &mut self, function_declaration: &mut FunctionDeclaration, From b3637c7613963d961bbcf51dd0384391cd998296 Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 13:46:23 +0100 Subject: [PATCH 06/10] refactoring on types (WIP) --- src/libs/core.rs | 40 ++++++------ src/references/type_reference.rs | 4 +- src/type_inference/mod.rs | 101 ++++++++++++------------------- src/values/core_values/type.rs | 14 +++-- 4 files changed, 74 insertions(+), 85 deletions(-) diff --git a/src/libs/core.rs b/src/libs/core.rs index 552033658..552c6cdfe 100644 --- a/src/libs/core.rs +++ b/src/libs/core.rs @@ -172,7 +172,6 @@ pub fn get_core_lib_type_definition( get_core_lib_type(id).type_definition } - fn has_core_lib_type(id: T) -> bool where T: Into, @@ -193,7 +192,8 @@ pub fn load_core_lib(memory: &mut Memory) { .as_ref() .unwrap() .to_string(); - let reference = Reference::TypeReference(type_reference.clone()); + let reference = + Reference::TypeReference(type_reference.clone()); memory.register_reference(&reference); (name, ValueContainer::Reference(reference)) } @@ -320,7 +320,10 @@ fn create_core_type( pointer_id: CoreLibPointerId, ) -> CoreLibTypeDefinition { let base_type_ref = match base_type { - Some(Type {type_definition: TypeDefinition::Reference(reference), ..}) => Some(reference), + Some(Type { + type_definition: TypeDefinition::Reference(reference), + .. + }) => Some(reference), Some(_) => { core::panic!("Base type must be a Reference") } @@ -328,18 +331,21 @@ fn create_core_type( }; ( pointer_id.clone(), - Type::new(TypeDefinition::reference(Rc::new(RefCell::new(TypeReference { - nominal_type_declaration: Some(NominalTypeDeclaration { - name: name.to_string(), - variant, - }), - type_value: Type { - base_type: base_type_ref, - reference_mutability: None, - type_definition: TypeDefinition::Unit, - }, - pointer_address: Some(PointerAddress::from(pointer_id)), - }))), None), + Type::new( + TypeDefinition::reference(Rc::new(RefCell::new(TypeReference { + nominal_type_declaration: Some(NominalTypeDeclaration { + name: name.to_string(), + variant, + }), + type_value: Type { + base_type: base_type_ref, + reference_mutability: None, + type_definition: TypeDefinition::Unit, + }, + pointer_address: Some(PointerAddress::from(pointer_id)), + }))), + None, + ), ) } @@ -470,7 +476,7 @@ mod tests { fn base_type_simple() { // integer -> integer -> integer ... let integer_type = get_core_lib_type(CoreLibPointerId::Integer(None)); - let integer_base = integer_type.base_type(); + let integer_base = integer_type.base_type_reference(); assert_eq!(integer_base.unwrap().borrow().to_string(), "integer"); } @@ -482,7 +488,7 @@ mod tests { )); assert_eq!(integer_u8_type.to_string(), "integer/u8"); - let integer = integer_u8_type.base_type(); + let integer = integer_u8_type.base_type_reference(); assert_eq!(integer.unwrap().borrow().to_string(), "integer"); } diff --git a/src/references/type_reference.rs b/src/references/type_reference.rs index 55e17bfe1..c63eb8592 100644 --- a/src/references/type_reference.rs +++ b/src/references/type_reference.rs @@ -122,7 +122,7 @@ impl TypeReference { // } pub fn base_type(&self) -> Option>> { - self.type_value.base_type() + self.type_value.base_type_reference() } pub fn matches_reference(&self, other: Rc>) -> bool { @@ -130,7 +130,7 @@ impl TypeReference { } pub fn matches_type(&self, other: &Type) -> bool { - if let Some(base) = other.base_type() { + if let Some(base) = other.base_type_reference() { return *self == *base.borrow(); } diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 13d53590b..63e610c07 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -756,8 +756,8 @@ impl ExpressionVisitor for TypeInference { match binary_operation.operator { BinaryOperator::Arithmetic(op) => { // if base types are the same, use that as result type - if let Some(left) = left_type.base_type() - && let Some(right) = right_type.base_type() + if let Some(left) = left_type.base_type_reference() + && let Some(right) = right_type.base_type_reference() && left == right { // FIXME is this correct? @@ -940,7 +940,7 @@ impl ExpressionVisitor for TypeInference { }; let inferred_return_type = self .infer_expression(&mut function_declaration.body) - .unwrap_or(TypeContainer::never()); + .unwrap_or(Type::never()); let parameters = function_declaration .parameters @@ -948,7 +948,7 @@ impl ExpressionVisitor for TypeInference { .map(|(name, param_type_expr)| { let param_type = self .infer_type_expression(param_type_expr) - .unwrap_or(TypeContainer::never()); + .unwrap_or(Type::never()); (name.clone(), param_type) }) .collect(); @@ -984,10 +984,10 @@ impl ExpressionVisitor for TypeInference { let inner = self.infer_expression(&mut unary_operation.expression)?; mark_type(match op { UnaryOperator::Logical(op) => match op { - LogicalUnaryOperator::Not => TypeContainer::boolean(), + LogicalUnaryOperator::Not => Type::boolean(), }, UnaryOperator::Arithmetic(_) | UnaryOperator::Bitwise(_) => { - inner.base_type() + inner.base_type().unwrap_or(Type::never()) } UnaryOperator::Reference(_) => return Err(SpannedTypeError { error: TypeError::Unimplemented( @@ -1017,12 +1017,11 @@ impl ExpressionVisitor for TypeInference { // if it's a TypeReference and it has the pointer address set, we can // remap the expression to a GetReference - if let TypeContainer::TypeReference(t) = &base_type - && let Some(addr) = &t.borrow().pointer_address + if let Some(reference) = base_type.inner_reference() + && let Some(addr) = &reference.borrow().pointer_address { Ok(addr.clone()) } else { - // otherwise, unimplemented Err(SpannedTypeError { error: TypeError::Unimplemented( "VariantAccess on Type not implemented".into(), @@ -1084,28 +1083,14 @@ impl ExpressionVisitor for TypeInference { let mut expression_type = self.infer_expression(&mut deref_assignment.deref_expression)?; for _ in 0..deref_assignment.deref_count - 1 { - expression_type = match &expression_type { - TypeContainer::Type(t) => { - if let TypeDefinition::Reference(r) = &t.type_definition { - let bor = r.borrow(); - bor.type_value.clone() - } else { - return Err(SpannedTypeError { - error: TypeError::InvalidDerefType(expression_type), - span: Some(span.clone()), - }); - } - } - TypeContainer::TypeReference(r) => { - let bor = r.borrow(); - bor.type_value.clone() - } - TypeContainer::TypeAlias(_) => { - unimplemented!( - "DerefAssignment for TypeAlias is not implemented yet" - ) - } - }; + if let Some(reference) = expression_type.inner_reference() { + expression_type = reference.borrow().type_value.clone(); + } else { + return Err(SpannedTypeError { + error: TypeError::InvalidDerefType(expression_type), + span: Some(span.clone()), + }); + } } let assigned_type = self.infer_expression(&mut deref_assignment.assigned_expression)?; @@ -1217,7 +1202,10 @@ mod tests { libs::core::{ CoreLibPointerId, get_core_lib_type, get_core_lib_type_reference, }, - references::type_reference::{NominalTypeDeclaration, TypeReference}, + references::{ + reference::ReferenceMutability, + type_reference::{NominalTypeDeclaration, TypeReference}, + }, type_inference::{ error::{SpannedTypeError, TypeError}, infer_expression_type_detailed_errors, @@ -1548,9 +1536,7 @@ mod tests { Type::structural(StructuralTypeDefinition::Text( "a".to_string().into() )), - TypeContainer::Type(Type::from(CoreValue::from( - Integer::from(1) - ))) + Type::from(CoreValue::from(Integer::from(1))) )])) ); } @@ -1567,11 +1553,12 @@ mod tests { let nominal_ref = TypeReference::nominal( Type::reference( get_core_lib_type_reference(CoreLibPointerId::Integer(None)), - None, + ReferenceMutability::Immutable, ), NominalTypeDeclaration::from("A"), None, - ); + ) + .as_type(); assert_eq!(var_a.var_type, Some(nominal_ref)); } @@ -1584,9 +1571,9 @@ mod tests { let metadata = metadata.borrow(); let var_a = metadata.variable_metadata(0).unwrap(); let var_type = var_a.var_type.as_ref().unwrap(); - if let TypeContainer::TypeReference(r) = var_type { + if let Some(reference) = &var_type.inner_reference() { assert_eq!( - r, + reference, &get_core_lib_type_reference(CoreLibPointerId::Integer(None)) ); } else { @@ -1624,7 +1611,7 @@ mod tests { let metadata = metadata.borrow(); let var = metadata.variable_metadata(0).unwrap(); let var_type = var.var_type.as_ref().unwrap(); - assert!(matches!(var_type, TypeContainer::TypeReference(_))); + assert!(var_type.is_reference()); } #[test] @@ -1639,25 +1626,18 @@ mod tests { let metadata = metadata.borrow(); let var = metadata.variable_metadata(0).unwrap(); let var_type = var.var_type.as_ref().unwrap(); - assert!(matches!(var_type, TypeContainer::TypeReference(_))); + assert!(var_type.is_reference()); // get next field, as wrapped in union let next = { - let var_type_ref = match var_type { - TypeContainer::TypeReference(r) => r, - _ => unreachable!(), - }; + let var_type_ref = var_type.inner_reference().unwrap(); let bor = var_type_ref.borrow(); let structural_type_definition = bor.structural_type().unwrap(); let fields = match structural_type_definition { StructuralTypeDefinition::Map(fields) => fields, _ => unreachable!(), }; - let inner_union = match &fields[1].1 { - TypeContainer::Type(r) => r.clone(), - _ => unreachable!(), - } - .type_definition; + let inner_union = &fields[1].1.type_definition; match inner_union { TypeDefinition::Union(members) => { assert_eq!(members.len(), 2); @@ -1712,7 +1692,7 @@ mod tests { ); let inferred = infer_from_script("10; 20; 30;"); - assert_eq!(inferred, TypeContainer::unit()); + assert_eq!(inferred, Type::unit()); } #[test] @@ -1733,27 +1713,24 @@ mod tests { ); let inferred = infer_from_script("var y: integer = 100u8; y"); - assert_eq!(inferred, TypeContainer::integer()); + assert_eq!(inferred, Type::integer()); } #[test] fn var_declaration_with_type_annotation() { let inferred = infer_from_script("var x: integer = 42"); - assert_eq!(inferred, TypeContainer::integer()); + assert_eq!(inferred, Type::integer()); let inferred = infer_from_script("var x: integer/u8 = 42"); - assert_eq!( - inferred, - TypeContainer::typed_integer(IntegerTypeVariant::U8) - ); + assert_eq!(inferred, Type::typed_integer(IntegerTypeVariant::U8)); let inferred = infer_from_script("var x: decimal = 42"); - assert_eq!(inferred, TypeContainer::decimal()); + assert_eq!(inferred, Type::decimal()); let inferred = infer_from_script("var x: boolean = true"); - assert_eq!(inferred, TypeContainer::boolean()); + assert_eq!(inferred, Type::boolean()); let inferred = infer_from_script("var x: text = 'hello'"); - assert_eq!(inferred, TypeContainer::text()); + assert_eq!(inferred, Type::text()); } #[test] @@ -1813,10 +1790,10 @@ mod tests { #[test] fn binary_operation() { let inferred = infer_from_script("10 + 32"); - assert_eq!(inferred, TypeContainer::integer()); + assert_eq!(inferred, Type::integer()); let inferred = infer_from_script("10 + 'test'"); - assert_eq!(inferred, TypeContainer::never()); + assert_eq!(inferred, Type::never()); } #[test] diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index 5e3d1ed0c..ea784ec53 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -209,7 +209,7 @@ impl Type { /// 42u8 -> integer /// 42 -> integer /// User/variant -> User - pub fn base_type(&self) -> Option>> { + pub fn base_type_reference(&self) -> Option>> { // has direct base type (e.g. integer/u8 -> integer) if let Some(base_type) = &self.base_type { return Some(base_type.clone()); @@ -233,6 +233,11 @@ impl Type { }) } + pub fn base_type(&self) -> Option { + self.base_type_reference() + .map(|r| Type::reference(r, ReferenceMutability::Immutable)) + } + /// 1 matches 1 -> true /// 1 matches 2 -> false /// 1 matches 1 | 2 -> true @@ -249,8 +254,9 @@ impl Type { // TODO #324 // println!("Matching types: {} and {}", self, other); - let other_base_type = - other.base_type().expect("other type has no base type"); + let other_base_type = other + .base_type_reference() + .expect("other type has no base type"); let other_base_type = other_base_type.borrow(); let other_base_type = other_base_type.clone().as_type(); @@ -277,7 +283,7 @@ impl Type { _ => {} } - if self.base_type() == other.base_type() { + if self.base_type_reference() == other.base_type_reference() { return true; } false From 46085f46f97186aeac21ae16554c3b67b4b540cb Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 13:51:14 +0100 Subject: [PATCH 07/10] refactoring on types (WIP) --- src/references/type_reference.rs | 7 +++++++ src/type_inference/mod.rs | 7 ++++--- src/types/collection_type_definition.rs | 11 ++++------- src/types/mod.rs | 2 +- src/types/type_alias.rs | 6 +++--- src/values/core_values/type.rs | 4 +++- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/references/type_reference.rs b/src/references/type_reference.rs index c63eb8592..4db7b1527 100644 --- a/src/references/type_reference.rs +++ b/src/references/type_reference.rs @@ -13,6 +13,7 @@ use crate::stdlib::{ string::String, }; use crate::traits::apply::Apply; +use crate::types::structural_type_definition::StructuralTypeDefinition; use crate::values::pointer::PointerAddress; use crate::values::value_container::ValueContainer; use crate::{ @@ -121,6 +122,12 @@ impl TypeReference { // &self.type_value // } + pub fn structural_type_definition( + &self, + ) -> Option<&StructuralTypeDefinition> { + self.type_value.structural_type_definition() + } + pub fn base_type(&self) -> Option>> { self.type_value.base_type_reference() } diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 63e610c07..510bcabaf 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -1632,7 +1632,8 @@ mod tests { let next = { let var_type_ref = var_type.inner_reference().unwrap(); let bor = var_type_ref.borrow(); - let structural_type_definition = bor.structural_type().unwrap(); + let structural_type_definition = + bor.structural_type_definition().unwrap(); let fields = match structural_type_definition { StructuralTypeDefinition::Map(fields) => fields, _ => unreachable!(), @@ -1761,7 +1762,7 @@ mod tests { let var_type = var.var_type.as_ref().unwrap(); assert_eq!( var_type, - Type::union(vec![ + &Type::union(vec![ get_core_lib_type(CoreLibPointerId::Text), get_core_lib_type(CoreLibPointerId::Integer(None)) ]) @@ -1783,7 +1784,7 @@ mod tests { annotated_type, assigned_type } if *annotated_type == get_core_lib_type(CoreLibPointerId::Integer(None)) - && assigned_type == Type::structural(StructuralTypeDefinition::Text("hello".to_string().into())) + && assigned_type == &Type::structural(StructuralTypeDefinition::Text("hello".to_string().into())) ); } diff --git a/src/types/collection_type_definition.rs b/src/types/collection_type_definition.rs index a552f93ff..cbf448e62 100644 --- a/src/types/collection_type_definition.rs +++ b/src/types/collection_type_definition.rs @@ -1,5 +1,5 @@ use crate::stdlib::boxed::Box; -use crate::types::type_container::TypeContainer; +use crate::values::core_values::r#type::Type; use core::fmt::Display; use core::prelude::rust_2024::*; @@ -7,16 +7,13 @@ use core::prelude::rust_2024::*; #[derive(Debug, Clone, PartialEq, Hash, Eq)] pub enum CollectionTypeDefinition { // e.g. [integer] - List(Box), + List(Box), // e.g. [integer; 5] - ListSlice(Box, usize), + ListSlice(Box, usize), // e.g. {string: integer} - Map { - key: Box, - value: Box, - }, + Map { key: Box, value: Box }, } impl Display for CollectionTypeDefinition { diff --git a/src/types/mod.rs b/src/types/mod.rs index 3ca1db197..c83037f29 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -3,4 +3,4 @@ pub mod definition; pub mod error; pub mod structural_type_definition; pub mod type_alias; -pub mod type_container; +// pub mod type_container; diff --git a/src/types/type_alias.rs b/src/types/type_alias.rs index a2823432b..428be3672 100644 --- a/src/types/type_alias.rs +++ b/src/types/type_alias.rs @@ -2,17 +2,17 @@ use core::fmt::Display; use crate::{ references::type_reference::NominalTypeDeclaration, - types::type_container::TypeContainer, + values::core_values::r#type::Type, }; #[derive(Debug, Clone, PartialEq, Eq)] pub struct TypeAlias { pub nominal_type_declaration: NominalTypeDeclaration, - pub type_container: TypeContainer, + pub type_container: Type, } impl TypeAlias { - pub fn new, U: Into>( + pub fn new, U: Into>( nominal_type_declaration: T, type_container: U, ) -> Self { diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index ea784ec53..f905df28c 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -114,7 +114,9 @@ impl Type { } } - pub fn structural_type(&self) -> Option<&StructuralTypeDefinition> { + pub fn structural_type_definition( + &self, + ) -> Option<&StructuralTypeDefinition> { if let TypeDefinition::Structural(s) = &self.type_definition { Some(s) } else { From 27256d14bc33ebb73cff146095188f8e4fb313f8 Mon Sep 17 00:00:00 2001 From: Jonas Strehle Date: Sat, 29 Nov 2025 14:01:46 +0100 Subject: [PATCH 08/10] refactoring on types (WIP) [17 test failing] --- src/dif/reference.rs | 4 +-- src/dif/representation.rs | 66 ++++++++++++++++++--------------------- src/dif/type.rs | 65 ++++++++++++++++++-------------------- src/dif/value.rs | 45 ++++++++++++++------------ src/libs/core.rs | 2 +- src/values/core_value.rs | 2 -- src/values/value.rs | 5 +-- 7 files changed, 90 insertions(+), 99 deletions(-) diff --git a/src/dif/reference.rs b/src/dif/reference.rs index ef0e73d45..4139b02de 100644 --- a/src/dif/reference.rs +++ b/src/dif/reference.rs @@ -4,9 +4,9 @@ use crate::references::reference::{Reference, ReferenceMutability}; use crate::runtime::memory::Memory; use core::cell::RefCell; use core::prelude::rust_2024::*; +use datex_core::dif::r#type::DIFTypeDefinition; use datex_core::dif::value::DIFValueContainer; use serde::{Deserialize, Serialize}; -use datex_core::dif::r#type::DIFTypeDefinition; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DIFReference { @@ -26,7 +26,7 @@ impl DIFReference { &reference.value_container(), memory, ); - let allowed_type = DIFTypeDefinition::from_type_container( + let allowed_type = DIFTypeDefinition::from_type_definition( &reference.allowed_type(), memory, ); diff --git a/src/dif/representation.rs b/src/dif/representation.rs index 4c1ad4cd7..705d0a929 100644 --- a/src/dif/representation.rs +++ b/src/dif/representation.rs @@ -1,6 +1,8 @@ use crate::dif::r#type::{DIFType, DIFTypeContainer, DIFTypeDefinition}; use crate::dif::value::{DIFReferenceNotFoundError, DIFValueContainer}; -use crate::libs::core::{CoreLibPointerId, get_core_lib_type, get_core_lib_type_definition}; +use crate::libs::core::{ + CoreLibPointerId, get_core_lib_type, get_core_lib_type_definition, +}; use crate::runtime::memory::Memory; use crate::std_random::RandomState; use crate::stdlib::boxed::Box; @@ -13,6 +15,7 @@ use crate::values::core_value::CoreValue; use crate::values::core_values::decimal::typed_decimal::{ DecimalTypeVariant, TypedDecimal, }; +use crate::values::core_values::map::Map; use crate::values::value::Value; use crate::values::value_container::ValueContainer; use core::cell::RefCell; @@ -25,7 +28,6 @@ use ordered_float::OrderedFloat; use serde::de::{MapAccess, SeqAccess, Visitor}; use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; -use crate::values::core_values::map::Map; #[derive(Clone, Debug, PartialEq)] pub enum DIFValueRepresentation { @@ -147,8 +149,8 @@ impl DIFValueRepresentation { type_definition: &DIFTypeDefinition, memory: &RefCell, ) -> Result { - Ok(match type_definition { - DIFTypeContainer::Reference(r) => { + Ok(match &type_definition { + DIFTypeDefinition::Reference(r) => { if let Ok(core_lib_ptr_id) = CoreLibPointerId::try_from(r) { match core_lib_ptr_id { // special mappings: @@ -172,15 +174,17 @@ impl DIFValueRepresentation { } // type map and represented as object -> convert to map CoreLibPointerId::Map - if let DIFValueRepresentation::Array(array) = - self => - { - // assert that array is empty, otherwise this is not a valid DIF representation - if !array.is_empty() { - unreachable!("Invalid DIF value, non-empty array with map type") - } - Value::from(CoreValue::Map(Map::Fixed(vec![]))) + if let DIFValueRepresentation::Array(array) = + self => + { + // assert that array is empty, otherwise this is not a valid DIF representation + if !array.is_empty() { + unreachable!( + "Invalid DIF value, non-empty array with map type" + ) } + Value::from(CoreValue::Map(Map::Fixed(vec![]))) + } // otherwise, use default mapping _ => self.to_default_value(memory)?, } @@ -188,14 +192,17 @@ impl DIFValueRepresentation { core::todo!("#389 Handle non-core library type references") } } - DIFTypeContainer::Type(dif_type) => { + DIFTypeDefinition::Type(dif_type) => { let val = self.to_default_value(memory)?; - let ty = dif_type.to_type(memory); + let ty = dif_type.to_type_definition(memory); Value { actual_type: Box::new(ty), ..val } } + e => { + core::todo!("Handle type definitions: {:?}", e) + } }) } } @@ -238,11 +245,7 @@ impl DIFTypeRepresentation { } StructuralTypeDefinition::List(arr) => { DIFTypeRepresentation::Array( - arr.iter() - .map(|v| { - DIFType::from_type(v, memory) - }) - .collect(), + arr.iter().map(|v| DIFType::from_type(v, memory)).collect(), ) } StructuralTypeDefinition::Map(fields) => { @@ -251,12 +254,8 @@ impl DIFTypeRepresentation { .iter() .map(|(k, v)| { ( - DIFType::from_type( - k, memory, - ), - DIFType::from_type( - v, memory, - ), + DIFType::from_type(k, memory), + DIFType::from_type(v, memory), ) }) .collect(), @@ -479,26 +478,21 @@ impl<'de> Deserialize<'de> for DIFTypeRepresentation { where A: SeqAccess<'de>, { - let first_entry = seq - .next_element::>( - )?; + let first_entry = + seq.next_element::>()?; match first_entry { Some(DeserializeMapOrArray::ArrayEntry(first)) => { let mut elements = vec![first]; - while let Some(elem) = - seq.next_element::()? - { + while let Some(elem) = seq.next_element::()? { elements.push(elem); } Ok(DIFTypeRepresentation::Array(elements)) } Some(DeserializeMapOrArray::MapEntry(k, v)) => { let mut elements = vec![(k, v)]; - while let Some((k, v)) = seq.next_element::<( - DIFType, - DIFType, - )>( - )? { + while let Some((k, v)) = + seq.next_element::<(DIFType, DIFType)>()? + { elements.push((k, v)); } Ok(DIFTypeRepresentation::Map(elements)) diff --git a/src/dif/type.rs b/src/dif/type.rs index 9aba023e0..fb7fbbe85 100644 --- a/src/dif/type.rs +++ b/src/dif/type.rs @@ -1,5 +1,5 @@ use crate::dif::DIFConvertible; -use crate::dif::representation::{DIFTypeRepresentation}; +use crate::dif::representation::DIFTypeRepresentation; use crate::references::reference::Reference; use crate::references::reference::ReferenceMutability; use crate::references::reference::mutability_option_as_int; @@ -74,7 +74,7 @@ impl DIFStructuralTypeDefinition { } impl DIFTypeDefinition { - fn from_type_definition( + pub fn from_type_definition( type_def: &TypeDefinition, memory: &RefCell, ) -> Self { @@ -101,9 +101,7 @@ impl DIFTypeDefinition { DIFTypeDefinition::Intersection( types .iter() - .map(|t| { - DIFType::from_type(t, memory) - }) + .map(|t| DIFType::from_type(t, memory)) .collect(), ) } @@ -129,40 +127,23 @@ impl DIFTypeDefinition { parameters: parameters .iter() .map(|(name, ty)| { - ( - name.clone(), - DIFType::from_type(ty, memory), - ) + (name.clone(), DIFType::from_type(ty, memory)) }) .collect(), - return_type: Box::new(DIFType::from_type( - return_type, - memory, - )), + return_type: Box::new(DIFType::from_type(return_type, memory)), }, } } - fn to_type_definition( - &self, - memory: &RefCell, - ) -> TypeDefinition { + fn to_type_definition(&self, memory: &RefCell) -> TypeDefinition { match self { DIFTypeDefinition::Intersection(types) => { TypeDefinition::Intersection( - types - .iter() - .map(|t| { - t.to_type(memory) - }) - .collect(), + types.iter().map(|t| t.to_type(memory)).collect(), ) } DIFTypeDefinition::Union(types) => TypeDefinition::Union( - types - .iter() - .map(|t| t.to_type(memory)) - .collect(), + types.iter().map(|t| t.to_type(memory)).collect(), ), DIFTypeDefinition::Reference(type_ref_addr) => { let type_ref = memory @@ -174,7 +155,7 @@ impl DIFTypeDefinition { } DIFTypeDefinition::Type(dif_type) => { TypeDefinition::Type(Box::new(dif_type.to_type(memory))) - }, + } DIFTypeDefinition::MarkedType(ty, markers) => { TypeDefinition::MarkedType( Box::new(ty.to_type(memory)), @@ -233,17 +214,33 @@ impl DIFType { } } + pub(crate) fn from_type_definition( + type_def: &TypeDefinition, + memory: &RefCell, + ) -> Self { + DIFType { + name: None, + mutability: None, + type_definition: DIFTypeDefinition::from_type_definition( + type_def, memory, + ), + } + } + pub(crate) fn to_type(&self, memory: &RefCell) -> Type { Type { reference_mutability: self.mutability.clone(), - type_definition: DIFTypeDefinition::to_type_definition( - &self.type_definition, - memory, - ), + type_definition: self.to_type_definition(memory), base_type: None, } } + pub(crate) fn to_type_definition( + &self, + memory: &RefCell, + ) -> TypeDefinition { + DIFTypeDefinition::to_type_definition(&self.type_definition, memory) + } } impl From for DIFType { @@ -284,11 +281,11 @@ mod tests { value: DIFTypeRepresentation::Object(vec![ ( "field1".to_string(), - DIFType::from(DIFTypeRepresentation::Null) + DIFType::from(DIFTypeRepresentation::Null), ), ( "field2".to_string(), - DIFType::from(DIFTypeRepresentation::Number(42.0)) + DIFType::from(DIFTypeRepresentation::Number(42.0)), ), ]), ty: None, diff --git a/src/dif/value.rs b/src/dif/value.rs index 48cfbd74c..1beeef0eb 100644 --- a/src/dif/value.rs +++ b/src/dif/value.rs @@ -1,9 +1,11 @@ use crate::dif::DIFConvertible; +use crate::dif::r#type::DIFTypeDefinition; use crate::dif::{ representation::DIFValueRepresentation, r#type::DIFTypeContainer, }; use crate::libs::core::CoreLibPointerId; use crate::stdlib::string::ToString; +use crate::types::definition::TypeDefinition; use crate::values::core_values::decimal::typed_decimal::{ DecimalTypeVariant, TypedDecimal, }; @@ -18,8 +20,6 @@ use core::result::Result; use datex_core::runtime::memory::Memory; use datex_core::values::core_value::CoreValue; use serde::{Deserialize, Serialize}; -use crate::dif::r#type::DIFTypeDefinition; -use crate::types::definition::TypeDefinition; #[derive(Debug)] pub struct DIFReferenceNotFoundError; @@ -226,25 +226,33 @@ impl DIFValue { DIFValueRepresentation::String( text_key.to_string(), ) - .into(), + .into(), + ) + } + _ => { + DIFValueContainer::from_value_container( + &ValueContainer::from(k), + memory, ) } - _ => DIFValueContainer::from_value_container( - &ValueContainer::from(k), - memory, - ), }, - DIFValueContainer::from_value_container(v, memory), + DIFValueContainer::from_value_container( + v, memory, + ), ) }) .collect(), ) - }, + } }; DIFValue { value: dif_core_value, - ty: get_type_if_non_default(&value.actual_type, memory, is_empty_map), + ty: get_type_if_non_default( + &value.actual_type, + memory, + is_empty_map, + ), } } } @@ -263,14 +271,13 @@ fn get_type_if_non_default( is_empty_map: bool, ) -> Option { match type_definition { - TypeContainer::TypeReference(inner) => { + TypeDefinition::Reference(inner) => { if let Some(Ok(address)) = inner .borrow() .pointer_address .as_ref() .map(CoreLibPointerId::try_from) - && ( - core::matches!( + && (core::matches!( address, CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64)) | CoreLibPointerId::Boolean @@ -279,18 +286,17 @@ fn get_type_if_non_default( | CoreLibPointerId::Null ) || // map is default only if not empty - (core::matches!(address, CoreLibPointerId::Map) && !is_empty_map) - ) + (core::matches!(address, CoreLibPointerId::Map) && !is_empty_map)) { None } else { - Some(DIFTypeContainer::from_type_container( + Some(DIFTypeDefinition::from_type_definition( type_definition, memory, )) } } - _ => Some(DIFTypeContainer::from_type_container( + _ => Some(DIFTypeDefinition::from_type_definition( type_definition, memory, )), @@ -300,18 +306,17 @@ fn get_type_if_non_default( #[cfg(test)] mod tests { use crate::dif::DIFConvertible; + use crate::dif::r#type::DIFTypeDefinition; use crate::runtime::memory::Memory; use crate::values::core_values::endpoint::Endpoint; use crate::values::core_values::map::Map; use crate::values::value_container::ValueContainer; use crate::{ - dif::{r#type::DIFTypeContainer, value::DIFValue}, - libs::core::CoreLibPointerId, + dif::value::DIFValue, libs::core::CoreLibPointerId, values::core_values::integer::typed_integer::IntegerTypeVariant, }; use core::cell::RefCell; use datex_core::values::value::Value; - use crate::dif::r#type::DIFTypeDefinition; fn get_mock_memory() -> RefCell { RefCell::new(Memory::new(Endpoint::default())) diff --git a/src/libs/core.rs b/src/libs/core.rs index 552c6cdfe..9111ffa61 100644 --- a/src/libs/core.rs +++ b/src/libs/core.rs @@ -184,7 +184,7 @@ pub fn load_core_lib(memory: &mut Memory) { with_core_lib(|core_lib_types| { let structure = core_lib_types .values() - .map(|ty| match ty.type_definition { + .map(|ty| match &ty.type_definition { TypeDefinition::Reference(type_reference) => { let name = type_reference .borrow() diff --git a/src/values/core_value.rs b/src/values/core_value.rs index 5b65ec453..527adea48 100644 --- a/src/values/core_value.rs +++ b/src/values/core_value.rs @@ -26,8 +26,6 @@ use crate::values::value_container::{ValueContainer, ValueError}; use core::fmt::{Display, Formatter}; use core::ops::{Add, AddAssign, Neg, Not, Sub}; use datex_core::types::definition::TypeDefinition; -use std::cell::RefCell; -use std::rc::Rc; #[derive(Clone, Debug, PartialEq, Eq, Hash, FromCoreValue)] pub enum CoreValue { diff --git a/src/values/value.rs b/src/values/value.rs index 1d5e63ee5..4ab399799 100644 --- a/src/values/value.rs +++ b/src/values/value.rs @@ -200,8 +200,6 @@ where /// The value is a holder for a combination of a CoreValue representation and its actual type. mod tests { use super::*; - use crate::types::structural_type_definition::StructuralTypeDefinition; - use crate::values::core_values::r#type::Type; use crate::{ assert_structural_eq, datex_list, logger::init_logger_debug, @@ -215,8 +213,7 @@ mod tests { use datex_core::libs::core::{ get_core_lib_type, get_core_lib_type_reference, }; - use log::{debug, info}; - use std::rc::Rc; + use log::info; #[test] fn endpoint() { From ea08dbc98b7c9f7a683c1bfd1e67911d3f8e3069 Mon Sep 17 00:00:00 2001 From: Benedikt Strehle Date: Thu, 4 Dec 2025 23:19:30 +0100 Subject: [PATCH 09/10] fix type matching tests --- src/type_inference/mod.rs | 96 ++++++++++++++++---------- src/values/core_values/type.rs | 121 +++++++++++++++++++++++++-------- 2 files changed, 154 insertions(+), 63 deletions(-) diff --git a/src/type_inference/mod.rs b/src/type_inference/mod.rs index 510bcabaf..e5f43da87 100644 --- a/src/type_inference/mod.rs +++ b/src/type_inference/mod.rs @@ -25,7 +25,7 @@ use crate::{ }; use core::{cell::RefCell, ops::Range, panic, str::FromStr}; - +use log::info; use crate::{ ast::structs::{ expression::{ @@ -631,7 +631,7 @@ impl ExpressionVisitor for TypeInference { match variable_assignment.operator { AssignmentOperator::Assign => { - if !annotated_type.matches_type(&assigned_type) { + if !assigned_type.matches_type(&annotated_type) { return Err(SpannedTypeError { error: TypeError::AssignmentTypeMismatch { annotated_type, @@ -725,7 +725,7 @@ impl ExpressionVisitor for TypeInference { if let Some(specific) = &mut variable_declaration.type_annotation { // FIXME check if matches let annotated_type = self.infer_type_expression(specific)?; - if !annotated_type.matches_type(&init_type) { + if !init_type.matches_type(&annotated_type) { self.record_error(SpannedTypeError::new_with_span( TypeError::AssignmentTypeMismatch { annotated_type: annotated_type.clone(), @@ -753,6 +753,8 @@ impl ExpressionVisitor for TypeInference { let left_type = self.infer_expression(&mut binary_operation.left)?; let right_type = self.infer_expression(&mut binary_operation.right)?; + println!("base types: left: {:?}, right: {:?}", left_type.base_type_reference(), right_type.base_type_reference()); + match binary_operation.operator { BinaryOperator::Arithmetic(op) => { // if base types are the same, use that as result type @@ -760,11 +762,7 @@ impl ExpressionVisitor for TypeInference { && let Some(right) = right_type.base_type_reference() && left == right { - // FIXME is this correct? - mark_type(Type::new( - left.borrow().type_value.type_definition.clone(), - None, - )) + mark_type(Type::new(TypeDefinition::Reference(left), None)) } else { Err(SpannedTypeError { error: TypeError::MismatchedOperands( @@ -814,9 +812,9 @@ impl ExpressionVisitor for TypeInference { } Some(r) => { // FIXME is this necesarry? - reference.borrow_mut().type_value = Type::reference( - r.clone(), - ReferenceMutability::Immutable, + reference.borrow_mut().type_value = Type::new( + TypeDefinition::Reference(r.clone()), + None ); } } @@ -953,11 +951,11 @@ impl ExpressionVisitor for TypeInference { }) .collect(); - // Check if annotated return type matches inferred return type + // Check if inferred return type matches the annotated return type // if an annotated return type is provided if let Some(annotated_type) = annotated_return_type { // If they match, use the annotated type - if annotated_type.matches_type(&inferred_return_type) { + if inferred_return_type.matches_type(&annotated_type) { return mark_type(Type::function(parameters, annotated_type)); } // If they don't match, record an error @@ -1276,9 +1274,13 @@ mod tests { let mut res = precompile_ast_simple_error(ast, &mut scope_stack, ast_metadata) .expect("Precompilation failed"); - infer_expression_type_simple_error(&mut res) - .expect("Type inference failed"); - res + let inferred_res = infer_expression_type_simple_error(&mut res); + if let Err(err) = infer_expression_type_simple_error(&mut res) { + panic!("Type inference failed: {:#?}", err); + } + else { + res + } } /// Infers the AST of the given expression. @@ -1318,6 +1320,21 @@ mod tests { .into() } + /// Infers the type definition of the given source code. + /// Panics if parsing, precompilation or type inference fails. + /// Returns the TypeDefinition if the inferred type is a TypeReference. + fn infer_from_script_get_reference_type( + src: &str, + ) -> Type { + let inferred_type = infer_from_script(src); + inferred_type + .inner_reference() + .expect("Expected type to be a TypeReference") + .borrow() + .type_value + .clone() + } + /// Infers the type of the given expression. /// Panics if type inference fails. fn infer_from_expression(expr: &mut DatexExpression) -> Type { @@ -1550,16 +1567,23 @@ mod tests { let metadata = metadata.borrow(); let var_a = metadata.variable_metadata(0).unwrap(); - let nominal_ref = TypeReference::nominal( - Type::reference( - get_core_lib_type_reference(CoreLibPointerId::Integer(None)), - ReferenceMutability::Immutable, + let nominal_type_def = Type::new( + TypeDefinition::Reference( + Rc::new(RefCell::new( + TypeReference::nominal( + get_core_lib_type(CoreLibPointerId::Integer(None)), + NominalTypeDeclaration::from("A".to_string()), + None, + ) + )) ), - NominalTypeDeclaration::from("A"), None, - ) - .as_type(); - assert_eq!(var_a.var_type, Some(nominal_ref)); + ); + + assert_eq!( + var_a.var_type, + Some(nominal_type_def) + ); } #[test] @@ -1799,7 +1823,7 @@ mod tests { #[test] fn infer_typed_literal() { - let inferred_type = infer_from_script("type X = 42u8"); + let inferred_type = infer_from_script_get_reference_type("type X = 42u8"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedInteger( @@ -1807,7 +1831,7 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = 42i32"); + let inferred_type = infer_from_script_get_reference_type("type X = 42i32"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedInteger( @@ -1815,7 +1839,7 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = 42.69f32"); + let inferred_type = infer_from_script_get_reference_type("type X = 42.69f32"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::TypedDecimal( @@ -1826,7 +1850,7 @@ mod tests { #[test] fn infer_type_simple_literal() { - let inferred_type = infer_from_script("type X = 42"); + let inferred_type = infer_from_script_get_reference_type("type X = 42"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Integer(Integer::from( @@ -1834,7 +1858,7 @@ mod tests { ))) ); - let inferred_type = infer_from_script("type X = 3/4"); + let inferred_type = infer_from_script_get_reference_type("type X = 3/4"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Decimal( @@ -1842,19 +1866,19 @@ mod tests { )) ); - let inferred_type = infer_from_script("type X = true"); + let inferred_type = infer_from_script_get_reference_type("type X = true"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Boolean(Boolean(true))) ); - let inferred_type = infer_from_script("type X = false"); + let inferred_type = infer_from_script_get_reference_type("type X = false"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Boolean(Boolean(false))) ); - let inferred_type = infer_from_script(r#"type X = "hello""#); + let inferred_type = infer_from_script_get_reference_type(r#"type X = "hello""#); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Text( @@ -1867,7 +1891,7 @@ mod tests { // TODO #451 resolve intersection and union types properly // by merging the member types if one is base (one level higher) than the other fn infer_intersection_type_expression() { - let inferred_type = infer_from_script("type X = integer/u8 & 42"); + let inferred_type = infer_from_script_get_reference_type("type X = integer/u8 & 42"); assert_eq!( inferred_type, Type::intersection(vec![ @@ -1883,7 +1907,7 @@ mod tests { #[test] fn infer_union_type_expression() { - let inferred_type = infer_from_script("type X = integer/u8 | decimal"); + let inferred_type = infer_from_script_get_reference_type("type X = integer/u8 | decimal"); assert_eq!( inferred_type, Type::union(vec![ @@ -1897,7 +1921,7 @@ mod tests { #[test] fn infer_empty_struct_type_expression() { - let inferred_type = infer_from_script("type X = {}"); + let inferred_type = infer_from_script_get_reference_type("type X = {}"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Map(vec![])) @@ -1907,7 +1931,7 @@ mod tests { #[test] fn infer_struct_type_expression() { let inferred_type = - infer_from_script("type X = { a: integer/u8, b: decimal }"); + infer_from_script_get_reference_type("type X = { a: integer/u8, b: decimal }"); assert_eq!( inferred_type, Type::structural(StructuralTypeDefinition::Map(vec![ diff --git a/src/values/core_values/type.rs b/src/values/core_values/type.rs index f905df28c..5195c5a2a 100644 --- a/src/values/core_values/type.rs +++ b/src/values/core_values/type.rs @@ -228,8 +228,28 @@ impl Type { core::todo!("#322 handle union base type"); // generic type base type / type } TypeDefinition::Reference(reference) => { - core::todo!("#323 handle reference base type"); - // return reference.collapse_to_value().borrow() + let type_ref = reference.borrow(); + if let Some(pointer_address) = &type_ref.pointer_address { + if let Ok(core_lib_id) = CoreLibPointerId::try_from(pointer_address) { + match core_lib_id { + // for integer and decimal variants, return the base type + CoreLibPointerId::Integer(Some(_)) => { + get_core_lib_type_reference(CoreLibPointerId::Integer(None)) + } + CoreLibPointerId::Decimal(Some(_)) => { + get_core_lib_type_reference(CoreLibPointerId::Decimal(None)) + } + // otherwise, reference is already base type + _ => reference.clone() + } + } + else { + todo!("handle non-core lib type base type"); + + } + } else { + todo!("handle pointer address none"); + } } _ => core::panic!("Unhandled type definition for base type"), }) @@ -252,25 +272,17 @@ impl Type { /// 1 matches integer -> true /// integer matches 1 -> false /// integer matches integer -> true + /// 1 matches integer | text -> true pub fn matches_type(&self, other: &Type) -> bool { - // TODO #324 - // println!("Matching types: {} and {}", self, other); - - let other_base_type = other - .base_type_reference() - .expect("other type has no base type"); - let other_base_type = other_base_type.borrow(); - let other_base_type = other_base_type.clone().as_type(); - match &self.type_definition { TypeDefinition::Union(members) => { // If self is a union, check if any member matches the other type for member in members { - if member == &other_base_type { + if member.matches_type(other) { return true; } } - return false; + false } TypeDefinition::Intersection(members) => { // If self is an intersection, all members must match the other type @@ -279,23 +291,59 @@ impl Type { return false; } } - return true; + true + } + _ => { + // atomic type match + Type::atomic_matches_type(self, other) } - // TODO #325 - _ => {} - } - - if self.base_type_reference() == other.base_type_reference() { - return true; } - false } - - /// Matches if the current type matches the other type reference - /// 42 matches integer/u8 -> true - pub fn matches_reference(&self, other: Rc>) -> bool { - self.matches_type(&other.borrow().type_value) - // core::todo!("#326 implement type reference matching"); + + /// Checks if an atomic type matches another type + /// An atomic type can be any type variant besides union or intersection + pub fn atomic_matches_type( + atomic_type: &Type, + other: &Type, + ) -> bool { + // first check if mutability matches + if atomic_type.reference_mutability != other.reference_mutability { + return false; + } + + match &other.type_definition { + TypeDefinition::Reference(reference) => { + // compare base type of atomic_type with the referenced type + if let Some(atomic_base_type_reference) = atomic_type.base_type_reference() { + *atomic_base_type_reference.borrow() == *reference.borrow() + } + else { + false + } + } + TypeDefinition::Union(members) => { + // atomic type must match at least one member of the union + for member in members { + if Type::atomic_matches_type(atomic_type, member) { + return true; + } + } + false + } + TypeDefinition::Intersection(members) => { + // atomic type must match all members of the intersection + for member in members { + if !Type::atomic_matches_type(atomic_type, member) { + return false; + } + } + true + } + _ => { + // compare type definitions directly + atomic_type.type_definition == other.type_definition + } + } } /// Matches a value against a type @@ -469,6 +517,7 @@ impl TryFrom<&DatexExpressionData> for Type { #[cfg(test)] mod tests { + use crate::libs::core::{get_core_lib_type, CoreLibPointerId}; use crate::values::{ core_values::{ integer::{Integer, typed_integer::TypedInteger}, @@ -517,6 +566,24 @@ mod tests { )) } + #[test] + fn type_matches_union_type() { + // 1 matches (1 | 2 | 3) + assert!(Type::structural(Integer::from(1)) + .matches_type(&Type::union(vec![ + Type::structural(Integer::from(1)), + Type::structural(Integer::from(2)), + Type::structural(Integer::from(3)), + ]))); + + // 1 matches integer | text + assert!(Type::structural(Integer::from(1)) + .matches_type(&Type::union(vec![ + get_core_lib_type(CoreLibPointerId::Integer(None)), + get_core_lib_type(CoreLibPointerId::Text), + ]))); + } + // TODO #330 // #[test] // fn test_match_combined_type() { From 0f2bc13ad34eece592277c723ddd28ac98890f91 Mon Sep 17 00:00:00 2001 From: Benedikt Strehle Date: Thu, 4 Dec 2025 23:21:04 +0100 Subject: [PATCH 10/10] remove debug log, all tests passed --- src/runtime/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/execution.rs b/src/runtime/execution.rs index b9b993724..e63d916d9 100644 --- a/src/runtime/execution.rs +++ b/src/runtime/execution.rs @@ -1140,7 +1140,7 @@ fn handle_value( // cast to active type if let Some(active_value) = &scope_container.active_value { - info!("casting, {:#?} to {:#?}", value_container, active_value); + // info!("casting, {:#?} to {:#?}", value_container, active_value); } let result_value = match &mut scope_container.scope {