From a7795f83db1ada379648c3067d760c6a76b71d6b Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 13:40:06 +0300 Subject: [PATCH] Use FunctionDefinitionKind for binops --- reid/src/ast/process.rs | 5 ++- reid/src/mir/fmt.rs | 2 +- reid/src/mir/mod.rs | 10 ++++-- reid/src/mir/typecheck.rs | 47 +++++++++++++++++++--------- reid/src/mir/typeinference.rs | 58 +++++++++++++++++++++++++---------- 5 files changed, 85 insertions(+), 37 deletions(-) diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index bad6d67..8387531 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -111,7 +111,10 @@ impl ast::Module { op: op.mir(), rhs: (rhs.0.clone(), rhs.1 .0.into_mir(module_id)), return_ty: return_ty.0.into_mir(module_id), - block: block.into_mir(module_id), + fn_kind: mir::FunctionDefinitionKind::Local( + block.into_mir(module_id), + block.2.as_meta(module_id), + ), meta: signature_range.as_meta(module_id), }); } diff --git a/reid/src/mir/fmt.rs b/reid/src/mir/fmt.rs index 9a31e51..4505afd 100644 --- a/reid/src/mir/fmt.rs +++ b/reid/src/mir/fmt.rs @@ -66,7 +66,7 @@ impl Display for BinopDefinition { "impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ", self.lhs.0, self.lhs.1, self.op, self.rhs.0, self.rhs.1, self.return_ty )?; - Display::fmt(&self.block, f) + Display::fmt(&self.fn_kind, f) } } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index db1ce2b..dfee8a3 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -371,13 +371,17 @@ pub struct BinopDefinition { pub op: BinaryOperator, pub rhs: (String, TypeKind), pub return_ty: TypeKind, - pub block: Block, + pub fn_kind: FunctionDefinitionKind, pub meta: Metadata, } impl BinopDefinition { - pub fn block_meta(&self) -> Metadata { - self.block.meta + pub fn block_meta(&self) -> Option { + match &self.fn_kind { + FunctionDefinitionKind::Local(block, _) => Some(block.meta), + FunctionDefinitionKind::Extern(_) => None, + FunctionDefinitionKind::Intrinsic(_) => None, + } } pub fn signature(&self) -> Metadata { diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 3d70126..f15b555 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -136,7 +136,7 @@ impl<'t> Pass for TypeCheck<'t> { for binop in &mut module.binop_defs { let res = binop.typecheck(&self.refs, &mut state.inner()); - state.ok(res, binop.block_meta()); + state.ok(res, binop.block_meta().unwrap_or(binop.signature())); } for function in &mut module.functions { @@ -206,15 +206,19 @@ impl BinopDefinition { let return_type = self.return_ty.clone().assert_known(typerefs, state)?; state.scope.return_type_hint = Some(self.return_ty.clone()); - let inferred = self - .block - .typecheck(&mut state.inner(), &typerefs, Some(&return_type)); + let inferred = + self.fn_kind + .typecheck(&typerefs, &mut state.inner(), Some(return_type.clone())); match inferred { Ok(t) => return_type .collapse_into(&t.1) .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), - Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta())), + Err(e) => Ok(state.or_else( + Err(e), + return_type, + self.block_meta().unwrap_or(self.signature()), + )), } } } @@ -246,10 +250,30 @@ impl FunctionDefinition { } let return_type = self.return_type.clone().assert_known(typerefs, state)?; - let inferred = match &mut self.kind { + let inferred = self + .kind + .typecheck(typerefs, state, Some(self.return_type.clone())); + + match inferred { + Ok(t) => return_type + .collapse_into(&t.1) + .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), + Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta())), + } + } +} + +impl FunctionDefinitionKind { + fn typecheck( + &mut self, + typerefs: &TypeRefs, + state: &mut TypecheckPassState, + hint: Option, + ) -> Result<(ReturnKind, TypeKind), ErrorKind> { + match self { FunctionDefinitionKind::Local(block, _) => { - state.scope.return_type_hint = Some(self.return_type.clone()); - block.typecheck(&mut state.inner(), &typerefs, Some(&return_type)) + state.scope.return_type_hint = hint.clone(); + block.typecheck(&mut state.inner(), &typerefs, hint.as_ref()) } FunctionDefinitionKind::Extern(_) => { Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) @@ -257,13 +281,6 @@ impl FunctionDefinition { FunctionDefinitionKind::Intrinsic(..) => { Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) } - }; - - match inferred { - Ok(t) => return_type - .collapse_into(&t.1) - .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), - Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta())), } } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index e831c64..ae7132b 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -80,7 +80,7 @@ impl<'t> Pass for TypeInference<'t> { for binop in &mut module.binop_defs { let res = binop.infer_types(&self.refs, &mut state.inner()); - state.ok(res, binop.block_meta()); + state.ok(res, binop.block_meta().unwrap_or(binop.signature())); } for function in &mut module.functions { @@ -124,18 +124,12 @@ impl BinopDefinition { self.signature(), ); - state.scope.return_type_hint = Some(self.return_ty.clone()); - let ret_res = self.block.infer_types(state, &scope_hints); - let (_, mut ret_ty) = state.or_else( - ret_res, - ( - ReturnKind::Soft, - scope_hints.from_type(&Vague(Unknown)).unwrap(), - ), - self.block_meta(), - ); - - ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap()); + let ret_ty = self + .fn_kind + .infer_types(state, &scope_hints, Some(self.return_ty.clone()))?; + if let Some(mut ret_ty) = ret_ty { + ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap()); + } Ok(()) } @@ -147,10 +141,10 @@ impl FunctionDefinition { type_refs: &TypeRefs, state: &mut TypeInferencePassState, ) -> Result<(), ErrorKind> { - let scope_hints = ScopeTypeRefs::from(type_refs); + let scope_refs = ScopeTypeRefs::from(type_refs); for param in &self.parameters { let param_t = state.or_else(param.1.assert_unvague(), Vague(Unknown), self.signature()); - let res = scope_hints + let res = scope_refs .new_var(param.0.clone(), false, ¶m_t) .or(Err(ErrorKind::VariableAlreadyDefined(param.0.clone()))); state.ok(res, self.signature()); @@ -161,21 +155,51 @@ impl FunctionDefinition { state.scope.return_type_hint = Some(self.return_type.clone()); // Infer block return type - let ret_res = block.infer_types(state, &scope_hints); + let ret_res = block.infer_types(state, &scope_refs); // Narrow block type to declared function type if let Some(mut ret_ty) = state.ok(ret_res.map(|(_, ty)| ty), self.block_meta()) { - ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap()); + ret_ty.narrow(&scope_refs.from_type(&self.return_type).unwrap()); } } FunctionDefinitionKind::Extern(_) => {} FunctionDefinitionKind::Intrinsic(_) => {} }; + let return_ty = self + .kind + .infer_types(state, &scope_refs, Some(self.return_type.clone())); + + if let Some(Some(mut ret_ty)) = state.ok(return_ty, self.block_meta()) { + ret_ty.narrow(&scope_refs.from_type(&self.return_type).unwrap()); + } Ok(()) } } +impl FunctionDefinitionKind { + fn infer_types<'s>( + &mut self, + state: &mut TypeInferencePassState, + scope_refs: &'s ScopeTypeRefs, + hint: Option, + ) -> Result>, ErrorKind> { + Ok(match self { + FunctionDefinitionKind::Local(block, _) => { + state.scope.return_type_hint = hint; + + // Infer block return type + let ret_res = block.infer_types(state, &scope_refs); + + // Narrow block type to declared function type + Some(ret_res.map(|(_, ty)| ty)?) + } + FunctionDefinitionKind::Extern(_) => None, + FunctionDefinitionKind::Intrinsic(_) => None, + }) + } +} + impl Block { fn infer_types<'s>( &mut self,