diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-13 02:20:48 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-13 02:20:48 -0400 |
| commit | aa74180ed1a32da1c0191d8e202922a5dc03f3ce (patch) | |
| tree | 01a7c9faf81d9a69aced60881d7db2c15dba20bd | |
| parent | 158a1c6ad2d9b3f2a598e6d1d8debcc824ad73d0 (diff) | |
Fixing up integers
| -rw-r--r-- | builtins/integers.c | 16 | ||||
| -rw-r--r-- | builtins/integers.h | 7 | ||||
| -rw-r--r-- | compile.c | 11 |
3 files changed, 28 insertions, 6 deletions
diff --git a/builtins/integers.c b/builtins/integers.c index dd38de91..08da553e 100644 --- a/builtins/integers.c +++ b/builtins/integers.c @@ -29,6 +29,13 @@ public Int_t Int$from_i64(int64_t i) return Int$from_mpz(result); } +public Int_t Int$from_num(double n) +{ + mpz_t result; + mpz_init_set_d(result, n); + return Int$from_mpz(result); +} + public CORD Int$as_text(const Int_t *i, bool colorize, const TypeInfo *type) { (void)type; if (!i) return "Int"; @@ -341,14 +348,17 @@ public const TypeInfo $Int = { (void)type; \ return *x == *y; \ } \ - public CORD KindOfInt ## $format(c_type i, int64_t digits) { \ + public CORD KindOfInt ## $format(c_type i, Int_t digits_int) { \ + int64_t digits = Int$as_i64(digits_int); \ return CORD_asprintf("%0*" fmt, (int)digits, i); \ } \ - public CORD KindOfInt ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix) { \ + public CORD KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \ + int64_t digits = Int$as_i64(digits_int); \ const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx"); \ return CORD_asprintf(hex_fmt, (int)digits, (uint64_t)i); \ } \ - public CORD KindOfInt ## $octal(c_type i, int64_t digits, bool prefix) { \ + public CORD KindOfInt ## $octal(c_type i, Int_t digits_int, bool prefix) { \ + int64_t digits = Int$as_i64(digits_int); \ const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; \ return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)i); \ } \ diff --git a/builtins/integers.h b/builtins/integers.h index f93e7abf..e41fd061 100644 --- a/builtins/integers.h +++ b/builtins/integers.h @@ -24,9 +24,9 @@ CORD type_name ## $as_text(const c_type *i, bool colorize, const TypeInfo *type); \ int32_t type_name ## $compare(const c_type *x, const c_type *y, const TypeInfo *type); \ bool type_name ## $equal(const c_type *x, const c_type *y, const TypeInfo *type); \ - CORD type_name ## $format(c_type i, int64_t digits); \ - CORD type_name ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix); \ - CORD type_name ## $octal(c_type i, int64_t digits, bool prefix); \ + CORD type_name ## $format(c_type i, Int_t digits); \ + CORD type_name ## $hex(c_type i, Int_t digits, bool uppercase, bool prefix); \ + CORD type_name ## $octal(c_type i, Int_t digits, bool prefix); \ array_t type_name ## $bits(c_type x); \ c_type type_name ## $random(c_type min, c_type max); \ Range_t type_name ## $to(c_type from, c_type to); \ @@ -77,6 +77,7 @@ Int_t Int$abs(Int_t x); #define Int$as_i64(i) (((i).small & 1) ? (int64_t)((i).small >> 2) : mpz_get_si(*(i).big)) Int_t Int$from_i64(int64_t i); +Int_t Int$from_num(double n); #define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int$from_i64(i)) Int_t Int$slow_plus(Int_t x, Int_t y); @@ -2331,6 +2331,17 @@ CORD compile(env_t *env, ast_t *ast) // Struct constructor: fn_t = Type(FunctionType, .args=Match(t, StructType)->fields, .ret=t); return CORD_all("((", compile_type(t), "){", compile_arguments(env, ast, Match(fn_t, FunctionType)->args, call->args), "})"); + } else if (t->tag == IntType && Match(t, IntType)->bits == 0) { + // Int/Num constructor: + if (!call->args || call->args->next) + code_err(call->fn, "This constructor takes exactly 1 argument"); + type_t *actual = get_type(env, call->args->value); + if (actual->tag == IntType) + return CORD_all("I((Int64_t)(", compile(env, call->args->value), "))"); + else if (actual->tag == NumType) + return CORD_all("Int$from_num((double)(", compile(env, call->args->value), "))"); + else + code_err(call->args->value, "This %T value cannot be converted to a %T", actual, t); } else if (t->tag == IntType || t->tag == NumType) { // Int/Num constructor: if (!call->args || call->args->next) |
