Typecheck custom binops
This commit is contained in:
parent
974c7e98f1
commit
50af50c43f
@ -1,7 +1,7 @@
|
|||||||
// Arithmetic, function calls and imports!
|
// Arithmetic, function calls and imports!
|
||||||
|
|
||||||
impl binop (lhs: u32) + (rhs: u32) -> u32 {
|
impl binop (lhs: u16) + (rhs: u32) -> u32 {
|
||||||
|
return (lhs as u32) + rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> u32 {
|
fn main() -> u32 {
|
||||||
|
@ -217,6 +217,7 @@ pub struct BinopDefinition {
|
|||||||
pub rhs: (String, Type),
|
pub rhs: (String, Type),
|
||||||
pub return_ty: Type,
|
pub return_ty: Type,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
|
pub signature_range: TokenRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -554,7 +554,11 @@ impl Parse for Block {
|
|||||||
statements.push(statement);
|
statements.push(statement);
|
||||||
}
|
}
|
||||||
stream.expect(Token::BraceClose)?;
|
stream.expect(Token::BraceClose)?;
|
||||||
Ok(Block(statements, return_stmt, stream.get_range().unwrap()))
|
Ok(Block(
|
||||||
|
statements,
|
||||||
|
return_stmt,
|
||||||
|
stream.get_range_prev().unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,6 +818,8 @@ impl Parse for BinopDefinition {
|
|||||||
let rhs_type = stream.parse()?;
|
let rhs_type = stream.parse()?;
|
||||||
stream.expect(Token::ParenClose)?;
|
stream.expect(Token::ParenClose)?;
|
||||||
|
|
||||||
|
let signature_range = stream.get_range().unwrap();
|
||||||
|
|
||||||
stream.expect(Token::Arrow)?;
|
stream.expect(Token::Arrow)?;
|
||||||
|
|
||||||
Ok(BinopDefinition {
|
Ok(BinopDefinition {
|
||||||
@ -822,6 +828,7 @@ impl Parse for BinopDefinition {
|
|||||||
rhs: (rhs_name, rhs_type),
|
rhs: (rhs_name, rhs_type),
|
||||||
return_ty: stream.parse()?,
|
return_ty: stream.parse()?,
|
||||||
block: stream.parse()?,
|
block: stream.parse()?,
|
||||||
|
signature_range,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ impl ast::Module {
|
|||||||
rhs,
|
rhs,
|
||||||
return_ty,
|
return_ty,
|
||||||
block,
|
block,
|
||||||
|
signature_range,
|
||||||
}) => {
|
}) => {
|
||||||
binops.push(mir::BinopDefinition {
|
binops.push(mir::BinopDefinition {
|
||||||
lhs: (lhs.0.clone(), lhs.1 .0.into_mir(module_id)),
|
lhs: (lhs.0.clone(), lhs.1 .0.into_mir(module_id)),
|
||||||
@ -111,6 +112,7 @@ impl ast::Module {
|
|||||||
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),
|
block: block.into_mir(module_id),
|
||||||
|
meta: signature_range.as_meta(module_id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,9 @@ impl Display for Module {
|
|||||||
for import in &self.imports {
|
for import in &self.imports {
|
||||||
writeln!(inner_f, "{}", import)?;
|
writeln!(inner_f, "{}", import)?;
|
||||||
}
|
}
|
||||||
|
for binop in &self.binop_defs {
|
||||||
|
writeln!(inner_f, "{}", binop)?;
|
||||||
|
}
|
||||||
for typedef in &self.typedefs {
|
for typedef in &self.typedefs {
|
||||||
writeln!(inner_f, "{}", typedef)?;
|
writeln!(inner_f, "{}", typedef)?;
|
||||||
}
|
}
|
||||||
@ -56,6 +59,17 @@ impl Display for Import {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for BinopDefinition {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ",
|
||||||
|
self.lhs.0, self.lhs.1, self.op, self.rhs.0, self.rhs.1, self.return_ty
|
||||||
|
)?;
|
||||||
|
Display::fmt(&self.block, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for TypeDefinition {
|
impl Display for TypeDefinition {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "type {} = ", self.name)?;
|
write!(f, "type {} = ", self.name)?;
|
||||||
|
@ -372,6 +372,17 @@ pub struct BinopDefinition {
|
|||||||
pub rhs: (String, TypeKind),
|
pub rhs: (String, TypeKind),
|
||||||
pub return_ty: TypeKind,
|
pub return_ty: TypeKind,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
|
pub meta: Metadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinopDefinition {
|
||||||
|
pub fn block_meta(&self) -> Metadata {
|
||||||
|
self.block.meta
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signature(&self) -> Metadata {
|
||||||
|
self.meta
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -132,6 +132,11 @@ impl<'t> Pass for TypeCheck<'t> {
|
|||||||
check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state);
|
check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for binop in &mut module.binop_defs {
|
||||||
|
let res = binop.typecheck(&self.refs, &mut state.inner());
|
||||||
|
state.ok(res, binop.block_meta());
|
||||||
|
}
|
||||||
|
|
||||||
for function in &mut module.functions {
|
for function in &mut module.functions {
|
||||||
let res = function.typecheck(&self.refs, &mut state.inner());
|
let res = function.typecheck(&self.refs, &mut state.inner());
|
||||||
state.ok(res, function.block_meta());
|
state.ok(res, function.block_meta());
|
||||||
@ -170,6 +175,48 @@ fn check_typedefs_for_recursion<'a, 'b>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BinopDefinition {
|
||||||
|
fn typecheck(
|
||||||
|
&mut self,
|
||||||
|
typerefs: &TypeRefs,
|
||||||
|
state: &mut TypecheckPassState,
|
||||||
|
) -> Result<TypeKind, ErrorKind> {
|
||||||
|
for param in vec![&self.lhs, &self.rhs] {
|
||||||
|
let param_t = state.or_else(
|
||||||
|
param.1.assert_known(typerefs, state),
|
||||||
|
TypeKind::Vague(Vague::Unknown),
|
||||||
|
self.signature(),
|
||||||
|
);
|
||||||
|
let res = state
|
||||||
|
.scope
|
||||||
|
.variables
|
||||||
|
.set(
|
||||||
|
param.0.clone(),
|
||||||
|
ScopeVariable {
|
||||||
|
ty: param_t.clone(),
|
||||||
|
mutable: param_t.is_mutable(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.or(Err(ErrorKind::VariableAlreadyDefined(param.0.clone())));
|
||||||
|
state.ok(res, self.signature());
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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 FunctionDefinition {
|
impl FunctionDefinition {
|
||||||
fn typecheck(
|
fn typecheck(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -12,8 +12,8 @@ use super::{
|
|||||||
pass::{Pass, PassResult, PassState},
|
pass::{Pass, PassResult, PassState},
|
||||||
typecheck::{ErrorKind, ErrorTypedefKind},
|
typecheck::{ErrorKind, ErrorTypedefKind},
|
||||||
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
||||||
Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind,
|
BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition,
|
||||||
IfExpression, Module, ReturnKind, StmtKind,
|
FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind,
|
||||||
TypeKind::*,
|
TypeKind::*,
|
||||||
VagueType::*,
|
VagueType::*,
|
||||||
WhileStatement,
|
WhileStatement,
|
||||||
@ -55,6 +55,11 @@ 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());
|
||||||
|
}
|
||||||
|
|
||||||
for function in &mut module.functions {
|
for function in &mut module.functions {
|
||||||
let res = function.infer_types(&self.refs, &mut state.inner());
|
let res = function.infer_types(&self.refs, &mut state.inner());
|
||||||
state.ok(res, function.block_meta());
|
state.ok(res, function.block_meta());
|
||||||
@ -63,6 +68,56 @@ impl<'t> Pass for TypeInference<'t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BinopDefinition {
|
||||||
|
fn infer_types(
|
||||||
|
&mut self,
|
||||||
|
type_refs: &TypeRefs,
|
||||||
|
state: &mut TypeInferencePassState,
|
||||||
|
) -> Result<(), ErrorKind> {
|
||||||
|
let scope_hints = ScopeTypeRefs::from(type_refs);
|
||||||
|
|
||||||
|
let lhs_ty = state.or_else(
|
||||||
|
self.lhs.1.assert_unvague(),
|
||||||
|
Vague(Unknown),
|
||||||
|
self.signature(),
|
||||||
|
);
|
||||||
|
state.ok(
|
||||||
|
scope_hints
|
||||||
|
.new_var(self.lhs.0.clone(), false, &lhs_ty)
|
||||||
|
.or(Err(ErrorKind::VariableAlreadyDefined(self.lhs.0.clone()))),
|
||||||
|
self.signature(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let rhs_ty = state.or_else(
|
||||||
|
self.rhs.1.assert_unvague(),
|
||||||
|
Vague(Unknown),
|
||||||
|
self.signature(),
|
||||||
|
);
|
||||||
|
|
||||||
|
state.ok(
|
||||||
|
scope_hints
|
||||||
|
.new_var(self.rhs.0.clone(), false, &rhs_ty)
|
||||||
|
.or(Err(ErrorKind::VariableAlreadyDefined(self.rhs.0.clone()))),
|
||||||
|
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());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FunctionDefinition {
|
impl FunctionDefinition {
|
||||||
fn infer_types(
|
fn infer_types(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
Loading…
Reference in New Issue
Block a user