Use FunctionDefinitionKind for binops
This commit is contained in:
parent
7c6de93b31
commit
a7795f83db
@ -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),
|
||||
});
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Metadata> {
|
||||
match &self.fn_kind {
|
||||
FunctionDefinitionKind::Local(block, _) => Some(block.meta),
|
||||
FunctionDefinitionKind::Extern(_) => None,
|
||||
FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn signature(&self) -> Metadata {
|
||||
|
@ -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<TypeKind>,
|
||||
) -> 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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<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 {
|
||||
fn infer_types<'s>(
|
||||
&mut self,
|
||||
|
Loading…
Reference in New Issue
Block a user