From cd31d7e7cdf82c65842db13d2c10540547ceb5d4 Mon Sep 17 00:00:00 2001 From: sofia Date: Wed, 16 Jul 2025 20:27:01 +0300 Subject: [PATCH] Nearly fix struct mutability --- reid-llvm-lib/src/builder.rs | 10 ++- reid-llvm-lib/src/lib.rs | 2 + reid/src/codegen.rs | 144 +++++++++++++++++++++------------- reid/src/mir/display.rs | 2 +- reid/src/mir/pass.rs | 35 +++++---- reid/src/mir/typecheck.rs | 99 ++++++++--------------- reid/src/mir/typeinference.rs | 20 ++--- reid/src/mir/types.rs | 88 +++++++++++++++++++-- reid_src/struct.reid | 4 +- 9 files changed, 249 insertions(+), 155 deletions(-) diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index c04e156..a35a436 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -310,10 +310,12 @@ impl Builder { Instr::ArrayAlloca(_, _) => Ok(()), Instr::GetElemPtr(ptr_val, _) => { let ptr_ty = ptr_val.get_type(&self)?; - if let Type::Ptr(_) = ptr_ty { - Ok(()) - } else { - Err(()) // TODO error: not a pointer + match ptr_ty { + Type::CustomType(custom) => match self.type_data(&custom).kind { + CustomTypeKind::NamedStruct(_) => Ok(()), + }, + Type::Ptr(_) => Ok(()), + _ => Err(()), } } Instr::GetStructElemPtr(ptr_val, idx) => { diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 9eee9cd..d6fb8b5 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -317,6 +317,8 @@ impl InstructionValue { GetElemPtr(ptr, _) => ptr.get_type(builder), GetStructElemPtr(instr, idx) => { let instr_ty = instr.get_type(builder)?; + dbg!(&builder); + dbg!(&instr, &instr_ty, idx); let Type::Ptr(inner_ty) = instr_ty else { panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty) }; diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 82093aa..b3ac0c8 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -65,7 +65,7 @@ impl mir::Module { // TODO: Reorder custom-type definitions such that // inner types get evaluated first. Otherwise this // will cause a panic! - .map(|StructField(_, t, _)| t.get_type(&type_values)) + .map(|StructField(_, t, _)| t.get_type(&type_values, &types)) .collect(), ))) } @@ -80,14 +80,14 @@ impl mir::Module { let param_types: Vec = function .parameters .iter() - .map(|(_, p)| p.get_type(&type_values)) + .map(|(_, p)| p.get_type(&type_values, &types)) .collect(); let is_main = self.is_main && function.name == "main"; let func = match &function.kind { mir::FunctionDefinitionKind::Local(_, _) => module.function( &function.name, - function.return_type.get_type(&type_values), + function.return_type.get_type(&type_values, &types), param_types, FunctionFlags { is_pub: function.is_pub || is_main, @@ -98,7 +98,7 @@ impl mir::Module { ), mir::FunctionDefinitionKind::Extern(imported) => module.function( &function.name, - function.return_type.get_type(&type_values), + function.return_type.get_type(&type_values, &types), param_types, FunctionFlags { is_extern: true, @@ -120,7 +120,7 @@ impl mir::Module { p_name.clone(), StackValue( StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()), - p_ty.get_type(&type_values), + p_ty.get_type(&type_values, &types), ), ); } @@ -202,48 +202,6 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { } } -impl IndexedVariableReference { - fn get_stack_value(&self, scope: &mut Scope) -> Option<(StackValue, Vec)> { - match &self.kind { - mir::IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => scope - .stack_values - .get(name) - .cloned() - .map(|v| (v, Vec::new())), - mir::IndexedVariableReferenceKind::ArrayIndex(inner, idx) => { - let (inner_val, mut indices) = inner.get_stack_value(scope)?; - - match &inner_val.1 { - Type::Ptr(_) => { - indices.push(*idx as u32); - Some((inner_val, indices)) - } - _ => panic!("Tried to codegen indexing a non-indexable value!"), - } - } - mir::IndexedVariableReferenceKind::StructIndex(inner, field) => { - let (inner_val, mut indices) = inner.get_stack_value(scope)?; - - let idx = if let Type::CustomType(ty_val) = inner_val.1 { - match scope.types.get(&ty_val).unwrap() { - TypeDefinitionKind::Struct(struct_type) => struct_type.find_index(field), - } - } else { - None - }?; - - match &inner_val.1 { - Type::Ptr(_) => { - indices.push(idx as u32); - Some((inner_val, indices)) - } - _ => panic!("Tried to codegen indexing a non-indexable value!"), - } - } - } - } -} - impl mir::Statement { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option { match &self.0 { @@ -255,13 +213,22 @@ impl mir::Statement { match mutable { false => StackValueKind::Immutable(value), true => match ty { + // Struct is already allocated at initialization TypeKind::Array(_, _) => StackValueKind::Mutable(value), + TypeKind::CustomType(n) => match scope + .types + .get(scope.type_values.get(n).unwrap()) + .unwrap() + { + // Struct also is allocated at initialization + TypeDefinitionKind::Struct(_) => StackValueKind::Mutable(value), + }, _ => StackValueKind::Mutable({ let alloca = scope .block .build(Instr::Alloca( name.clone(), - ty.get_type(scope.type_values), + ty.get_type(scope.type_values, scope.types), )) .unwrap(); scope.block.build(Instr::Store(alloca, value)).unwrap(); @@ -269,7 +236,7 @@ impl mir::Statement { }), }, }, - ty.get_type(scope.type_values), + ty.get_type(scope.type_values, scope.types), ), ); None @@ -454,7 +421,10 @@ impl mir::Expression { Some( scope .block - .build(Instr::Load(ptr, val_t.get_type(scope.type_values))) + .build(Instr::Load( + ptr, + val_t.get_type(scope.type_values, scope.types), + )) .unwrap(), ) } @@ -472,7 +442,7 @@ impl mir::Expression { let array = scope .block .build(Instr::ArrayAlloca( - instr_t.get_type(scope.type_values), + instr_t.get_type(scope.type_values, scope.types), instr_list.len() as u32, )) .unwrap(); @@ -502,10 +472,14 @@ impl mir::Expression { .build(Instr::GetStructElemPtr(struct_val, idx as u32)) .unwrap(); + dbg!(&type_kind.get_type(scope.type_values, scope.types)); Some( scope .block - .build(Instr::Load(ptr, type_kind.get_type(scope.type_values))) + .build(Instr::Load( + ptr, + type_kind.get_type(scope.type_values, scope.types), + )) .unwrap(), ) } @@ -534,6 +508,56 @@ impl mir::Expression { } } +impl IndexedVariableReference { + fn get_stack_value(&self, scope: &mut Scope) -> Option<(StackValue, Vec)> { + match &self.kind { + mir::IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => scope + .stack_values + .get(name) + .cloned() + .map(|v| (v, Vec::new())), + mir::IndexedVariableReferenceKind::ArrayIndex(inner, idx) => { + let (inner_val, mut indices) = inner.get_stack_value(scope)?; + + match &inner_val.1 { + Type::Ptr(_) => { + indices.push(*idx as u32); + Some((inner_val, indices)) + } + _ => panic!("Tried to codegen indexing a non-indexable value!"), + } + } + mir::IndexedVariableReferenceKind::StructIndex(inner, field) => { + let (inner_val, mut indices) = inner.get_stack_value(scope)?; + + let (idx, elem_ty) = if let Type::Ptr(inner_ty) = inner_val.1 { + if let Type::CustomType(ty_val) = *inner_ty { + match scope.types.get(&ty_val).unwrap() { + TypeDefinitionKind::Struct(struct_type) => Some(( + struct_type.find_index(field)?, + struct_type.get_field_ty(field)?, + )), + } + } else { + None + } + } else { + None + }?; + + indices.push(idx as u32); + Some(( + StackValue( + inner_val.0, + Type::Ptr(Box::new(elem_ty.get_type(scope.type_values, scope.types))), + ), + indices, + )) + } + } + } +} + impl mir::CmpOperator { fn int_predicate(&self) -> CmpPredicate { match self { @@ -596,7 +620,11 @@ impl mir::Literal { } impl TypeKind { - fn get_type(&self, type_vals: &HashMap) -> Type { + fn get_type( + &self, + type_vals: &HashMap, + typedefs: &HashMap, + ) -> Type { match &self { TypeKind::I8 => Type::I8, TypeKind::I16 => Type::I16, @@ -610,10 +638,16 @@ impl TypeKind { TypeKind::U128 => Type::U128, TypeKind::Bool => Type::Bool, TypeKind::StringPtr => Type::Ptr(Box::new(Type::I8)), - TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type(type_vals))), + TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type(type_vals, typedefs))), TypeKind::Void => Type::Void, TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), - TypeKind::CustomType(n) => Type::CustomType(type_vals.get(n).unwrap().clone()), + TypeKind::CustomType(n) => { + let type_val = type_vals.get(n).unwrap().clone(); + let custom_t = Type::CustomType(type_val); + match typedefs.get(&type_val).unwrap() { + TypeDefinitionKind::Struct(_) => Type::Ptr(Box::new(custom_t)), + } + } } } } diff --git a/reid/src/mir/display.rs b/reid/src/mir/display.rs index 912caf3..38cf46f 100644 --- a/reid/src/mir/display.rs +++ b/reid/src/mir/display.rs @@ -66,7 +66,7 @@ impl Display for TypeDefinitionKind { impl Display for StructField { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "{}: {:?},", self.0, self.1) + write!(f, "{}: {:?}", self.0, self.1) } } diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index cc5eae3..a2cc8bd 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -33,9 +33,6 @@ impl STDError for Error { } } -#[derive(Clone, Debug)] -pub struct Storage(HashMap); - #[derive(Debug)] pub struct State { pub errors: Vec>, @@ -84,6 +81,9 @@ impl State { } } +#[derive(Clone, Debug)] +pub struct Storage(HashMap); + impl Default for Storage { fn default() -> Self { Self(Default::default()) @@ -114,6 +114,24 @@ pub struct Scope { pub return_type_hint: Option, } +impl Scope { + pub fn inner(&self) -> Scope { + Scope { + function_returns: self.function_returns.clone(), + variables: self.variables.clone(), + types: self.types.clone(), + return_type_hint: self.return_type_hint.clone(), + } + } + + pub fn get_struct_type(&self, name: &String) -> Option<&StructType> { + let ty = self.types.get(&name)?; + match ty { + TypeDefinitionKind::Struct(struct_ty) => Some(struct_ty), + } + } +} + #[derive(Clone, Debug)] pub struct ScopeFunction { pub ret: TypeKind, @@ -126,17 +144,6 @@ pub struct ScopeVariable { pub mutable: bool, } -impl Scope { - pub fn inner(&self) -> Scope { - Scope { - function_returns: self.function_returns.clone(), - variables: self.variables.clone(), - types: self.types.clone(), - return_type_hint: self.return_type_hint.clone(), - } - } -} - pub struct PassState<'st, 'sc, TError: STDError + Clone> { state: &'st mut State, pub scope: &'sc mut Scope, diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 57da88b..34a5565 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -186,7 +186,7 @@ impl Block { fn typecheck( &mut self, state: &mut PassState, - hints: &TypeRefs, + typerefs: &TypeRefs, hint_t: Option<&TypeKind>, ) -> Result<(ReturnKind, TypeKind), ErrorKind> { let mut state = state.inner(); @@ -197,10 +197,10 @@ impl Block { let ret = match &mut statement.0 { StmtKind::Let(variable_reference, mutable, expression) => { // Resolve possible hint in var reference - let var_t_resolved = variable_reference.0.resolve_hinted(&hints); + let var_t_resolved = variable_reference.0.resolve_ref(&typerefs); // Typecheck (and coerce) expression with said type - let res = expression.typecheck(&mut state, &hints, Some(&var_t_resolved)); + let res = expression.typecheck(&mut state, &typerefs, Some(&var_t_resolved)); // If expression resolution itself was erronous, resolve as // Unknown and note error. @@ -222,7 +222,7 @@ impl Block { ); // Re-typecheck and coerce expression to default type - let expr_res = expression.typecheck(&mut state, &hints, Some(&res_t)); + let expr_res = expression.typecheck(&mut state, &typerefs, Some(&res_t)); state.ok(expr_res, expression.1); res_t @@ -251,6 +251,9 @@ impl Block { None } StmtKind::Set(variable_reference, expression) => { + // Update typing from reference + variable_reference.resolve_ref(&typerefs)?; + if let Some(var) = state .ok( variable_reference @@ -259,8 +262,11 @@ impl Block { ) .flatten() { + let field_ty = variable_reference.retrieve_type(&state.scope)?; + dbg!(&field_ty); + // Typecheck expression and coerce to variable type - let res = expression.typecheck(&mut state, &hints, Some(&var.ty)); + let res = expression.typecheck(&mut state, &typerefs, Some(&field_ty)); // If expression resolution itself was erronous, resolve as // Unknown. @@ -269,15 +275,11 @@ impl Block { // Make sure the expression and variable type to really // be the same - let res_t = state.or_else( - expr_ty.collapse_into(&var.ty.resolve_hinted(&hints)), - TypeKind::Vague(Vague::Unknown), + state.ok( + expr_ty.collapse_into(&field_ty), variable_reference.meta + expression.1, ); - // Update typing to be more accurate - variable_reference.update_type(&res_t); - if !var.mutable { state.ok::<_, Infallible>( Err(ErrorKind::VariableNotMutable(variable_reference.get_name())), @@ -296,7 +298,7 @@ impl Block { } StmtKind::Import(_) => todo!(), // TODO StmtKind::Expression(expression) => { - let res = expression.typecheck(&mut state, &hints, None); + let res = expression.typecheck(&mut state, &typerefs, None); state.or_else(res, TypeKind::Void, expression.1); if let Ok((kind, _)) = expression.return_type() { Some((kind, expression)) @@ -316,7 +318,7 @@ impl Block { // block) if let Some((ReturnKind::Hard, expr)) = early_return { let hint = state.scope.return_type_hint.clone(); - let res = expr.typecheck(&mut state, &hints, hint.as_ref()); + let res = expr.typecheck(&mut state, &typerefs, hint.as_ref()); return Ok(( ReturnKind::Hard, state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), @@ -329,7 +331,7 @@ impl Block { ReturnKind::Hard => state.scope.return_type_hint.clone(), ReturnKind::Soft => hint_t.cloned(), }; - let res = expr.typecheck(&mut state, &hints, ret_hint_t.as_ref()); + let res = expr.typecheck(&mut state, &typerefs, ret_hint_t.as_ref()); Ok(( *return_kind, state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), @@ -361,11 +363,11 @@ impl Expression { TypeKind::Vague(Vague::Unknown), var_ref.2, ) - .resolve_hinted(hints); + .resolve_ref(hints); // Update typing to be more accurate var_ref.0 = state.or_else( - var_ref.0.resolve_hinted(hints).collapse_into(&existing), + var_ref.0.resolve_ref(hints).collapse_into(&existing), TypeKind::Vague(Vague::Unknown), var_ref.2, ); @@ -437,12 +439,12 @@ impl Expression { // return type let ret_t = f .ret - .collapse_into(&function_call.return_type.resolve_hinted(hints))?; + .collapse_into(&function_call.return_type.resolve_ref(hints))?; // Update typing to be more accurate function_call.return_type = ret_t.clone(); - Ok(ret_t.resolve_hinted(hints)) + Ok(ret_t.resolve_ref(hints)) } else { - Ok(function_call.return_type.clone().resolve_hinted(hints)) + Ok(function_call.return_type.clone().resolve_ref(hints)) } } ExprKind::If(IfExpression(cond, lhs, rhs)) => { @@ -515,7 +517,7 @@ impl Expression { return Err(ErrorKind::IndexOutOfBounds(*idx, len)); } let ty = state.or_else( - elem_ty.resolve_hinted(hints).collapse_into(&inferred_ty), + elem_ty.resolve_ref(hints).collapse_into(&inferred_ty), TypeKind::Vague(Vague::Unknown), self.1, ); @@ -564,7 +566,7 @@ impl Expression { } ExprKind::StructIndex(expression, type_kind, field_name) => { // Resolve expected type - let expected_ty = type_kind.resolve_hinted(hints); + let expected_ty = type_kind.resolve_ref(hints); // Typecheck expression let expr_res = expression.typecheck(state, hints, Some(&expected_ty)); @@ -572,7 +574,10 @@ impl Expression { state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); if let TypeKind::CustomType(struct_name) = expr_ty { - let struct_type = state.scope.get_struct_type(&struct_name)?; + let struct_type = state + .scope + .get_struct_type(&struct_name) + .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?; if let Some(expr_field_ty) = struct_type.get_field_ty(&field_name) { // Make sure they are the same let true_ty = state.or_else( @@ -591,7 +596,11 @@ impl Expression { } } ExprKind::Struct(struct_name, items) => { - let struct_def = state.scope.get_struct_type(struct_name)?.clone(); + let struct_def = state + .scope + .get_struct_type(struct_name) + .ok_or(ErrorKind::NoSuchType(struct_name.clone()))? + .clone(); for (field_name, field_expr) in items { // Get expected type, or error if field does not exist let expected_ty = state.or_else( @@ -718,37 +727,7 @@ impl Literal { } } -impl TypeKind { - /// Assert that a type is already known and not vague. Return said type or - /// error. - pub fn assert_known(&self) -> Result { - self.known().map_err(ErrorKind::TypeIsVague) - } - - /// Try to collapse a type on itself producing a default type if one exists, - /// Error if not. - fn or_default(&self) -> Result { - match self { - TypeKind::Vague(vague_type) => match &vague_type { - Vague::Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), - Vague::Number => Ok(TypeKind::I32), - Vague::TypeRef(_) => panic!("Hinted default!"), - }, - _ => Ok(self.clone()), - } - } - - fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind { - let resolved = match self { - TypeKind::Vague(Vague::TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(), - _ => self.clone(), - }; - match resolved { - TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_hinted(hints)), len), - _ => resolved, - } - } -} +impl TypeKind {} pub trait Collapsable: Sized + Clone { /// Try to narrow two types into one singular type. E.g. Vague(Number) and @@ -803,15 +782,3 @@ impl Collapsable for ScopeFunction { }) } } - -impl pass::Scope { - pub fn get_struct_type(&self, name: &String) -> Result<&StructType, ErrorKind> { - let ty = self - .types - .get(&name) - .ok_or(ErrorKind::NoSuchType(name.clone()))?; - match ty { - TypeDefinitionKind::Struct(struct_ty) => Ok(struct_ty), - } - } -} diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index b0e6820..4c6e25f 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -106,13 +106,8 @@ impl Block { } } StmtKind::Set(var, expr) => { - // Get the TypeRef for this variable declaration - let var_ref = var.find_hint(&state, &inner_hints)?; - - // If ok, update the MIR type to this TypeRef - if let Some((_, var_ref)) = &var_ref { - var.update_type(&var_ref.as_type()); - } + // Update this MIR type to its TypeRef + let var_ref = var.into_typeref(&inner_hints); // Infer hints for the expression itself let inferred = expr.infer_types(&mut state, &inner_hints); @@ -371,7 +366,10 @@ impl Expression { let kind = expr_ty.resolve_weak().unwrap(); match kind { CustomType(name) => { - let struct_ty = state.scope.get_struct_type(&name)?; + let struct_ty = state + .scope + .get_struct_type(&name) + .ok_or(ErrorKind::NoSuchType(name.clone()))?; match struct_ty.get_field_ty(&field_name) { Some(field_ty) => { let mut elem_ty = type_refs.from_type(&type_kind).unwrap(); @@ -386,7 +384,11 @@ impl Expression { } } ExprKind::Struct(struct_name, fields) => { - let expected_struct_ty = state.scope.get_struct_type(&struct_name)?.clone(); + let expected_struct_ty = state + .scope + .get_struct_type(&struct_name) + .ok_or(ErrorKind::NoSuchType(struct_name.clone()))? + .clone(); for field in fields { if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { let field_ty = field.1.infer_types(state, type_refs); diff --git a/reid/src/mir/types.rs b/reid/src/mir/types.rs index 1701fb4..5d640bc 100644 --- a/reid/src/mir/types.rs +++ b/reid/src/mir/types.rs @@ -1,4 +1,8 @@ -use super::*; +use super::{ + typecheck::{Collapsable, ErrorKind}, + typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, + VagueType as Vague, *, +}; #[derive(Debug, Clone)] pub enum ReturnTypeOther { @@ -179,6 +183,38 @@ pub fn pick_return(lhs: (ReturnKind, T), rhs: (ReturnKind, T)) -> (ReturnKind } } +impl TypeKind { + /// Assert that a type is already known and not vague. Return said type or + /// error. + pub fn assert_known(&self) -> Result { + self.known().map_err(ErrorKind::TypeIsVague) + } + + /// Try to collapse a type on itself producing a default type if one exists, + /// Error if not. + pub fn or_default(&self) -> Result { + match self { + TypeKind::Vague(vague_type) => match &vague_type { + Vague::Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), + Vague::Number => Ok(TypeKind::I32), + Vague::TypeRef(_) => panic!("Hinted default!"), + }, + _ => Ok(self.clone()), + } + } + + pub fn resolve_ref(&self, refs: &TypeRefs) -> TypeKind { + let resolved = match self { + TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_type(*idx).unwrap(), + _ => self.clone(), + }; + match resolved { + TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len), + _ => resolved, + } + } +} + impl IndexedVariableReference { pub fn get_name(&self) -> String { match &self.kind { @@ -192,13 +228,55 @@ impl IndexedVariableReference { } } - pub fn update_type(&mut self, new_ty: &TypeKind) { + /// Retrieve the indexed type that this variable reference is pointing to + pub fn retrieve_type(&self, scope: &pass::Scope) -> Result { + match &self.kind { + IndexedVariableReferenceKind::Named(NamedVariableRef(ty, _, _)) => Ok(ty.clone()), + IndexedVariableReferenceKind::ArrayIndex(inner, _) => { + let inner_ty = inner.retrieve_type(scope)?; + match inner_ty { + TypeKind::Array(type_kind, _) => Ok(*type_kind), + _ => Err(ErrorKind::TriedIndexingNonArray(inner_ty)), + } + } + IndexedVariableReferenceKind::StructIndex(inner, field_name) => { + let inner_ty = inner.retrieve_type(scope)?; + match inner_ty { + TypeKind::CustomType(struct_name) => { + let struct_ty = scope + .get_struct_type(&struct_name) + .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?; + struct_ty + .get_field_ty(&field_name) + .ok_or(ErrorKind::NoSuchField(field_name.clone())) + .cloned() + } + _ => Err(ErrorKind::TriedAccessingNonStruct(inner_ty)), + } + } + } + } + + pub fn into_typeref<'s>(&mut self, typerefs: &'s ScopeTypeRefs) -> Option<(bool, TypeRef<'s>)> { + match &mut self.kind { + IndexedVariableReferenceKind::Named(NamedVariableRef(ty, name, _)) => { + let t = typerefs.find_var(name)?; + *ty = t.1.as_type(); + Some(t) + } + IndexedVariableReferenceKind::ArrayIndex(inner, _) => inner.into_typeref(typerefs), + IndexedVariableReferenceKind::StructIndex(inner, _) => inner.into_typeref(typerefs), + } + } + + pub fn resolve_ref<'s>(&mut self, typerefs: &'s TypeRefs) -> Result { match &mut self.kind { IndexedVariableReferenceKind::Named(NamedVariableRef(ty, _, _)) => { - *ty = new_ty.clone(); + *ty = ty.resolve_ref(typerefs); + Ok(ty.clone()) } - IndexedVariableReferenceKind::ArrayIndex(inner, _) => inner.update_type(new_ty), - IndexedVariableReferenceKind::StructIndex(inner, _) => inner.update_type(new_ty), + IndexedVariableReferenceKind::ArrayIndex(inner, _) => inner.resolve_ref(typerefs), + IndexedVariableReferenceKind::StructIndex(inner, _) => inner.resolve_ref(typerefs), } } } diff --git a/reid_src/struct.reid b/reid_src/struct.reid index 988aef2..ac293d7 100644 --- a/reid_src/struct.reid +++ b/reid_src/struct.reid @@ -6,10 +6,12 @@ struct Test { } fn main() -> u32 { - let value = Test { + let mut value = Test { field: 5, second: 3, }; + value.second = 17; + return value.second; }