aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/integers.c16
-rw-r--r--builtins/integers.h7
-rw-r--r--compile.c11
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);
diff --git a/compile.c b/compile.c
index 2377ec25..2766143c 100644
--- a/compile.c
+++ b/compile.c
@@ -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)