nandi/rustnimpublic Fork
⑂ 64cb049
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Call a value that holds a function

`(self.map)(o)` is how winnow's combinators invoke the closure they were
built with, and rustnim accepted only a named function in call position. Nim
calls a proc-typed value with the same syntax, so all this needed was the
callee's type -- and a refusal that says what it found rather than what it
wanted, for anything that is not one.

tests/cases/061.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-19T19:29:03-07:00 Browse files
64cb049 parent: 670d6a7
modified src/lower.rs +19 -1
@@ -6098,7 +6098,25 @@ impl Lowerer {
60986098
60996099 fn call(&mut self, c: &syn::ExprCall, expect: Option<&Nim>) -> Result<Val, String> {
61006100 let Expr::Path(p) = &*c.func else {
6101- return Err("only calls to named functions are supported".into());
6101+ // `(self.map)(o)` -- calling something that holds a proc. Nim
6102+ // calls a proc-typed value with the same syntax, so this needs
6103+ // only the callee's type to confirm that is what it is.
6104+ let f = self.expr(&c.func)?;
6105+ let Some(Nim::Proc(ptys, ret)) = f.ty.clone() else {
6106+ return Err(format!(
6107+ "`{}` is called here but is not a function; only a named \
6108+ function or a value of proc type can be",
6109+ snippet(&quote::quote!(#{ &c.func }).to_string()),
6110+ ));
6111+ };
6112+ let mut codes = Vec::new();
6113+ for (i, a) in c.args.iter().enumerate() {
6114+ codes.push(self.expr_at(a, ptys.get(i))?.code);
6115+ }
6116+ return Ok(Val::new(
6117+ format!("{}({})", f.code, codes.join(", ")),
6118+ Some((*ret).clone()),
6119+ ));
61026120 };
61036121 let name = path_name(&p.path);
61046122
@@ -6098,7 +6098,25 @@ impl Lowerer {
6098 6098
6099 fn call(&mut self, c: &syn::ExprCall, expect: Option<&Nim>) -> Result<Val, String> {6099 fn call(&mut self, c: &syn::ExprCall, expect: Option<&Nim>) -> Result<Val, String> {
6100 let Expr::Path(p) = &*c.func else {6100 let Expr::Path(p) = &*c.func else {
6101- return Err("only calls to named functions are supported".into());6101+ // `(self.map)(o)` -- calling something that holds a proc. Nim
6102+ // calls a proc-typed value with the same syntax, so this needs
6103+ // only the callee's type to confirm that is what it is.
6104+ let f = self.expr(&c.func)?;
6105+ let Some(Nim::Proc(ptys, ret)) = f.ty.clone() else {
6106+ return Err(format!(
6107+ "`{}` is called here but is not a function; only a named \
6108+ function or a value of proc type can be",
6109+ snippet(&quote::quote!(#{ &c.func }).to_string()),
6110+ ));
6111+ };
6112+ let mut codes = Vec::new();
6113+ for (i, a) in c.args.iter().enumerate() {
6114+ codes.push(self.expr_at(a, ptys.get(i))?.code);
6115+ }
6116+ return Ok(Val::new(
6117+ format!("{}({})", f.code, codes.join(", ")),
6118+ Some((*ret).clone()),
6119+ ));
6102 };6120 };
6103 let name = path_name(&p.path);6121 let name = path_name(&p.path);
6104 6122
added tests/cases/061-call-proc-value.rs +27 -0
new file mode 100644
@@ -0,0 +1,27 @@
1+// Calling something that holds a function rather than a named function. Nim
2+// calls a proc-typed value with the same syntax, so what this needs is the
3+// callee's type.
4+struct Mapper {
5+ f: fn(u32) -> u32,
6+}
7+
8+fn double(x: u32) -> u32 {
9+ x * 2
10+}
11+
12+fn plus3(x: u32) -> u32 {
13+ x + 3
14+}
15+
16+fn apply(m: &Mapper, v: u32) -> u32 {
17+ (m.f)(v)
18+}
19+
20+fn main() {
21+ let a = Mapper { f: double };
22+ let b = Mapper { f: plus3 };
23+ println!("{} {}", apply(&a, 10), apply(&b, 10));
24+
25+ let g: fn(u32) -> u32 = double;
26+ println!("{}", (g)(21));
27+}
new file mode 100644
@@ -0,0 +1,27 @@
1+// Calling something that holds a function rather than a named function. Nim
2+// calls a proc-typed value with the same syntax, so what this needs is the
3+// callee's type.
4+struct Mapper {
5+ f: fn(u32) -> u32,
6+}
7+
8+fn double(x: u32) -> u32 {
9+ x * 2
10+}
11+
12+fn plus3(x: u32) -> u32 {
13+ x + 3
14+}
15+
16+fn apply(m: &Mapper, v: u32) -> u32 {
17+ (m.f)(v)
18+}
19+
20+fn main() {
21+ let a = Mapper { f: double };
22+ let b = Mapper { f: plus3 };
23+ println!("{} {}", apply(&a, 10), apply(&b, 10));
24+
25+ let g: fn(u32) -> u32 = double;
26+ println!("{}", (g)(21));
27+}