Use FunctionDefinitionKind for binops

This commit is contained in:
Sofia 2025-07-24 13:40:06 +03:00
parent 7c6de93b31
commit a7795f83db
5 changed files with 85 additions and 37 deletions

View File

@ -111,7 +111,10 @@ impl ast::Module {
op: op.mir(), op: op.mir(),
rhs: (rhs.0.clone(), rhs.1 .0.into_mir(module_id)), rhs: (rhs.0.clone(), rhs.1 .0.into_mir(module_id)),
return_ty: return_ty.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), meta: signature_range.as_meta(module_id),
}); });
} }

View File

@ -66,7 +66,7 @@ impl Display for BinopDefinition {
"impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ", "impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ",
self.lhs.0, self.lhs.1, self.op, self.rhs.0, self.rhs.1, self.return_ty 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)
} }
} }

View File

@ -371,13 +371,17 @@ pub struct BinopDefinition {
pub op: BinaryOperator, pub op: BinaryOperator,
pub rhs: (String, TypeKind), pub rhs: (String, TypeKind),
pub return_ty: TypeKind, pub return_ty: TypeKind,
pub block: Block, pub fn_kind: FunctionDefinitionKind,
pub meta: Metadata, pub meta: Metadata,
} }
impl BinopDefinition { impl BinopDefinition {
pub fn block_meta(&self) -> Metadata { pub fn block_meta(&self) -> Option<Metadata> {
self.block.meta match &self.fn_kind {
FunctionDefinitionKind::Local(block, _) => Some(block.meta),
FunctionDefinitionKind::Extern(_) => None,
FunctionDefinitionKind::Intrinsic(_) => None,
}
} }
pub fn signature(&self) -> Metadata { pub fn signature(&self) -> Metadata {

View File

@ -136,7 +136,7 @@ impl<'t> Pass for TypeCheck<'t> {
for binop in &mut module.binop_defs { for binop in &mut module.binop_defs {
let res = binop.typecheck(&self.refs, &mut state.inner()); 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 { for function in &mut module.functions {
@ -206,15 +206,19 @@ impl BinopDefinition {
let return_type = self.return_ty.clone().assert_known(typerefs, state)?; let return_type = self.return_ty.clone().assert_known(typerefs, state)?;
state.scope.return_type_hint = Some(self.return_ty.clone()); state.scope.return_type_hint = Some(self.return_ty.clone());
let inferred = self let inferred =
.block self.fn_kind
.typecheck(&mut state.inner(), &typerefs, Some(&return_type)); .typecheck(&typerefs, &mut state.inner(), Some(return_type.clone()));
match inferred { match inferred {
Ok(t) => return_type Ok(t) => return_type
.collapse_into(&t.1) .collapse_into(&t.1)
.or(Err(ErrorKind::ReturnTypeMismatch(return_type, 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 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<TypeKind>,
) -> Result<(ReturnKind, TypeKind), ErrorKind> {
match self {
FunctionDefinitionKind::Local(block, _) => { FunctionDefinitionKind::Local(block, _) => {
state.scope.return_type_hint = Some(self.return_type.clone()); state.scope.return_type_hint = hint.clone();
block.typecheck(&mut state.inner(), &typerefs, Some(&return_type)) block.typecheck(&mut state.inner(), &typerefs, hint.as_ref())
} }
FunctionDefinitionKind::Extern(_) => { FunctionDefinitionKind::Extern(_) => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
@ -257,13 +281,6 @@ impl FunctionDefinition {
FunctionDefinitionKind::Intrinsic(..) => { FunctionDefinitionKind::Intrinsic(..) => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) 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())),
} }
} }
} }

View File

@ -80,7 +80,7 @@ impl<'t> Pass for TypeInference<'t> {
for binop in &mut module.binop_defs { for binop in &mut module.binop_defs {
let res = binop.infer_types(&self.refs, &mut state.inner()); 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 { for function in &mut module.functions {
@ -124,18 +124,12 @@ impl BinopDefinition {
self.signature(), self.signature(),
); );
state.scope.return_type_hint = Some(self.return_ty.clone()); let ret_ty = self
let ret_res = self.block.infer_types(state, &scope_hints); .fn_kind
let (_, mut ret_ty) = state.or_else( .infer_types(state, &scope_hints, Some(self.return_ty.clone()))?;
ret_res, if let Some(mut ret_ty) = ret_ty {
( ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap());
ReturnKind::Soft, }
scope_hints.from_type(&Vague(Unknown)).unwrap(),
),
self.block_meta(),
);
ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap());
Ok(()) Ok(())
} }
@ -147,10 +141,10 @@ impl FunctionDefinition {
type_refs: &TypeRefs, type_refs: &TypeRefs,
state: &mut TypeInferencePassState, state: &mut TypeInferencePassState,
) -> Result<(), ErrorKind> { ) -> Result<(), ErrorKind> {
let scope_hints = ScopeTypeRefs::from(type_refs); let scope_refs = ScopeTypeRefs::from(type_refs);
for param in &self.parameters { for param in &self.parameters {
let param_t = state.or_else(param.1.assert_unvague(), Vague(Unknown), self.signature()); 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, &param_t) .new_var(param.0.clone(), false, &param_t)
.or(Err(ErrorKind::VariableAlreadyDefined(param.0.clone()))); .or(Err(ErrorKind::VariableAlreadyDefined(param.0.clone())));
state.ok(res, self.signature()); state.ok(res, self.signature());
@ -161,21 +155,51 @@ impl FunctionDefinition {
state.scope.return_type_hint = Some(self.return_type.clone()); state.scope.return_type_hint = Some(self.return_type.clone());
// Infer block return type // 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 // Narrow block type to declared function type
if let Some(mut ret_ty) = state.ok(ret_res.map(|(_, ty)| ty), self.block_meta()) { 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::Extern(_) => {}
FunctionDefinitionKind::Intrinsic(_) => {} 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(()) Ok(())
} }
} }
impl FunctionDefinitionKind {
fn infer_types<'s>(
&mut self,
state: &mut TypeInferencePassState,
scope_refs: &'s ScopeTypeRefs,
hint: Option<TypeKind>,
) -> Result<Option<TypeRef<'s>>, 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 { impl Block {
fn infer_types<'s>( fn infer_types<'s>(
&mut self, &mut self,