forked from M-Labs/nac3
inference and tests
This commit is contained in:
parent
7f09596bcb
commit
929b7e1d92
@ -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())
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user