fixed and enabled inference_core tests

This commit is contained in:
pca006132 2021-01-04 11:50:40 +08:00
parent 8ade8c7b1f
commit fa2fc1db54
1 changed files with 374 additions and 351 deletions

View File

@ -198,394 +198,417 @@ pub fn resolve_call(
resolve_call_rec(ctx, &None, obj, func, args) resolve_call_rec(ctx, &None, obj, func, args)
} }
// #[cfg(test)] #[cfg(test)]
// mod tests { mod tests {
// use super::*; use std::rc::Rc;
// use crate::primitives::*; use super::*;
use crate::context::TopLevelContext;
use crate::primitives::*;
// #[test] fn get_inference_context(ctx: TopLevelContext) -> InferenceContext {
// fn test_simple_generic() { InferenceContext::new(ctx, Box::new(|_| Err("unbounded identifier".into())))
// let mut ctx = basic_ctx(); }
// assert_eq!( #[test]
// resolve_call(&ctx, None, "int32", &[PrimitiveType(FLOAT_TYPE).into()]), fn test_simple_generic() {
// Ok(Some(PrimitiveType(INT32_TYPE).into())) let mut ctx = basic_ctx();
// ); let v1 = ctx.add_variable(VarDef {
name: "V1",
bound: vec![
ctx.get_primitive(INT32_TYPE),
ctx.get_primitive(FLOAT_TYPE),
],
});
let v1 = ctx.get_variable(v1);
let v2 = ctx.add_variable(VarDef {
name: "V2",
bound: vec![
ctx.get_primitive(BOOL_TYPE),
ctx.get_primitive(INT32_TYPE),
ctx.get_primitive(FLOAT_TYPE),
],
});
let v2 = ctx.get_variable(v2);
let ctx = get_inference_context(ctx);
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "int32", &[PrimitiveType(INT32_TYPE).into()],), resolve_call(&ctx, None, "int32", &[ctx.get_primitive(FLOAT_TYPE)]),
// Ok(Some(PrimitiveType(INT32_TYPE).into())) Ok(Some(ctx.get_primitive(INT32_TYPE).into()))
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "float", &[PrimitiveType(INT32_TYPE).into()]), resolve_call(&ctx, None, "int32", &[ctx.get_primitive(INT32_TYPE)],),
// Ok(Some(PrimitiveType(FLOAT_TYPE).into())) Ok(Some(ctx.get_primitive(INT32_TYPE).into()))
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "float", &[PrimitiveType(BOOL_TYPE).into()]), resolve_call(&ctx, None, "float", &[ctx.get_primitive(INT32_TYPE)]),
// Err("different domain".to_string()) Ok(Some(ctx.get_primitive(FLOAT_TYPE).into()))
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "float", &[]), resolve_call(&ctx, None, "float", &[ctx.get_primitive(BOOL_TYPE)]),
// Err("incorrect parameter number".to_string()) Err("different domain".to_string())
// ); );
// let v1 = ctx.add_variable(VarDef { assert_eq!(
// name: "V1", resolve_call(&ctx, None, "float", &[]),
// bound: vec![ Err("incorrect parameter number".to_string())
// PrimitiveType(INT32_TYPE).into(), );
// PrimitiveType(FLOAT_TYPE).into(),
// ],
// });
// assert_eq!(
// resolve_call(&ctx, None, "float", &[TypeVariable(v1).into()]),
// Ok(Some(PrimitiveType(FLOAT_TYPE).into()))
// );
// let v2 = ctx.add_variable(VarDef { assert_eq!(
// name: "V2", resolve_call(&ctx, None, "float", &[v1]),
// bound: vec![ Ok(Some(ctx.get_primitive(FLOAT_TYPE)))
// PrimitiveType(BOOL_TYPE).into(), );
// PrimitiveType(INT32_TYPE).into(),
// PrimitiveType(FLOAT_TYPE).into(),
// ],
// });
// assert_eq!(
// resolve_call(&ctx, None, "float", &[TypeVariable(v2).into()]),
// Err("different domain".to_string())
// );
// }
// #[test] assert_eq!(
// fn test_methods() { resolve_call(&ctx, None, "float", &[v2]),
// let mut ctx = basic_ctx(); Err("different domain".to_string())
);
}
// let v0 = Rc::new(TypeVariable(ctx.add_variable(VarDef { #[test]
// name: "V0", fn test_methods() {
// bound: vec![], let mut ctx = basic_ctx();
// })));
// 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 v0 = ctx.add_variable(VarDef {
// let int64 = Rc::new(PrimitiveType(INT64_TYPE)); name: "V0",
bound: vec![],
});
let v0 = ctx.get_variable(v0);
let v1 = ctx.add_variable(VarDef {
name: "V1",
bound: vec![
ctx.get_primitive(INT32_TYPE).into(),
ctx.get_primitive(FLOAT_TYPE).into(),
],
});
let v1 = ctx.get_variable(v1);
let v2 = ctx.add_variable(VarDef {
name: "V2",
bound: vec![
ctx.get_primitive(INT32_TYPE).into(),
ctx.get_primitive(FLOAT_TYPE).into(),
],
});
let v2 = ctx.get_variable(v2);
let v3 = ctx.add_variable(VarDef {
name: "V3",
bound: vec![
ctx.get_primitive(BOOL_TYPE).into(),
ctx.get_primitive(INT32_TYPE).into(),
ctx.get_primitive(FLOAT_TYPE).into(),
],
});
let v3 = ctx.get_variable(v3);
// // simple cases let int32 = ctx.get_primitive(INT32_TYPE);
// assert_eq!( let int64 = ctx.get_primitive(INT64_TYPE);
// resolve_call(&ctx, Some(int32.clone()), "__add__", &[int32.clone()]), let ctx = get_inference_context(ctx);
// Ok(Some(int32.clone()))
// );
// assert_ne!( // simple cases
// resolve_call(&ctx, Some(int32.clone()), "__add__", &[int32.clone()]), assert_eq!(
// Ok(Some(int64.clone())) resolve_call(&ctx, Some(int32.clone()), "__add__", &[int32.clone()]),
// ); Ok(Some(int32.clone()))
);
// assert_eq!( assert_ne!(
// resolve_call(&ctx, Some(int32.clone()), "__add__", &[int64.clone()]), resolve_call(&ctx, Some(int32.clone()), "__add__", &[int32.clone()]),
// Err("not equal".to_string()) Ok(Some(int64.clone()))
// ); );
// // with type variables assert_eq!(
// assert_eq!( resolve_call(&ctx, Some(int32.clone()), "__add__", &[int64.clone()]),
// resolve_call(&ctx, Some(v1.clone()), "__add__", &[v1.clone()]), Err("not equal".to_string())
// Ok(Some(v1.clone())) );
// );
// assert_eq!(
// resolve_call(&ctx, Some(v0.clone()), "__add__", &[v2.clone()]),
// Err("unbounded type var".to_string())
// );
// assert_eq!(
// resolve_call(&ctx, Some(v1.clone()), "__add__", &[v0.clone()]),
// Err("different domain".to_string())
// );
// assert_eq!(
// resolve_call(&ctx, Some(v1.clone()), "__add__", &[v2.clone()]),
// Err("different domain".to_string())
// );
// assert_eq!(
// resolve_call(&ctx, Some(v1.clone()), "__add__", &[v3.clone()]),
// Err("different domain".to_string())
// );
// assert_eq!(
// resolve_call(&ctx, Some(v3.clone()), "__add__", &[v1.clone()]),
// Err("no such function".to_string())
// );
// assert_eq!(
// resolve_call(&ctx, Some(v3.clone()), "__add__", &[v3.clone()]),
// Err("no such function".to_string())
// );
// }
// #[test] // with type variables
// fn test_multi_generic() { assert_eq!(
// let mut ctx = basic_ctx(); resolve_call(&ctx, Some(v1.clone()), "__add__", &[v1.clone()]),
// let v0 = Rc::new(TypeVariable(ctx.add_variable(VarDef { Ok(Some(v1.clone()))
// name: "V0", );
// bound: vec![], assert_eq!(
// }))); resolve_call(&ctx, Some(v0.clone()), "__add__", &[v2.clone()]),
// let v1 = Rc::new(TypeVariable(ctx.add_variable(VarDef { Err("unbounded type var".to_string())
// name: "V1", );
// bound: vec![], assert_eq!(
// }))); resolve_call(&ctx, Some(v1.clone()), "__add__", &[v0.clone()]),
// let v2 = Rc::new(TypeVariable(ctx.add_variable(VarDef { Err("different domain".to_string())
// name: "V2", );
// bound: vec![], assert_eq!(
// }))); resolve_call(&ctx, Some(v1.clone()), "__add__", &[v2.clone()]),
// let v3 = Rc::new(TypeVariable(ctx.add_variable(VarDef { Err("different domain".to_string())
// name: "V3", );
// bound: vec![], assert_eq!(
// }))); resolve_call(&ctx, Some(v1.clone()), "__add__", &[v3.clone()]),
Err("different domain".to_string())
);
assert_eq!(
resolve_call(&ctx, Some(v3.clone()), "__add__", &[v1.clone()]),
Err("no such function".to_string())
);
assert_eq!(
resolve_call(&ctx, Some(v3.clone()), "__add__", &[v3.clone()]),
Err("no such function".to_string())
);
}
// ctx.add_fn( #[test]
// "foo", fn test_multi_generic() {
// FnDef { let mut ctx = basic_ctx();
// args: vec![v0.clone(), v0.clone(), v1.clone()], let v0 = ctx.add_variable(VarDef {
// result: Some(v0.clone()), name: "V0",
// }, bound: vec![],
// ); });
let v0 = ctx.get_variable(v0);
let v1 = ctx.add_variable(VarDef {
name: "V1",
bound: vec![],
});
let v1 = ctx.get_variable(v1);
let v2 = ctx.add_variable(VarDef {
name: "V2",
bound: vec![],
});
let v2 = ctx.get_variable(v2);
let v3 = ctx.add_variable(VarDef {
name: "V3",
bound: vec![],
});
let v3 = ctx.get_variable(v3);
// ctx.add_fn( ctx.add_fn(
// "foo1", "foo",
// FnDef { FnDef {
// args: vec![ args: vec![v0.clone(), v0.clone(), v1.clone()],
// ParametricType(TUPLE_TYPE, vec![v0.clone(), v0.clone(), v1.clone()]).into(), result: Some(v0.clone()),
// ], },
// result: Some(v0.clone()), );
// },
// );
// assert_eq!( ctx.add_fn(
// resolve_call(&ctx, None, "foo", &[v2.clone(), v2.clone(), v2.clone()]), "foo1",
// Ok(Some(v2.clone())) FnDef {
// ); args: vec![
// assert_eq!( ParametricType(TUPLE_TYPE, vec![v0.clone(), v0.clone(), v1.clone()]).into(),
// resolve_call(&ctx, None, "foo", &[v2.clone(), v2.clone(), v3.clone()]), ],
// Ok(Some(v2.clone())) result: Some(v0.clone()),
// ); },
// assert_eq!( );
// resolve_call(&ctx, None, "foo", &[v2.clone(), v3.clone(), v3.clone()]), let ctx = get_inference_context(ctx);
// Err("different variables".to_string())
// );
// assert_eq!( assert_eq!(
// resolve_call( resolve_call(&ctx, None, "foo", &[v2.clone(), v2.clone(), v2.clone()]),
// &ctx, Ok(Some(v2.clone()))
// None, );
// "foo1", assert_eq!(
// &[ParametricType(TUPLE_TYPE, vec![v2.clone(), v2.clone(), v2.clone()]).into()] resolve_call(&ctx, None, "foo", &[v2.clone(), v2.clone(), v3.clone()]),
// ), Ok(Some(v2.clone()))
// Ok(Some(v2.clone())) );
// ); assert_eq!(
// assert_eq!( resolve_call(&ctx, None, "foo", &[v2.clone(), v3.clone(), v3.clone()]),
// resolve_call( Err("different variables".to_string())
// &ctx, );
// None,
// "foo1",
// &[ParametricType(TUPLE_TYPE, vec![v2.clone(), v2.clone(), v3.clone()]).into()]
// ),
// Ok(Some(v2.clone()))
// );
// assert_eq!(
// resolve_call(
// &ctx,
// None,
// "foo1",
// &[ParametricType(TUPLE_TYPE, vec![v2.clone(), v3.clone(), v3.clone()]).into()]
// ),
// Err("different variables".to_string())
// );
// }
// #[test] assert_eq!(
// fn test_class_generics() { resolve_call(
// let mut ctx = basic_ctx(); &ctx,
None,
"foo1",
&[ParametricType(TUPLE_TYPE, vec![v2.clone(), v2.clone(), v2.clone()]).into()]
),
Ok(Some(v2.clone()))
);
assert_eq!(
resolve_call(
&ctx,
None,
"foo1",
&[ParametricType(TUPLE_TYPE, vec![v2.clone(), v2.clone(), v3.clone()]).into()]
),
Ok(Some(v2.clone()))
);
assert_eq!(
resolve_call(
&ctx,
None,
"foo1",
&[ParametricType(TUPLE_TYPE, vec![v2.clone(), v3.clone(), v3.clone()]).into()]
),
Err("different variables".to_string())
);
}
// let list = ctx.get_parametric_mut(LIST_TYPE); #[test]
// let t = Rc::new(TypeVariable(list.params[0])); fn test_class_generics() {
// list.base.methods.insert( let mut ctx = basic_ctx();
// "head",
// FnDef {
// args: vec![],
// result: Some(t.clone()),
// },
// );
// list.base.methods.insert(
// "append",
// FnDef {
// args: vec![t.clone()],
// result: None,
// },
// );
// let v0 = Rc::new(TypeVariable(ctx.add_variable(VarDef { let list = ctx.get_parametric_def_mut(LIST_TYPE);
// name: "V0", let t = Rc::new(TypeVariable(list.params[0]));
// bound: vec![], list.base.methods.insert(
// }))); "head",
// let v1 = Rc::new(TypeVariable(ctx.add_variable(VarDef { FnDef {
// name: "V1", args: vec![],
// bound: vec![], result: Some(t.clone()),
// }))); },
);
list.base.methods.insert(
"append",
FnDef {
args: vec![t.clone()],
result: None,
},
);
// assert_eq!( let v0 = ctx.add_variable(VarDef {
// resolve_call( name: "V0",
// &ctx, bound: vec![],
// Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()), });
// "head", let v0 = ctx.get_variable(v0);
// &[] let v1 = ctx.add_variable(VarDef {
// ), name: "V1",
// Ok(Some(v0.clone())) bound: vec![],
// ); });
// assert_eq!( let v1 = ctx.get_variable(v1);
// resolve_call( let ctx = get_inference_context(ctx);
// &ctx,
// Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
// "append",
// &[v0.clone()]
// ),
// Ok(None)
// );
// assert_eq!(
// resolve_call(
// &ctx,
// Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
// "append",
// &[v1.clone()]
// ),
// Err("different variables".to_string())
// );
// }
// #[test] assert_eq!(
// fn test_virtual_class() { resolve_call(
// let mut ctx = basic_ctx(); &ctx,
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
"head",
&[]
),
Ok(Some(v0.clone()))
);
assert_eq!(
resolve_call(
&ctx,
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
"append",
&[v0.clone()]
),
Ok(None)
);
assert_eq!(
resolve_call(
&ctx,
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
"append",
&[v1.clone()]
),
Err("different variables".to_string())
);
}
// let foo = ctx.add_class(ClassDef { #[test]
// base: TypeDef { fn test_virtual_class() {
// name: "Foo", let mut ctx = basic_ctx();
// methods: HashMap::new(),
// fields: HashMap::new(),
// },
// parents: vec![],
// });
// let foo1 = ctx.add_class(ClassDef { let foo = ctx.add_class(ClassDef {
// base: TypeDef { base: TypeDef {
// name: "Foo1", name: "Foo",
// methods: HashMap::new(), methods: HashMap::new(),
// fields: HashMap::new(), fields: HashMap::new(),
// }, },
// parents: vec![foo], parents: vec![],
// }); });
// let foo2 = ctx.add_class(ClassDef { let foo1 = ctx.add_class(ClassDef {
// base: TypeDef { base: TypeDef {
// name: "Foo2", name: "Foo1",
// methods: HashMap::new(), methods: HashMap::new(),
// fields: HashMap::new(), fields: HashMap::new(),
// }, },
// parents: vec![foo1], parents: vec![foo],
// }); });
// let bar = ctx.add_class(ClassDef { let foo2 = ctx.add_class(ClassDef {
// base: TypeDef { base: TypeDef {
// name: "bar", name: "Foo2",
// methods: HashMap::new(), methods: HashMap::new(),
// fields: HashMap::new(), fields: HashMap::new(),
// }, },
// parents: vec![], parents: vec![foo1],
// }); });
// ctx.add_fn( let bar = ctx.add_class(ClassDef {
// "foo", base: TypeDef {
// FnDef { name: "bar",
// args: vec![VirtualClassType(foo).into()], methods: HashMap::new(),
// result: None, fields: HashMap::new(),
// }, },
// ); parents: vec![],
// ctx.add_fn( });
// "foo1",
// FnDef {
// args: vec![VirtualClassType(foo1).into()],
// result: None,
// },
// );
// assert_eq!( ctx.add_fn(
// resolve_call(&ctx, None, "foo", &[ClassType(foo).into()]), "foo",
// Ok(None) FnDef {
// ); args: vec![VirtualClassType(foo).into()],
result: None,
},
);
ctx.add_fn(
"foo1",
FnDef {
args: vec![VirtualClassType(foo1).into()],
result: None,
},
);
let ctx = get_inference_context(ctx);
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo", &[ClassType(foo1).into()]), resolve_call(&ctx, None, "foo", &[ClassType(foo).into()]),
// Ok(None) Ok(None)
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo", &[ClassType(foo2).into()]), resolve_call(&ctx, None, "foo", &[ClassType(foo1).into()]),
// Ok(None) Ok(None)
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo", &[ClassType(bar).into()]), resolve_call(&ctx, None, "foo", &[ClassType(foo2).into()]),
// Err("not subtype".to_string()) Ok(None)
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo1", &[ClassType(foo1).into()]), resolve_call(&ctx, None, "foo", &[ClassType(bar).into()]),
// Ok(None) Err("not subtype".to_string())
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo1", &[ClassType(foo2).into()]), resolve_call(&ctx, None, "foo1", &[ClassType(foo1).into()]),
// Ok(None) Ok(None)
// ); );
// assert_eq!( assert_eq!(
// resolve_call(&ctx, None, "foo1", &[ClassType(foo).into()]), resolve_call(&ctx, None, "foo1", &[ClassType(foo2).into()]),
// Err("not subtype".to_string()) Ok(None)
// ); );
// // virtual class substitution assert_eq!(
// assert_eq!( resolve_call(&ctx, None, "foo1", &[ClassType(foo).into()]),
// resolve_call(&ctx, None, "foo", &[VirtualClassType(foo).into()]), Err("not subtype".to_string())
// Ok(None) );
// );
// assert_eq!( // virtual class substitution
// resolve_call(&ctx, None, "foo", &[VirtualClassType(foo1).into()]), assert_eq!(
// Ok(None) resolve_call(&ctx, None, "foo", &[VirtualClassType(foo).into()]),
// ); Ok(None)
// assert_eq!( );
// resolve_call(&ctx, None, "foo", &[VirtualClassType(foo2).into()]), assert_eq!(
// Ok(None) resolve_call(&ctx, None, "foo", &[VirtualClassType(foo1).into()]),
// ); Ok(None)
// assert_eq!( );
// resolve_call(&ctx, None, "foo", &[VirtualClassType(bar).into()]), assert_eq!(
// Err("not subtype".to_string()) resolve_call(&ctx, None, "foo", &[VirtualClassType(foo2).into()]),
// ); Ok(None)
// } );
// } assert_eq!(
resolve_call(&ctx, None, "foo", &[VirtualClassType(bar).into()]),
Err("not subtype".to_string())
);
}
}