aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-06 05:42:19 +0200
committerlemon <lsof@mailbox.org>2022-08-06 05:43:06 +0200
commit762c6c17c9effd360a6e00a440964cb176cf96e7 (patch)
tree83f460ec36865dbb77808e22054f164a20bc26b1 /bootstrap
parent3083cf126cf3989b257546aa3b1b69608aac7923 (diff)
macro body arg
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/all.h2
-rw-r--r--bootstrap/parse.c44
-rw-r--r--bootstrap/test.cff25
3 files changed, 61 insertions, 10 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h
index 15f932c..7631872 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -201,7 +201,7 @@ struct fn {
};
struct macrocase {
- bool variadic;
+ bool variadic, bodyarg;
slice_t(const char *) params;
struct toktree body;
};
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 4372cdc..2b0f08e 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -1642,6 +1642,7 @@ parseexpandmacro(struct parser *P, const struct macro *macro) {
struct expan expan = {0};
struct expanarg *expanargs;
struct macrocase c;
+ bool bodyarg = 0;
expan.span = lexpeek(P).span;
lexexpect(P, '(');
@@ -1685,11 +1686,42 @@ parseexpandmacro(struct parser *P, const struct macro *macro) {
}
}
+ if (lexmatch(P, &tok, '{')) {
+ int pabal = 0,
+ bkbal = 0,
+ bcbal = 1;
+ struct span espan = tok.span;
+ vec_t(struct tok) toks = {0};
+ struct toktree ttoks;
+ vec_push(&toks, (struct tok){'{'});
+ bodyarg = 1;
+
+ while (bcbal > 0) {
+ tok = lex(P);
+ switch (tok.t) {
+ case '[': ++bkbal; break;
+ case ']': --bkbal; break;
+ case '{': ++bcbal; break;
+ case '}': --bcbal; break;
+ case '(': ++pabal; break;
+ case ')': --pabal; break;
+ case TKeof:
+ fatal(P, espan, "unterminated macro `%s' invokation", macro->name);
+ }
+ vec_push(&toks, tok);
+ }
+
+ vec_slice_cpy(&ttoks, &toks);
+ vec_push(&args, ttoks);
+ }
+
for (int i = 0; i < macro->cs.n; ++i) {
c = macro->cs.d[i];
- if (!c.variadic && args.length == c.params.n) {
+ if (c.bodyarg && bodyarg && args.length == c.params.n) {
+ goto ok;
+ } else if (!c.variadic && args.length == c.params.n && !bodyarg) {
goto ok;
- } else if (c.variadic && args.length >= c.params.n - 1) {
+ } else if (c.variadic && args.length >= c.params.n - 1 && !bodyarg) {
int n = args.length - (c.params.n - 1);
if (n == 0) {
vec_push(&args, (struct toktree){0});
@@ -1939,8 +1971,14 @@ parsemacrocase(struct parser *P) {
lexexpect(P, ')');
break;
} else {
+ if (lexmatch(P, &tok, '&'))
+ c.bodyarg = 1;
vec_push(&params, lexexpects(P, TKident, "parameter name").str);
- if (!lexmatch(P, &tok, ',')) {
+ if (c.bodyarg) {
+ lexmatch(P, &tok, ',');
+ lexexpect(P, ')');
+ break;
+ } else if (!lexmatch(P, &tok, ',')) {
lexexpect(P, ')');
break;
}
diff --git a/bootstrap/test.cff b/bootstrap/test.cff
index 011d386..6c0f605 100644
--- a/bootstrap/test.cff
+++ b/bootstrap/test.cff
@@ -20,6 +20,18 @@ enum Color {
static xs *void = {},
ok = 6;
+defmacro each(i, x, arr, &body) [
+ for let i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i {
+ let x = arr[i];
+ body
+ }
+]
+defmacro times(n,&body) [
+ for let $i = 0; $i < (n); ++$i {
+ body
+ }
+]
+
fn isort(xs *int, n usize) void {
fn icmp(lhs *const void, rhs *const void, _ *void) int {
let lhs = *as(*int)lhs,
@@ -40,13 +52,14 @@ extern fn main (argc int, argv **u8) int {
let p = &x;
printf("v = { %g, %g }\n", x.x, p.y);
- let is [10]int = { [4] = 1, 2, [1 - 1] = 3 };
- isort(is, 10);
- for let i = 0; i < 10; ++i {
- printf("%d\n", is[i]);
- }
+ let xs [10]int = { [4] = 1, 2, [1 - 1] = 3 };
+ isort(xs, 10);
+
+ each(i, x, xs) {
+ printf("%d\n", xs[i]);
+ }
- printf("sizeof(is) = %zu\n", sizeof(is));
+ printf("sizeof(is) = %zu\n", sizeof(xs));
printf("sizeof *void = %zu\n", sizeof *void);