feat: capture-less anonymous functions (closures)
Implement MVP closures — anonymous functions without captures.
Syntax:
|a: int, b: int| -> int { return a + b; }
Changes:
- ast.bux + ast.nim: add ekClosure AST node
- parser.bux + parser.nim: parse |params| -> Ret { body }
- sema.bux + sema.nim: type-check closure params/body, return tyFunc
- hir_lower.bux + hir_lower.nim: generate __closure_N function + hAddrOf
- lir_c_backend.nim: fix function-pointer variable declaration (cParamDecl)
- C backend: closures compile to global functions with unique names
Test: _test_closure/src/Main.bux
- Closure as variable
- Closure passed to higher-order function
- Address of named function as function pointer
Both bootstrap and selfhost compilers build and pass the test.
This commit is contained in:
Executable
BIN
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
/* Bux Standard Library - I/O functions */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* PrintLine - print string with newline */
|
||||
void PrintLine(const char* s) {
|
||||
if (s != NULL) {
|
||||
puts(s);
|
||||
} else {
|
||||
puts("");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print - print string without newline */
|
||||
void Print(const char* s) {
|
||||
if (s != NULL) {
|
||||
printf("%s", s);
|
||||
}
|
||||
}
|
||||
|
||||
/* PrintInt - print integer */
|
||||
void PrintInt(int n) {
|
||||
printf("%d", n);
|
||||
}
|
||||
|
||||
/* PrintInt64 - print 64-bit integer */
|
||||
void PrintInt64(int64_t n) {
|
||||
printf("%lld", (long long)n);
|
||||
}
|
||||
|
||||
/* PrintFloat - print float */
|
||||
void PrintFloat(double f) {
|
||||
printf("%g", f);
|
||||
}
|
||||
|
||||
/* PrintBool - print boolean */
|
||||
void PrintBool(int b) {
|
||||
printf("%s", b ? "true" : "false");
|
||||
}
|
||||
|
||||
/* ReadLine - read line from stdin (simplified) */
|
||||
const char* ReadLine(void) {
|
||||
static char buffer[1024];
|
||||
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
|
||||
size_t len = strlen(buffer);
|
||||
if (len > 0 && buffer[len-1] == '\n') {
|
||||
buffer[len-1] = '\0';
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,67 @@
|
||||
// Generated by Bux C Backend v2
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef const char* String;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long uint64;
|
||||
typedef signed char int8;
|
||||
typedef short int16;
|
||||
typedef long long int64;
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
typedef char char8;
|
||||
|
||||
void* bux_alloc(unsigned int size);
|
||||
void bux_free(void* ptr);
|
||||
|
||||
|
||||
int Apply(int x, int (*op)(int));
|
||||
int Double(int x);
|
||||
int __closure_2(int a, int b);
|
||||
int __closure_3(int x);
|
||||
int main();
|
||||
|
||||
void PrintInt(int x);
|
||||
void PrintLine(String msg);
|
||||
|
||||
int Apply(int x, int (*op)(int)) {
|
||||
return op(x);
|
||||
|
||||
}
|
||||
|
||||
int Double(int x) {
|
||||
return x * 2;
|
||||
|
||||
}
|
||||
|
||||
int __closure_2(int a, int b) {
|
||||
return a + b;
|
||||
|
||||
}
|
||||
|
||||
int __closure_3(int x) {
|
||||
return x * 3;
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
int (*add)(int, int) = &__closure_2;
|
||||
int sum = add(3, 4);
|
||||
PrintInt(sum);
|
||||
PrintLine("");
|
||||
int result = Apply(5, &__closure_3);
|
||||
PrintInt(result);
|
||||
PrintLine("");
|
||||
int (*d)(int) = &Double;
|
||||
PrintInt(d(7));
|
||||
PrintLine("");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
[Package]
|
||||
Name = "closure_test"
|
||||
Version = "0.1.0"
|
||||
Type = "bin"
|
||||
|
||||
[Build]
|
||||
Output = "Bin"
|
||||
@@ -0,0 +1,34 @@
|
||||
module Main {
|
||||
|
||||
extern func PrintInt(x: int);
|
||||
extern func PrintLine(msg: String);
|
||||
|
||||
func Apply(x: int, op: func(int) -> int) -> int {
|
||||
return op(x);
|
||||
}
|
||||
|
||||
func Double(x: int) -> int {
|
||||
return x * 2;
|
||||
}
|
||||
|
||||
func main() -> int {
|
||||
// Closure as variable
|
||||
let add: func(int, int) -> int = |a: int, b: int| -> int { return a + b; };
|
||||
let sum: int = add(3, 4);
|
||||
PrintInt(sum);
|
||||
PrintLine("");
|
||||
|
||||
// Closure passed to function
|
||||
let result: int = Apply(5, |x: int| -> int { return x * 3; });
|
||||
PrintInt(result);
|
||||
PrintLine("");
|
||||
|
||||
// Address of named function as function pointer
|
||||
let d: func(int) -> int = &Double;
|
||||
PrintInt(d(7));
|
||||
PrintLine("");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user