forked from M-Labs/nac3
virtual class tests
This commit is contained in:
parent
87dd0ee3cb
commit
75183c39fd
@ -77,8 +77,7 @@ fn find_subst(
|
||||
parents = [*id_a].to_vec();
|
||||
}
|
||||
VirtualClassType(id_a) => {
|
||||
let a = ctx.get_class(*id_a);
|
||||
parents = a.parents.clone();
|
||||
parents = [*id_a].to_vec();
|
||||
}
|
||||
_ => {
|
||||
return Err("cannot substitute non-class type into virtual class".to_string());
|
||||
@ -486,4 +485,232 @@ mod tests {
|
||||
Err("different variables".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_class_generics() {
|
||||
let mut ctx = basic_ctx();
|
||||
let mut assumptions = HashMap::new();
|
||||
|
||||
let list = ctx.get_parametric_mut(LIST_TYPE);
|
||||
let t = Rc::new(TypeVariable(list.params[0]));
|
||||
list.base.methods.insert("head", FnDef {
|
||||
args: create_tuple(vec![]),
|
||||
result: Some(t.clone())
|
||||
});
|
||||
list.base.methods.insert("append", FnDef {
|
||||
args: create_tuple(vec![t.clone()]),
|
||||
result: None
|
||||
});
|
||||
|
||||
let v0 = Rc::new(TypeVariable(ctx.add_variable(VarDef {
|
||||
name: "V0",
|
||||
bound: vec![],
|
||||
})));
|
||||
let v1 = Rc::new(TypeVariable(ctx.add_variable(VarDef {
|
||||
name: "V1",
|
||||
bound: vec![],
|
||||
})));
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
|
||||
"head",
|
||||
create_tuple(vec![]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(Some(v0.clone()))
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
|
||||
"append",
|
||||
create_tuple(vec![v0.clone()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
Some(ParametricType(LIST_TYPE, vec![v0.clone()]).into()),
|
||||
"append",
|
||||
create_tuple(vec![v1.clone()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Err("different variables".to_string())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtual_class() {
|
||||
let mut ctx = basic_ctx();
|
||||
let mut assumptions = HashMap::new();
|
||||
|
||||
let foo = ctx.add_class(ClassDef {
|
||||
base: TypeDef {
|
||||
name: "Foo",
|
||||
methods: HashMap::new(),
|
||||
fields: HashMap::new()
|
||||
},
|
||||
parents: vec![]
|
||||
});
|
||||
|
||||
let foo1 = ctx.add_class(ClassDef {
|
||||
base: TypeDef {
|
||||
name: "Foo1",
|
||||
methods: HashMap::new(),
|
||||
fields: HashMap::new()
|
||||
},
|
||||
parents: vec![foo]
|
||||
});
|
||||
|
||||
let foo2 = ctx.add_class(ClassDef {
|
||||
base: TypeDef {
|
||||
name: "Foo2",
|
||||
methods: HashMap::new(),
|
||||
fields: HashMap::new()
|
||||
},
|
||||
parents: vec![foo1]
|
||||
});
|
||||
|
||||
let bar = ctx.add_class(ClassDef {
|
||||
base: TypeDef {
|
||||
name: "bar",
|
||||
methods: HashMap::new(),
|
||||
fields: HashMap::new()
|
||||
},
|
||||
parents: vec![]
|
||||
});
|
||||
|
||||
ctx.add_fn("foo", FnDef {
|
||||
args: create_tuple(vec![VirtualClassType(foo).into()]),
|
||||
result: None
|
||||
});
|
||||
ctx.add_fn("foo1", FnDef {
|
||||
args: create_tuple(vec![VirtualClassType(foo1).into()]),
|
||||
result: None
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![ClassType(foo).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![ClassType(foo1).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![ClassType(foo2).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![ClassType(bar).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Err("not subtype".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo1",
|
||||
create_tuple(vec![ClassType(foo1).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo1",
|
||||
create_tuple(vec![ClassType(foo2).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo1",
|
||||
create_tuple(vec![ClassType(foo).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Err("not subtype".to_string())
|
||||
);
|
||||
|
||||
// virtual class substitution
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![VirtualClassType(foo).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![VirtualClassType(foo1).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![VirtualClassType(foo2).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Ok(None)
|
||||
);
|
||||
assert_eq!(
|
||||
resolve_call(
|
||||
&ctx,
|
||||
None,
|
||||
"foo",
|
||||
create_tuple(vec![VirtualClassType(bar).into()]),
|
||||
&mut assumptions
|
||||
),
|
||||
Err("not subtype".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user