From 929b7e1d92964545a7ddf30566c5de93a0741c54 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 28 Dec 2020 14:33:18 +0800 Subject: [PATCH] inference and tests --- nac3type/src/inference.rs | 205 +++++++++++++++++++++++++++++++++++++ nac3type/src/lib.rs | 6 +- nac3type/src/primitives.rs | 14 ++- nac3type/src/types.rs | 3 + 4 files changed, 220 insertions(+), 8 deletions(-) diff --git a/nac3type/src/inference.rs b/nac3type/src/inference.rs index 6cdc28a06b..c7f89ce58e 100644 --- a/nac3type/src/inference.rs +++ b/nac3type/src/inference.rs @@ -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()) + ); + + } +} + diff --git a/nac3type/src/lib.rs b/nac3type/src/lib.rs index a3df4ca59b..a62c270738 100644 --- a/nac3type/src/lib.rs +++ b/nac3type/src/lib.rs @@ -1,6 +1,6 @@ extern crate rustpython_parser; -mod types; -mod inference; -mod primitives; +pub mod types; +pub mod inference; +pub mod primitives; diff --git a/nac3type/src/primitives.rs b/nac3type/src/primitives.rs index 321088cb37..4159b3aecd 100644 --- a/nac3type/src/primitives.rs +++ b/nac3type/src/primitives.rs @@ -13,7 +13,7 @@ pub const FLOAT_TYPE: PrimitiveId = PrimitiveId(3); fn impl_math(def: &mut TypeDef, ty: &Rc) { let bin = Rc::new(ParametricType( TUPLE_TYPE, - vec![SelfType.into(), ty.clone()], + vec![ty.clone()], )); let result = Some(ty.clone()); let fun = FnDef { @@ -39,7 +39,7 @@ fn impl_math(def: &mut TypeDef, ty: &Rc) { fn impl_bits(def: &mut TypeDef, ty: &Rc) { let bin = Rc::new(ParametricType( TUPLE_TYPE, - vec![SelfType.into(), PrimitiveType(INT32_TYPE).into()], + vec![PrimitiveType(INT32_TYPE).into()], )); let result = Some(ty.clone()); let fun = FnDef { @@ -52,7 +52,7 @@ fn impl_bits(def: &mut TypeDef, ty: &Rc) { def.methods.insert( "__xor__", FnDef { - args: ParametricType(TUPLE_TYPE, vec![SelfType.into(), ty.clone()]).into(), + args: ParametricType(TUPLE_TYPE, vec![ty.clone()]).into(), result: Some(ty.clone()), }, ); @@ -61,7 +61,7 @@ fn impl_bits(def: &mut TypeDef, ty: &Rc) { fn impl_eq(def: &mut TypeDef, ty: &Rc) { let bin = Rc::new(ParametricType( TUPLE_TYPE, - vec![SelfType.into(), ty.clone()], + vec![ty.clone()], )); let fun = FnDef { args: bin.clone(), @@ -75,7 +75,7 @@ fn impl_eq(def: &mut TypeDef, ty: &Rc) { fn impl_order(def: &mut TypeDef, ty: &Rc) { let bin = Rc::new(ParametricType( TUPLE_TYPE, - vec![SelfType.into(), ty.clone()], + vec![ty.clone()], )); let fun = FnDef { args: bin.clone(), @@ -88,6 +88,10 @@ fn impl_order(def: &mut TypeDef, ty: &Rc) { def.methods.insert("__ge__", fun.clone()); } +pub fn create_tuple(tys: Vec>) -> Rc { + ParametricType(TUPLE_TYPE, tys).into() +} + pub fn basic_ctx() -> GlobalContext<'static> { let primitives = [ TypeDef { diff --git a/nac3type/src/types.rs b/nac3type/src/types.rs index 8828439be6..586507d8ca 100644 --- a/nac3type/src/types.rs +++ b/nac3type/src/types.rs @@ -26,6 +26,8 @@ pub enum Type { #[derive(Clone)] pub struct FnDef { + // we assume methods first argument to be SelfType, + // so the first argument is not contained here pub args: Rc, pub result: Option>, } @@ -209,3 +211,4 @@ impl Type { } } } +