feat: call with default bindings (#671)

This commit is contained in:
Myriad-Dreamin 2024-10-14 13:06:11 +08:00 committed by GitHub
parent e9ec60d2b5
commit 28f2645c40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 103 additions and 5 deletions

View file

@ -375,6 +375,7 @@ impl<'a, 'w> TypeChecker<'a, 'w> {
let mut pos = vec![];
let mut named = BTreeMap::new();
let mut defaults = BTreeMap::new();
let mut rest = None;
for param in closure.params().children() {
@ -389,6 +390,7 @@ impl<'a, 'w> TypeChecker<'a, 'w> {
// optimize it, so I put a todo here.
self.constrain(&exp, &v);
named.insert(e.name().into(), v);
defaults.insert(e.name().into(), exp);
}
// todo: spread left/right
ast::Param::Spread(a) => {
@ -418,8 +420,18 @@ impl<'a, 'w> TypeChecker<'a, 'w> {
self.weaken(rest);
}
let sig = SigTy::new(pos, named, rest, Some(body));
Some(Ty::Func(sig.into()))
let sig = SigTy::new(pos, named, rest, Some(body)).into();
let sig = Ty::Func(sig);
if defaults.is_empty() {
return Some(sig);
}
let defaults: Vec<(Interned<str>, Ty)> = defaults.into_iter().collect();
let with_defaults = SigWithTy {
sig: sig.into(),
with: ArgsTy::new(vec![], defaults, None, None).into(),
};
Some(Ty::With(with_defaults.into()))
}
fn check_let(&mut self, root: LinkedNode<'_>) -> Option<Ty> {

View file

@ -0,0 +1,2 @@
#let foo(d: 3) = d
#let x = foo()

View file

@ -0,0 +1,3 @@
#let val = 1
#let foo(a: val) = a
#let x = foo()

View file

@ -0,0 +1,5 @@
#let fun() = {
return 2
}
#let foo(b: fun()) = b
#let x = foo()

View file

@ -0,0 +1,4 @@
#let dict = (x: 3)
#let foo(c: dict.x) = c
#let x = foo()

View file

@ -5,7 +5,7 @@ input_file: crates/tinymist-query/src/fixtures/type_check/confusing-name.typ
---
"date" = Any
"info" = Any
"master-cover" = (Any, "x": Any) => TypeBinary { operands: (Any, TypeBinary { operands: ({"submit-date": 0}, Any), op: Add }), op: Assign }
"master-cover" = ((Any, "x": Any) => TypeBinary { operands: (Any, TypeBinary { operands: ({"submit-date": 0}, Any), op: Add }), op: Assign }).with(..("x": (Any) => Any) => any)
"x" = (Any) => Any
"x" = Any
---

View file

@ -4,7 +4,7 @@ expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/external.typ
---
"bad-instantiate" = Any
"prefix" = ("title": ( ⪯ Any)) => TypeBinary { operands: (TypeBinary { operands: (TypeBinary { operands: (Any, Infer), op: Add }, Infer), op: Add }, Infer), op: Add }
"prefix" = (("title": ( ⪯ Any)) => TypeBinary { operands: (TypeBinary { operands: (TypeBinary { operands: (Any, Infer), op: Add }, Infer), op: Add }, Infer), op: Add }).with(..("title": None) => any)
"title" = None
---
27..33 -> @prefix

View file

@ -0,0 +1,15 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/fn_named.typ
---
"d" = ( ⪰ 3 | Type(integer))
"foo" = (("d": Any) => Any).with(..("d": 3) => any)
"x" = 3
---
5..8 -> @foo
9..10 -> @d
17..18 -> @d
24..25 -> @x
28..31 -> (Any | @foo)
28..33 -> 3

View file

@ -0,0 +1,18 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/fn_named2.typ
---
"a" = Any
"foo" = (("a": Any) => Any).with(..("a": 1) => any)
"val" = 1
"x" = Any
---
5..8 -> @val
18..21 -> @foo
22..23 -> @a
25..28 -> @val
32..33 -> @a
39..40 -> @x
43..46 -> (Any | @foo)
43..48 -> @val

View file

@ -0,0 +1,19 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/fn_named3.typ
---
"b" = ( ⪰ None | None)
"foo" = (("b": Any) => Any).with(..("b": None) => any)
"fun" = () => None
"x" = None
---
5..8 -> @fun
33..36 -> @foo
37..38 -> @b
40..43 -> (@fun | () => None)
40..45 -> None
49..50 -> @b
56..57 -> @x
60..63 -> (Any | @foo)
60..65 -> None

View file

@ -0,0 +1,18 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: result
input_file: crates/tinymist-query/src/fixtures/type_check/fn_named4.typ
---
"c" = ( ⪰ (3 | {"x": 3}.x) | (3 | {"x": 3}.x))
"dict" = {"x": 3}
"foo" = (("c": Any) => Any).with(..("c": (3 | {"x": 3}.x)) => any)
"x" = (3 | {"x": 3}.x)
---
5..9 -> @dict
24..27 -> @foo
28..29 -> @c
31..35 -> (@dict | {"x": 3})
41..42 -> @c
48..49 -> @x
52..55 -> (Any | @foo)
52..57 -> (3 | @v"dict".x)

View file

@ -7,7 +7,7 @@ input_file: crates/tinymist-query/src/fixtures/type_check/sig_template_set.typ
"class" = ( ⪰ "article" | "article" | "letter" | "article" | "letter")
"content" = Any
"font" = None
"tmpl" = (Any, "authors": ( ⪯ (Type(array) | Type(string))), "class": Any, "font": ( ⪯ (TextFont | Array<TextFont>))) => Any
"tmpl" = ((Any, "authors": ( ⪯ (Type(array) | Type(string))), "class": Any, "font": ( ⪯ (TextFont | Array<TextFont>))) => Any).with(..("authors": (), "class": "article", "font": None) => any)
---
5..9 -> @tmpl
10..17 -> @content

View file

@ -7,6 +7,7 @@ impl<'a> Sig<'a> {
pol: bool,
ctx: &mut impl TyCtxMut,
) -> Option<Ty> {
log::debug!("call {self:?} {args:?} {pol:?}");
ctx.with_scope(|ctx| {
let body = self.check_bind(args, ctx)?;
@ -24,6 +25,7 @@ impl<'a> Sig<'a> {
for (arg_recv, arg_ins) in sig.matches(args, withs) {
if let Ty::Var(arg_recv) = arg_recv {
log::debug!("bind {arg_recv:?} {arg_ins:?}");
ctx.bind_local(arg_recv, arg_ins.clone());
}
}