@@ -37,17 +37,18 @@ static void v_fastc_print_bool(bool value) { fputs(value ? "true" : "false", std
3737static void v_fastc_print_char(char value) { fputc(value, stdout); }
3838static void v_fastc_print_signed(long long value) { printf("%lld", value); }
3939static void v_fastc_print_unsigned(unsigned long long value) { printf("%llu", value); }
40- static void v_fastc_print_float(double value) { printf("%g ", value); }
4140static void v_fastc_println_string(const char *value) { puts(value); }
4241static void v_fastc_println_bool(bool value) { puts(value ? "true" : "false"); }
4342static void v_fastc_println_char(char value) { fputc(value, stdout); fputc(10, stdout); }
4443static void v_fastc_println_signed(long long value) { printf("%lld\n", value); }
4544static void v_fastc_println_unsigned(unsigned long long value) { printf("%llu\n", value); }
46- static void v_fastc_println_float(double value) { printf("%g \n", value); }
4745
48- #define V_FASTC_PRINT_SELECT(value, string_fn, bool_fn, char_fn, signed_fn, unsigned_fn, float_fn) _Generic((value), char *: string_fn, const char *: string_fn, bool: bool_fn, char: char_fn, signed char: signed_fn, short: signed_fn, int: signed_fn, long: signed_fn, long long: signed_fn, unsigned char: unsigned_fn, unsigned short: unsigned_fn, unsigned int: unsigned_fn, unsigned long: unsigned_fn, unsigned long long: unsigned_fn, float: float_fn, double: float_fn)(value)
49- #define print(value) V_FASTC_PRINT_SELECT(value, v_fastc_print_string, v_fastc_print_bool, v_fastc_print_char, v_fastc_print_signed, v_fastc_print_unsigned, v_fastc_print_float)
50- #define println(value) V_FASTC_PRINT_SELECT(value, v_fastc_println_string, v_fastc_println_bool, v_fastc_println_char, v_fastc_println_signed, v_fastc_println_unsigned, v_fastc_println_float)
46+ /* Float formatting belongs to the V strconv routines. Leaving float and double
47+ * unmatched makes TinyCC reject this speculative candidate so the driver uses
48+ * the checked FastC lane instead of silently applying printf %g semantics. */
49+ #define V_FASTC_PRINT_SELECT(value, string_fn, bool_fn, char_fn, signed_fn, unsigned_fn) _Generic((value), char *: string_fn, const char *: string_fn, bool: bool_fn, char: char_fn, signed char: signed_fn, short: signed_fn, int: signed_fn, long: signed_fn, long long: signed_fn, unsigned char: unsigned_fn, unsigned short: unsigned_fn, unsigned int: unsigned_fn, unsigned long: unsigned_fn, unsigned long long: unsigned_fn)(value)
50+ #define print(value) V_FASTC_PRINT_SELECT(value, v_fastc_print_string, v_fastc_print_bool, v_fastc_print_char, v_fastc_print_signed, v_fastc_print_unsigned)
51+ #define println(value) V_FASTC_PRINT_SELECT(value, v_fastc_println_string, v_fastc_println_bool, v_fastc_println_char, v_fastc_println_signed, v_fastc_println_unsigned)
5152#define assert(value) do { if (!(value)) { fprintf(stderr, "assertion failed: %s \n", #value); abort(); } } while (0)
5253
5354'
6263 protos strings.Builder
6364 indent int
6465 in_main bool
66+ temp_id int
6567}
6668
6769// generate scans V source and emits C as each declaration and statement is consumed. It does
@@ -114,6 +116,12 @@ fn (mut g DirectGen) next() {
114116 g.lit = g.s.lit
115117}
116118
119+ fn (mut g DirectGen) temporary_name (kind string ) string {
120+ name := '__v_fastc_${kind }_${g .temp_id }'
121+ g.temp_id++
122+ return name
123+ }
124+
117125fn (mut g DirectGen) skip_semicolons () {
118126 for g.tok == .semicolon {
119127 g.next ()
@@ -355,7 +363,12 @@ fn (mut g DirectGen) parse_for() ! {
355363 g.expect (.dotdot)!
356364 end := g.read_expression ([token.Token.lcbr])!
357365 g.expect (.lcbr)!
358- g.write_line ('for (__typeof__((${start })) ${name } = (${start }); ${name } < (${end }); ${name }++) {' )
366+ start_name := g.temporary_name ('range_start' )
367+ end_name := g.temporary_name ('range_end' )
368+ // V evaluates both range bounds exactly once, from left to right.
369+ g.write_line ('__typeof__((${start })) ${start_name } = (${start });' )
370+ g.write_line ('__typeof__((${end })) ${end_name } = (${end });' )
371+ g.write_line ('for (__typeof__((${start_name })) ${name } = (${start_name }); ${name } < (${end_name }); ${name }++) {' )
359372 g.indent++
360373 g.parse_block_body ()!
361374 g.indent--
0 commit comments