From a138115c78ae59e8a5fc7bc2894a296fbc4e10de Mon Sep 17 00:00:00 2001 From: myuon Date: Tue, 14 Nov 2023 23:29:43 +0900 Subject: [PATCH 1/8] test: add a test --- tests/cases/closures/test11.qz | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/cases/closures/test11.qz diff --git a/tests/cases/closures/test11.qz b/tests/cases/closures/test11.qz new file mode 100644 index 00000000..6e29187b --- /dev/null +++ b/tests/cases/closures/test11.qz @@ -0,0 +1,43 @@ +fun js_fetch(url: string, call: fun[(i32), nil]) { + call(10); +} + +fun js_image_set_onload(image: any, call: fun[(), nil]) { + call(); +} + +fun js_image_set_onerror(image: any, call: fun[(), nil]) { + call(); +} + +fun js_context_draw_image(context: any, image: any, x: i32, y: i32) { + debug(context); + debug(image); + debug(x); + debug(y); +} + +fun main() { + let rhb = 200; + let context = "context"; + let image = "image"; + + js_fetch( + "assets/rhb.json", + fun (resp_id: i32) { + js_image_set_onload( + rhb, + fun () { + js_context_draw_image(context, rhb, 0, 0); + }, + ); + js_image_set_onerror( + image, + fun () { + panic("Image failed to load"); + }, + ); + }, + ); +} + From 86c54dc6c5fba607b0714823c1e50131944da6ae Mon Sep 17 00:00:00 2001 From: myuon Date: Sat, 18 Nov 2023 19:08:44 +0900 Subject: [PATCH 2/8] fix: indent for to_string_pretty --- quartz/std.qz | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/quartz/std.qz b/quartz/std.qz index 3e0a8a52..ec107388 100644 --- a/quartz/std.qz +++ b/quartz/std.qz @@ -1512,6 +1512,11 @@ module derive { indent = " ".repeat(depth * 4); } + let indent_prev = " "; + if pretty { + indent_prev = " ".repeat((depth - 1) * 4); + } + let rep = reflection::get_type_rep(t); if rep.name.equal("string") { return format(`"{}"`, t as string); @@ -1573,9 +1578,14 @@ module derive { let tag_name = rep.fields.at(tag); let v = (t as ptr[any]).at(1); - s = s.concat(format(" {}: {} }", tag_name, derive::to_string_internal(v, pretty, depth + 1))); + s = s.concat(format( + "{}{}: {}", + indent, + tag_name, + derive::to_string_internal(v, pretty, depth + 1), + )); - return s; + return s.concat("{}{}}".format(sep, indent_prev)); } let s = format("{} {{}", rep.name, sep); @@ -1589,7 +1599,7 @@ module derive { s = s.concat(format("{}{}: {}", indent, f, derive::to_string_internal(v, pretty, depth + 1))); } - return s.concat(" }"); + return s.concat("{}{}}".format(sep, indent_prev)); } fun to_string(t: any): string { From f86ddb907def52ccbd5e71248ad7f4ac4dca53e7 Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 15:14:58 +0900 Subject: [PATCH 3/8] fix: restore captured in typecheck with env map --- quartz/typecheck.qz | 49 ++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/quartz/typecheck.qz b/quartz/typecheck.qz index 5d5db99c..e473ba39 100644 --- a/quartz/typecheck.qz +++ b/quartz/typecheck.qz @@ -37,6 +37,7 @@ struct Typechecker { }], current_function_name: string?, captured: vec[string], + env: map[string, LType], } module Typechecker { @@ -370,6 +371,7 @@ module Typechecker { }]](), current_function_name: nil, captured: make[vec[string]](), + env: make[map[string, LType]](), }; } @@ -642,12 +644,10 @@ module Typechecker { return _ or error::new(format("unimplemented: decl, {}", d.to_string())); } - fun function(self, f: Function, locals_init: map[string, LType]): Type or error { - let locals = self.locals; + fun function(self, f: Function, env: map[string, LType]): Type or error { + let prev_locals = self.locals; self.locals = make[map[string, LType]](); - for k in locals_init.list_keys() { - self.locals.insert(k, locals_init.(k)); - } + self.env = env; self.captured = make[vec[string]](); @@ -678,28 +678,8 @@ module Typechecker { self.result_type = f.result_type?; self.block(f.body).try; - let captured_local = make[map[string, bool]](); - for c in self.captured { - captured_local.insert(c, true); - } - for p in f.params { - captured_local.insert(p.name, false); - } - for l in self.locals.list_keys() { - if !locals_init.has(l) { - captured_local.insert(l, false); - } - } - - self.captured = make[vec[string]](); - for c in captured_local.list_keys() { - if captured_local.(c) { - self.captured.push(c); - } - } - - self.locals = locals; self.current_function_name = nil; + self.locals = prev_locals; let ps = make[vec[Type]](); for param in f.params { @@ -1049,7 +1029,6 @@ module Typechecker { return _ or error::new("unimplemented: binop, {}".format(expr.to_string())); } else if expr.t_ident != nil { if self.locals.has(expr.t_ident!.name) { - self.captured.push(expr.t_ident!.name); let t = self.locals.at(expr.t_ident!.name); self.set_search_node_type(t.data, lexpr.location); self.set_search_node_definition(self.current_path, t.location, lexpr.location); @@ -1057,6 +1036,15 @@ module Typechecker { return t.data; } + if self.env.has(expr.t_ident!.name) { + self.captured.push(expr.t_ident!.name); + let t = self.env.at(expr.t_ident!.name); + self.set_search_node_type(t.data, lexpr.location); + self.set_search_node_definition(self.current_path, t.location, lexpr.location); + self.set_completion(t.data, lexpr.location).try; + + return t.data; + } let result or _err = self.resolve_path(Path::new(expr.t_ident!.name)); if result != nil { @@ -1782,9 +1770,10 @@ module Typechecker { lexpr.location.start!.to_string(), ); - let prev = self.current_function_name; + let prev_name = self.current_function_name; + let prev_captured = self.captured; let func_type = self.function(expr.t_closure!.func, self.locals).try; - self.current_function_name = prev; + self.current_function_name = prev_name; let captures = make[vec[struct { name: string, @@ -1798,6 +1787,8 @@ module Typechecker { } expr.t_closure!.captures = captures; + self.captured = prev_captured; + return Type { t_closure: struct { params: func_type.t_func!.params, From 1e4d8dbcdc3f1efe96343cddd60aead5e7febf66 Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 15:21:26 +0900 Subject: [PATCH 4/8] test: fix --- tests/cases/closures/test4.qz | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/closures/test4.qz b/tests/cases/closures/test4.qz index 89fddf24..bb872e17 100644 --- a/tests/cases/closures/test4.qz +++ b/tests/cases/closures/test4.qz @@ -3,7 +3,6 @@ fun main() { let outer = fun () { let x = "outer"; let inner = fun () { - let x = "inner"; println(x); }; inner(); From 9816837f723ba1b0bb1cfebe243bfd41f9c75f7c Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 15:59:02 +0900 Subject: [PATCH 5/8] fix: lookup self.env --- quartz/typecheck.qz | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/quartz/typecheck.qz b/quartz/typecheck.qz index e473ba39..83f8c3f8 100644 --- a/quartz/typecheck.qz +++ b/quartz/typecheck.qz @@ -529,7 +529,7 @@ module Typechecker { }, ); - self.function(d.t_func!, make[map[string, LType]]()).try; + self.function(d.t_func!).try; self.globals.insert( self.path_to(d.t_func!.name.data), @@ -644,10 +644,13 @@ module Typechecker { return _ or error::new(format("unimplemented: decl, {}", d.to_string())); } - fun function(self, f: Function, env: map[string, LType]): Type or error { + fun function(self, f: Function): Type or error { let prev_locals = self.locals; + let prev_env = self.env; + for l in self.locals.list_keys() { + self.env.insert(l, self.locals.at(l)); + } self.locals = make[map[string, LType]](); - self.env = env; self.captured = make[vec[string]](); @@ -680,6 +683,7 @@ module Typechecker { self.current_function_name = nil; self.locals = prev_locals; + self.env = prev_env; let ps = make[vec[Type]](); for param in f.params { @@ -1772,7 +1776,7 @@ module Typechecker { let prev_name = self.current_function_name; let prev_captured = self.captured; - let func_type = self.function(expr.t_closure!.func, self.locals).try; + let func_type = self.function(expr.t_closure!.func).try; self.current_function_name = prev_name; let captures = make[vec[struct { @@ -1782,7 +1786,7 @@ module Typechecker { for c in self.captured { captures.push(struct { name: c, - type_: self.locals.(c).data, + type_: self.env.(c).data, }); } expr.t_closure!.captures = captures; From 2c101712d743affce3df2793623429a0ddf8fbd2 Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 16:02:25 +0900 Subject: [PATCH 6/8] fix: merge with prev_captured --- quartz/typecheck.qz | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quartz/typecheck.qz b/quartz/typecheck.qz index 83f8c3f8..31c3c342 100644 --- a/quartz/typecheck.qz +++ b/quartz/typecheck.qz @@ -1791,7 +1791,10 @@ module Typechecker { } expr.t_closure!.captures = captures; - self.captured = prev_captured; + // merge with previous captures + for p in prev_captured { + self.captured.push(p); + } return Type { t_closure: struct { From 062fcbad3c25140db90e09c2d3e46e424d05bcc4 Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 16:05:05 +0900 Subject: [PATCH 7/8] test: fix --- tests/cases/closures/test10.qz | 9 ++++++--- tests/cases/closures/test10.stdout | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/cases/closures/test10.stdout diff --git a/tests/cases/closures/test10.qz b/tests/cases/closures/test10.qz index 0d8b39e0..8d994eae 100644 --- a/tests/cases/closures/test10.qz +++ b/tests/cases/closures/test10.qz @@ -1,5 +1,6 @@ -fun f(a: i32, p: any) { +fun f(a: i32, p: fun[(i32), nil]) { println("{}", a.to_string()); + p(7); } fun main() { @@ -10,11 +11,13 @@ fun main() { fun (resp_id: i32) { f( a, - fun () { - panic("Image failed to load"); + fun (arg: i32) { + println("called with {}", arg.to_string()); }, ); }, ); + + println("ok"); } diff --git a/tests/cases/closures/test10.stdout b/tests/cases/closures/test10.stdout new file mode 100644 index 00000000..854cc68f --- /dev/null +++ b/tests/cases/closures/test10.stdout @@ -0,0 +1,4 @@ +5 +10 +called with 7 +ok From 063e3899fb3f34653b9797eabec7c2dc58777f10 Mon Sep 17 00:00:00 2001 From: myuon Date: Thu, 23 Nov 2023 16:07:24 +0900 Subject: [PATCH 8/8] test: fix --- tests/cases/closures/test11.qz | 14 ++++++++------ tests/cases/closures/test11.stdout | 6 ++++++ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 tests/cases/closures/test11.stdout diff --git a/tests/cases/closures/test11.qz b/tests/cases/closures/test11.qz index 6e29187b..76a9a3b4 100644 --- a/tests/cases/closures/test11.qz +++ b/tests/cases/closures/test11.qz @@ -10,11 +10,11 @@ fun js_image_set_onerror(image: any, call: fun[(), nil]) { call(); } -fun js_context_draw_image(context: any, image: any, x: i32, y: i32) { - debug(context); - debug(image); - debug(x); - debug(y); +fun js_context_draw_image(context: string, image: i32, x: i32, y: i32) { + println(context); + println("{}", image.to_string()); + println("{}", x.to_string()); + println("{}", y.to_string()); } fun main() { @@ -34,10 +34,12 @@ fun main() { js_image_set_onerror( image, fun () { - panic("Image failed to load"); + println("Image failed to load"); }, ); }, ); + + println("ok"); } diff --git a/tests/cases/closures/test11.stdout b/tests/cases/closures/test11.stdout new file mode 100644 index 00000000..99cbd813 --- /dev/null +++ b/tests/cases/closures/test11.stdout @@ -0,0 +1,6 @@ +context +200 +0 +0 +Image failed to load +ok