aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-13 23:37:24 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-13 23:37:24 -0500
commitb71624abffe8ff975814d7ff5400ec5ddb9c2767 (patch)
tree769426074e94ac3b5bcd5261ac9e4cf4501107c1
parent1f2b288b32b61dca84fa39eb048e30fbee1262aa (diff)
Fix floating point literals to be exactly precise
-rw-r--r--compile.c7
-rw-r--r--util.h2
2 files changed, 8 insertions, 1 deletions
diff --git a/compile.c b/compile.c
index d48a296a..4611305e 100644
--- a/compile.c
+++ b/compile.c
@@ -35,7 +35,12 @@ CORD compile(env_t *env, ast_t *ast)
case Bool: return Match(ast, Bool)->b ? "yes" : "no";
case Var: return Match(ast, Var)->name;
case Int: return CORD_asprintf("I%ld(%ld)", Match(ast, Int)->precision, Match(ast, Int)->i);
- case Num: return CORD_asprintf(Match(ast, Num)->precision == 64 ? "%g" : "%gf", Match(ast, Num)->n);
+ case Num: {
+ // HACK: since the cord library doesn't support the '%a' specifier, this workaround
+ // is necessary:
+ char *buf = asprintfa(Match(ast, Num)->precision == 64 ? "%a" : "%af", Match(ast, Num)->n);
+ return CORD_from_char_star(buf);
+ }
case UnaryOp: {
auto unop = Match(ast, UnaryOp);
CORD expr = compile(env, unop->value);
diff --git a/util.h b/util.h
index 1c098781..68ce2c9f 100644
--- a/util.h
+++ b/util.h
@@ -27,6 +27,8 @@ char *heap_strf(const char *fmt, ...);
CORD CORD_asprintf(const char *fmt, ...);
#define CORD_appendf(cord, fmt, ...) CORD_sprintf(cord, "%r" fmt, *(cord) __VA_OPT__(,) __VA_ARGS__)
+#define asprintfa(...) ({ char *_buf = alloca(snprintf(0, 0, __VA_ARGS__)); sprintf(_buf, __VA_ARGS__); _buf; })
+
#define REVERSE_LIST(list) do { \
__typeof(list) _prev = NULL; \
__typeof(list) _next = NULL; \