summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c1
-rw-r--r--test.toc29
-rw-r--r--tests/varargs.toc8
-rw-r--r--types.c33
4 files changed, 47 insertions, 24 deletions
diff --git a/main.c b/main.c
index 6b7747a..fe55fcc 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
TODO:
-varargs len
make new and del functions!
where
#returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf)
diff --git a/test.toc b/test.toc
index 5573554..0885da4 100644
--- a/test.toc
+++ b/test.toc
@@ -1,10 +1,33 @@
printf ::= #foreign("printf","libc.so.6") fn(#C &"const char", #C ..) #C int;
+tprintf ::= fn(fmt: []char, args: ..) {
+ printf(&fmt[0], args);
+};
+
+sum ::= fn(x: ..) int {
+ total := 0;
+ for a, i := x {
+ total += a + i - i + 1;
+ }
+ total - x.len
+};
+
+sumc ::= fn(x:: ..) int {
+ total := 0;
+ for a, i := x {
+ total += a + i - i + 1;
+ }
+ total - x.len
+};
-f ::= fn(x: int, y: int) int {
- x+y
+do_printing ::= fn(x::..) {
+ tprintf("%ld\n",sum(x));
+ tprintf("%ld\n",sumc(x));
};
main ::= fn() {
- f(3,4 as typeof f(3,4));
+ do_printing();
+ do_printing(1,2,3);
+ do_printing(4);
+ do_printing(1,10,100,1000,10000);
};
diff --git a/tests/varargs.toc b/tests/varargs.toc
index 8709a64..0885da4 100644
--- a/tests/varargs.toc
+++ b/tests/varargs.toc
@@ -6,22 +6,18 @@ tprintf ::= fn(fmt: []char, args: ..) {
sum ::= fn(x: ..) int {
total := 0;
- n := 0;
for a, i := x {
total += a + i - i + 1;
- n += 1;
}
- total - n
+ total - x.len
};
sumc ::= fn(x:: ..) int {
total := 0;
- n := 0;
for a, i := x {
total += a + i - i + 1;
- n += 1;
}
- total - n
+ total - x.len
};
do_printing ::= fn(x::..) {
diff --git a/types.c b/types.c
index 4e9704c..1af49f1 100644
--- a/types.c
+++ b/types.c
@@ -2585,14 +2585,7 @@ static Status types_expr(Typer *tr, Expression *e) {
t->builtin = BUILTIN_BOOL;
break;
case UNARY_LEN:
- t->kind = TYPE_BUILTIN;
- t->builtin = BUILTIN_I64;
- if (of_type->kind != TYPE_SLICE || of_type->kind != TYPE_ARR) {
- char *s = type_to_str(of_type);
- err_print(e->where, "Cannot get length of non-array, non-slice type %s.", s);
- free(s);
- return false;
- }
+ assert(0); /* types_expr is what makes things UNARY_LEN */
break;
case UNARY_TYPEOF: {
if (of->type.kind == TYPE_VOID) {
@@ -2915,19 +2908,31 @@ static Status types_expr(Typer *tr, Expression *e) {
return false;
break;
}
- } else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR) {
+ } else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR || type_is_builtin(struct_type, BUILTIN_VARARGS)) {
if (!ident_eq_str(rhs->ident, "len")) {
- err_print(rhs->where, "Field of array or slice must be .len");
+ char *s = type_to_str(struct_type);
+ err_print(rhs->where, "Field of %s must be .len", s);
+ free(s);
return false;
}
/* length of slice/arr is i64 */
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_I64;
- /* change expr to UNARY_LEN */
- e->kind = EXPR_UNARY_OP;
Expression *of = lhs;
- e->unary.op = UNARY_LEN;
- e->unary.of = of;
+ if (type_is_builtin(struct_type, BUILTIN_VARARGS)) {
+ /* replace with val */
+ assert(of->kind == EXPR_IDENT);
+ Identifier ident = of->ident;
+ assert(ident->decl_kind == IDECL_DECL);
+ Declaration *decl = ident->decl;
+ e->kind = EXPR_VAL;
+ e->val.i64 = (I64)arr_len(decl->val.varargs);
+ } else {
+ /* change expr to UNARY_LEN */
+ e->kind = EXPR_UNARY_OP;
+ e->unary.op = UNARY_LEN;
+ e->unary.of = of;
+ }
} else if (type_is_builtin(struct_type, BUILTIN_NMS)) {
Value nms_val;
if (!eval_expr(tr->evalr, lhs, &nms_val))