diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-12 22:52:42 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-12 22:52:42 -0400 |
commit | ec2f3f213e4abce5cef3131673d969ca9d3c534c (patch) | |
tree | b88ae5109f5bb4c5b4c4c7f666f68de17c70e811 | |
parent | 65c9211b961c0c5d2c48b37533825852013687b5 (diff) |
foreign varargs almost working
-rw-r--r-- | cgen.c | 56 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 41 |
3 files changed, 72 insertions, 26 deletions
@@ -415,7 +415,7 @@ static inline void cgen_fn_name(CGenerator *g, FnExpr *f) { } static inline void cgen_fn_instance_number(CGenerator *g, U64 instance) { - cgen_write(g, U64_FMT"_", instance); + cgen_write(g, U64_FMT "_", instance); } /* should we generate this function? (or is it just meant for compile time) */ @@ -1622,7 +1622,6 @@ static void cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_ cgen_write(g, " {"); cgen_nl(g); if (compile_time_args) { - int carg_idx = 0; ++compile_time_args; /* move past which_are_const */ int semi_const_idx = 0; arr_foreach(f->params, Declaration, param) { @@ -1630,24 +1629,41 @@ static void cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_ || ((param->flags & DECL_SEMI_CONST) && (which_are_const & (((U64)1) << semi_const_idx++)))) { int i = 0; - arr_foreach(param->idents, Identifier, ident) { - Type *type = param->type.kind == TYPE_TUPLE ? ¶m->type.tuple[i] - : ¶m->type; - Value arg = compile_time_args[carg_idx]; - if (type_is_builtin(type, BUILTIN_TYPE) || type_is_builtin(type, BUILTIN_VARARGS)) { - /* don't need to do anything */ - } else { - cgen_val_pre(g, arg, type); - cgen_type_pre(g, type); - cgen_write(g, " const "); - cgen_ident(g, *ident); - cgen_type_post(g, type); - cgen_write(g, " = "); - cgen_val(g, arg, type); - cgen_write(g, ";"); - cgen_nl(g); + if (type_is_builtin(¶m->type, BUILTIN_VARARGS)) { + VarArg *vararg = param->val.varargs; + size_t nvarargs = arr_len(vararg); + for (size_t v = 0; v < nvarargs; ++v, ++vararg) { + Type *type = vararg->type; + Value arg = vararg->val; + if (!type_is_compileonly(type)) { + cgen_val_pre(g, arg, type); + cgen_type_pre(g, type); + cgen_write(g, " const "); + assert(arr_len(param->idents) == 1); + cgen_ident(g, param->idents[0]); + cgen_write(g, "%lu_", (unsigned long)v); + cgen_type_post(g, type); + cgen_write(g, " = "); + cgen_val(g, arg, type); + cgen_writeln(g, ";"); + } + } + } else { + arr_foreach(param->idents, Identifier, ident) { + Type *type = decl_type_at_index(param, i); + Value arg = *decl_val_at_index(param, i); + if (!type_is_compileonly(type)) { + cgen_val_pre(g, arg, type); + cgen_type_pre(g, type); + cgen_write(g, " const "); + cgen_ident(g, *ident); + cgen_type_post(g, type); + cgen_write(g, " = "); + cgen_val(g, arg, type); + cgen_writeln(g, ";"); + } + ++i; } - ++carg_idx; } } } @@ -1757,7 +1773,7 @@ static void cgen_val_ptr(CGenerator *g, void *v, Type *t) { case BUILTIN_U32: cgen_write(g, U32_FMT, *(U32 *)v); break; case BUILTIN_I64: cgen_write(g, I64_FMT, *(I64 *)v); break; case BUILTIN_U64: cgen_write(g, U64_FMT, *(U64 *)v); break; - case BUILTIN_F32: cgen_write(g, F32_FMT"f", *(F32 *)v); break; + case BUILTIN_F32: cgen_write(g, F32_FMT "f", *(F32 *)v); break; case BUILTIN_F64: cgen_write(g, F64_FMT, *(F64 *)v); break; case BUILTIN_CHAR: cgen_write(g, "'\\x%02x'", *(char *)v); break; case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break; @@ -8,6 +8,7 @@ /* TODO: +is the current cgen_val situation good? there are probably situations where it could be problematic (i.e. where an expression is replaced with an array value-- try varargs[0][0], where varargs[0] is an array) EXPR_VALs don't always need temp variables 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) @@ -1,8 +1,37 @@ -printf ::= #foreign("printf", "libc.so.6") fn(#C &"const char", #C ..) #C int; +printf ::= #foreign("printf","libc.so.6") fn(#C &"const char", #C ..) #C int; -main::=fn(){ - s := "Hello %d\n\0"; - printf(&s[0], 5); - +tprintf ::= fn(fmt: []char, args: ..) { + printf(&fmt[0], args); +}; + +sum ::= fn(x: ..) int { + total := 0; + n := 0; + for a, i := x { + total += a + i / i; + n += 1; + } + total - n +}; + +sumc ::= fn(x:: ..) int { + total := 0; + n := 0; + for a, i := x { + total += a + i / i; + n += 1; + } + total - n +}; + +do_printing ::= fn(x::..) { + tprintf("%ld\n",sum(x)); + tprintf("%ld\n",sumc(x)); +}; + +main ::= fn() { + do_printing(); + do_printing(1,2,3); + do_printing(4); + do_printing(1,10,100,1000,10000); }; -main();
\ No newline at end of file |