inference and tests

This commit is contained in:
pca006132 2020-12-28 14:33:18 +08:00 committed by pca006132
parent 7f09596bcb
commit 929b7e1d92
4 changed files with 220 additions and 8 deletions

View File

@ -169,3 +169,208 @@ pub fn resolve_call(
} }
})) }))
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::primitives::*;
#[test]
fn test_simple_generic() {
let mut ctx = basic_ctx();
let mut assumptions = HashMap::new();
assert_eq!(
resolve_call(
&ctx,
None,
"int32",
create_tuple(vec![PrimitiveType(FLOAT_TYPE).into()]),
&mut assumptions
),
Ok(Some(PrimitiveType(INT32_TYPE).into()))
);
assert_eq!(
resolve_call(
&ctx,
None,
"int32",
create_tuple(vec![PrimitiveType(INT32_TYPE).into()]),
&mut assumptions
),
Ok(Some(PrimitiveType(INT32_TYPE).into()))
);
assert_eq!(
resolve_call(
&ctx,
None,
"float",
create_tuple(vec![PrimitiveType(INT32_TYPE).into()]),
&mut assumptions
),
Ok(Some(PrimitiveType(FLOAT_TYPE).into()))
);
assert_eq!(
resolve_call(
&ctx,
None,
"float",
create_tuple(vec![PrimitiveType(BOOL_TYPE).into()]),
&mut assumptions
),
Err("different domain".to_string())
);
let v1 = ctx.add_variable(VarDef {
name: "V1",
bound: vec![
PrimitiveType(INT32_TYPE).into(),
PrimitiveType(FLOAT_TYPE).into(),
],
});
assert_eq!(
resolve_call(
&ctx,
None,
"float",
create_tuple(vec![TypeVariable(v1).into()]),
&mut assumptions
),
Ok(Some(PrimitiveType(FLOAT_TYPE).into()))
);
let v2 = ctx.add_variable(VarDef {
name: "V2",
bound: vec![
PrimitiveType(BOOL_TYPE).into(),
PrimitiveType(INT32_TYPE).into(),
PrimitiveType(FLOAT_TYPE).into(),
],
});
assert_eq!(
resolve_call(
&ctx,
None,
"float",
create_tuple(vec![TypeVariable(v2).into()]),
&mut assumptions
),
Err("different domain".to_string())
);
}
#[test]
fn test_methods() {
let mut ctx = basic_ctx();
let mut assumptions = HashMap::new();
let v1 = Rc::new(TypeVariable(ctx.add_variable(VarDef {
name: "V1",
bound: vec![
PrimitiveType(INT32_TYPE).into(),
PrimitiveType(FLOAT_TYPE).into(),
],
})));
let v2 = Rc::new(TypeVariable(ctx.add_variable(VarDef {
name: "V2",
bound: vec![
PrimitiveType(INT32_TYPE).into(),
PrimitiveType(FLOAT_TYPE).into(),
],
})));
let v3 = Rc::new(TypeVariable(ctx.add_variable(VarDef {
name: "V3",
bound: vec![
PrimitiveType(BOOL_TYPE).into(),
PrimitiveType(INT32_TYPE).into(),
PrimitiveType(FLOAT_TYPE).into(),
],
})));
let int32 = Rc::new(PrimitiveType(INT32_TYPE));
let int64 = Rc::new(PrimitiveType(INT64_TYPE));
// simple cases
assert_eq!(
resolve_call(
&ctx,
Some(int32.clone()),
"__add__",
create_tuple(vec![int32.clone()]),
&mut assumptions
),
Ok(Some(int32.clone()))
);
assert_ne!(
resolve_call(
&ctx,
Some(int32.clone()),
"__add__",
create_tuple(vec![int32.clone()]),
&mut assumptions
),
Ok(Some(int64.clone()))
);
assert_eq!(
resolve_call(
&ctx,
Some(int32.clone()),
"__add__",
create_tuple(vec![int64.clone()]),
&mut assumptions
),
Err("not equal".to_string())
);
// with type variables
assert_eq!(
resolve_call(
&ctx,
Some(v1.clone()),
"__add__",
create_tuple(vec![v1.clone()]),
&mut assumptions
),
Ok(Some(v1.clone()))
);
assert_eq!(
resolve_call(
&ctx,
Some(v1.clone()),
"__add__",
create_tuple(vec![v2.clone()]),
&mut assumptions
),
Err("different domain".to_string())
);
assert_eq!(
resolve_call(
&ctx,
Some(v3.clone()),
"__add__",
create_tuple(vec![v1.clone()]),
&mut assumptions
),
Err("no such function".to_string())
);
assert_eq!(
resolve_call(
&ctx,
Some(v3.clone()),
"__add__",
create_tuple(vec![v3.clone()]),
&mut assumptions
),
Err("no such function".to_string())
);
}
}

View File

@ -1,6 +1,6 @@
extern crate rustpython_parser; extern crate rustpython_parser;
mod types; pub mod types;
mod inference; pub mod inference;
mod primitives; pub mod primitives;

View File

@ -13,7 +13,7 @@ pub const FLOAT_TYPE: PrimitiveId = PrimitiveId(3);
fn impl_math(def: &mut TypeDef, ty: &Rc<Type>) { fn impl_math(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType( let bin = Rc::new(ParametricType(
TUPLE_TYPE, TUPLE_TYPE,
vec![SelfType.into(), ty.clone()], vec![ty.clone()],
)); ));
let result = Some(ty.clone()); let result = Some(ty.clone());
let fun = FnDef { let fun = FnDef {
@ -39,7 +39,7 @@ fn impl_math(def: &mut TypeDef, ty: &Rc<Type>) {
fn impl_bits(def: &mut TypeDef, ty: &Rc<Type>) { fn impl_bits(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType( let bin = Rc::new(ParametricType(
TUPLE_TYPE, TUPLE_TYPE,
vec![SelfType.into(), PrimitiveType(INT32_TYPE).into()], vec![PrimitiveType(INT32_TYPE).into()],
)); ));
let result = Some(ty.clone()); let result = Some(ty.clone());
let fun = FnDef { let fun = FnDef {
@ -52,7 +52,7 @@ fn impl_bits(def: &mut TypeDef, ty: &Rc<Type>) {
def.methods.insert( def.methods.insert(
"__xor__", "__xor__",
FnDef { FnDef {
args: ParametricType(TUPLE_TYPE, vec![SelfType.into(), ty.clone()]).into(), args: ParametricType(TUPLE_TYPE, vec![ty.clone()]).into(),
result: Some(ty.clone()), result: Some(ty.clone()),
}, },
); );
@ -61,7 +61,7 @@ fn impl_bits(def: &mut TypeDef, ty: &Rc<Type>) {
fn impl_eq(def: &mut TypeDef, ty: &Rc<Type>) { fn impl_eq(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType( let bin = Rc::new(ParametricType(
TUPLE_TYPE, TUPLE_TYPE,
vec![SelfType.into(), ty.clone()], vec![ty.clone()],
)); ));
let fun = FnDef { let fun = FnDef {
args: bin.clone(), args: bin.clone(),
@ -75,7 +75,7 @@ fn impl_eq(def: &mut TypeDef, ty: &Rc<Type>) {
fn impl_order(def: &mut TypeDef, ty: &Rc<Type>) { fn impl_order(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType( let bin = Rc::new(ParametricType(
TUPLE_TYPE, TUPLE_TYPE,
vec![SelfType.into(), ty.clone()], vec![ty.clone()],
)); ));
let fun = FnDef { let fun = FnDef {
args: bin.clone(), args: bin.clone(),
@ -88,6 +88,10 @@ fn impl_order(def: &mut TypeDef, ty: &Rc<Type>) {
def.methods.insert("__ge__", fun.clone()); def.methods.insert("__ge__", fun.clone());
} }
pub fn create_tuple(tys: Vec<Rc<Type>>) -> Rc<Type> {
ParametricType(TUPLE_TYPE, tys).into()
}
pub fn basic_ctx() -> GlobalContext<'static> { pub fn basic_ctx() -> GlobalContext<'static> {
let primitives = [ let primitives = [
TypeDef { TypeDef {

View File

@ -26,6 +26,8 @@ pub enum Type {
#[derive(Clone)] #[derive(Clone)]
pub struct FnDef { pub struct FnDef {
// we assume methods first argument to be SelfType,
// so the first argument is not contained here
pub args: Rc<Type>, pub args: Rc<Type>,
pub result: Option<Rc<Type>>, pub result: Option<Rc<Type>>,
} }
@ -209,3 +211,4 @@ impl Type {
} }
} }
} }