Use FunctionDefinitionKind for binops
This commit is contained in:
parent
7c6de93b31
commit
a7795f83db
@ -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),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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())),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
(
|
|
||||||
ReturnKind::Soft,
|
|
||||||
scope_hints.from_type(&Vague(Unknown)).unwrap(),
|
|
||||||
),
|
|
||||||
self.block_meta(),
|
|
||||||
);
|
|
||||||
|
|
||||||
ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap());
|
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, ¶m_t)
|
.new_var(param.0.clone(), false, ¶m_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,
|
||||||
|
Loading…
Reference in New Issue
Block a user