aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-14 14:57:01 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-14 14:57:01 -0400
commit9c2d7c437d7576b44f4cf0e6b6a293acd7188a5d (patch)
treef77b86d59c258f2e1d9834f8acc7c68da68af01a
parentc8af1ac9c12073776fda6af7ae58f9d6e2d81e66 (diff)
Fix up type conversions with ints and nums
-rw-r--r--builtins/array.c16
-rw-r--r--builtins/array.h4
-rw-r--r--builtins/channel.c2
-rw-r--r--builtins/integers.c44
-rw-r--r--builtins/integers.h109
-rw-r--r--builtins/nums.c8
-rw-r--r--builtins/text.c2
-rw-r--r--compile.c43
-rw-r--r--repl.c20
9 files changed, 154 insertions, 94 deletions
diff --git a/builtins/array.c b/builtins/array.c
index 96a218f5..a6e0dca2 100644
--- a/builtins/array.c
+++ b/builtins/array.c
@@ -50,7 +50,7 @@ public void Array$compact(array_t *arr, int64_t padded_item_size)
public void Array$insert(array_t *arr, const void *item, Int_t int_index, int64_t padded_item_size)
{
- int64_t index = Int$as_i64(int_index);
+ int64_t index = Int_to_Int64(int_index, false);
if (index <= 0) index = arr->length + index + 1;
if (index < 1) index = 1;
@@ -82,7 +82,7 @@ public void Array$insert(array_t *arr, const void *item, Int_t int_index, int64_
public void Array$insert_all(array_t *arr, array_t to_insert, Int_t int_index, int64_t padded_item_size)
{
- int64_t index = Int$as_i64(int_index);
+ int64_t index = Int_to_Int64(int_index, false);
if (to_insert.length == 0)
return;
@@ -154,10 +154,10 @@ public void Array$insert_all(array_t *arr, array_t to_insert, Int_t int_index, i
public void Array$remove(array_t *arr, Int_t int_index, Int_t int_count, int64_t padded_item_size)
{
- int64_t index = Int$as_i64(int_index);
+ int64_t index = Int_to_Int64(int_index, false);
if (index < 1) index = arr->length + index + 1;
- int64_t count = Int$as_i64(int_count);
+ int64_t count = Int_to_Int64(int_count, false);
if (index < 1 || index > (int64_t)arr->length || count < 1) return;
if (count > arr->length - index + 1)
@@ -240,7 +240,7 @@ public table_t Array$counts(array_t arr, const TypeInfo *type)
public array_t Array$sample(array_t arr, Int_t int_n, array_t weights, int64_t padded_item_size)
{
- int64_t n = Int$as_i64(int_n);
+ int64_t n = Int_to_Int64(int_n, false);
if (arr.length == 0 || n <= 0)
return (array_t){};
@@ -319,7 +319,7 @@ public array_t Array$sample(array_t arr, Int_t int_n, array_t weights, int64_t p
public array_t Array$from(array_t array, Int_t int_first)
{
- int64_t first = Int$as_i64(int_first);
+ int64_t first = Int_to_Int64(int_first, false);
if (first < 0)
first = array.length + first + 1;
@@ -337,7 +337,7 @@ public array_t Array$from(array_t array, Int_t int_first)
public array_t Array$to(array_t array, Int_t int_last)
{
- int64_t last = Int$as_i64(int_last);
+ int64_t last = Int_to_Int64(int_last, false);
if (last < 0)
last = array.length + last + 1;
@@ -358,7 +358,7 @@ public array_t Array$to(array_t array, Int_t int_last)
public array_t Array$by(array_t array, Int_t int_stride, int64_t padded_item_size)
{
- int64_t stride = Int$as_i64(int_stride);
+ int64_t stride = Int_to_Int64(int_stride, false);
// In the unlikely event that the stride value would be too large to fit in
// a 15-bit integer, fall back to creating a copy of the array:
if (__builtin_expect(array.stride*stride < ARRAY_MIN_STRIDE || array.stride*stride > ARRAY_MAX_STRIDE, 0)) {
diff --git a/builtins/array.h b/builtins/array.h
index 6da84afd..a3305ca3 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -13,13 +13,13 @@
// Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1
#define Array_get(item_type, arr_expr, index_expr, filename, start, end) *({ \
- const array_t arr = arr_expr; int64_t index = Int$as_i64(index_expr); \
+ const array_t arr = arr_expr; int64_t index = Int_to_Int64(index_expr, false); \
int64_t off = index + (index < 0) * (arr.length + 1) - 1; \
if (__builtin_expect(off < 0 || off >= arr.length, 0)) \
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64$as_text(&index, no, NULL), arr.length); \
(item_type*)(arr.data + arr.stride * off);})
#define Array_lvalue(item_type, arr_expr, index_expr, padded_item_size, filename, start, end) *({ \
- array_t *arr = arr_expr; int64_t index = Int$as_i64(index_expr); \
+ array_t *arr = arr_expr; int64_t index = Int_to_Int64(index_expr, false); \
int64_t off = index + (index < 0) * (arr->length + 1) - 1; \
if (__builtin_expect(off < 0 || off >= arr->length, 0)) \
fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64$as_text(&index, no, NULL), arr->length); \
diff --git a/builtins/channel.c b/builtins/channel.c
index dba50115..dd49163c 100644
--- a/builtins/channel.c
+++ b/builtins/channel.c
@@ -26,7 +26,7 @@ public channel_t *Channel$new(Int_t max_size)
channel->items = (array_t){};
channel->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
channel->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
- channel->max_size = Int$as_i64(max_size);
+ channel->max_size = Int_to_Int64(max_size, false);
return channel;
}
diff --git a/builtins/integers.c b/builtins/integers.c
index 0783f16d..bb82fab6 100644
--- a/builtins/integers.c
+++ b/builtins/integers.c
@@ -21,30 +21,6 @@ public void Int$init_random(long seed)
gmp_randseed_ui(Int_rng, (unsigned long)seed);
}
-public Int_t Int$from_i64(int64_t i)
-{
- int64_t z = i<<2;
- if (z == (int32_t)z) return (Int_t){.small=z+1};
- mpz_t result;
- mpz_init_set_si(result, 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 double Int$as_num(Int_t i)
-{
- if (__builtin_expect(i.small & 1, 1))
- return (double)(i.small >> 2);
-
- return mpz_get_d(*i.big);
-}
-
public CORD Int$as_text(const Int_t *i, bool colorize, const TypeInfo *type) {
(void)type;
if (!i) return "Int";
@@ -93,7 +69,7 @@ public uint32_t Int$hash(const Int_t *x, const TypeInfo *type) {
public CORD Int$format(Int_t i, Int_t digits_int)
{
- int64_t digits = Int$as_i64(digits_int);
+ int64_t digits = Int_to_Int64(digits_int, false);
if (__builtin_expect(i.small & 1, 1)) {
return CORD_asprintf("%0.*ld", digits, (i.small)>>2);
} else {
@@ -110,7 +86,7 @@ public CORD Int$format(Int_t i, Int_t digits_int)
}
public CORD Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
- int64_t digits = Int$as_i64(digits_int);
+ int64_t digits = Int_to_Int64(digits_int, false);
const char *hex_fmt = uppercase ? (prefix ? "0x%0.*lX" : "%0.*lX") : (prefix ? "0x%0.*lx" : "%0.*lx");
if (__builtin_expect(i.small & 1, 1)) {
return CORD_asprintf(hex_fmt, digits, (i.small)>>2);
@@ -125,7 +101,7 @@ public CORD Int$hex(Int_t i, Int_t digits_int, bool uppercase, bool prefix) {
}
public CORD Int$octal(Int_t i, Int_t digits_int, bool prefix) {
- int64_t digits = Int$as_i64(digits_int);
+ int64_t digits = Int_to_Int64(digits_int, false);
const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo";
if (__builtin_expect(i.small & 1, 1)) {
return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)(i.small >> 2));
@@ -213,7 +189,7 @@ public Int_t Int$slow_modulo1(Int_t x, Int_t modulus)
public Int_t Int$slow_left_shifted(Int_t x, Int_t y)
{
- mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y);
+ mp_bitcnt_t bits = (mp_bitcnt_t)Int_to_Int64(y, false);
mpz_t result;
mpz_init_set_int(result, x);
mpz_mul_2exp(result, result, bits);
@@ -222,7 +198,7 @@ public Int_t Int$slow_left_shifted(Int_t x, Int_t y)
public Int_t Int$slow_right_shifted(Int_t x, Int_t y)
{
- mp_bitcnt_t bits = (mp_bitcnt_t)Int$as_i64(y);
+ mp_bitcnt_t bits = (mp_bitcnt_t)Int_to_Int64(y, false);
mpz_t result;
mpz_init_set_int(result, x);
mpz_tdiv_q_2exp(result, result, bits);
@@ -292,7 +268,7 @@ public Int_t Int$abs(Int_t x)
public Int_t Int$power(Int_t base, Int_t exponent)
{
- int64_t exp = Int$as_i64(exponent);
+ int64_t exp = Int_to_Int64(exponent, false);
if (__builtin_expect(exp < 0, 0))
fail("Cannot take a negative power of an integer!");
mpz_t result;
@@ -382,16 +358,16 @@ public const TypeInfo $Int = {
return *x == *y; \
} \
public CORD KindOfInt ## $format(c_type i, Int_t digits_int) { \
- int64_t digits = Int$as_i64(digits_int); \
+ int64_t digits = Int_to_Int64(digits_int, false); \
return CORD_asprintf("%0*" fmt, (int)digits, i); \
} \
public CORD KindOfInt ## $hex(c_type i, Int_t digits_int, bool uppercase, bool prefix) { \
- int64_t digits = Int$as_i64(digits_int); \
+ int64_t digits = Int_to_Int64(digits_int, false); \
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, Int_t digits_int, bool prefix) { \
- int64_t digits = Int$as_i64(digits_int); \
+ int64_t digits = Int_to_Int64(digits_int, false); \
const char *octal_fmt = prefix ? "0o%0.*lo" : "%0.*lo"; \
return CORD_asprintf(octal_fmt, (int)digits, (uint64_t)i); \
} \
@@ -422,7 +398,7 @@ public const TypeInfo $Int = {
return (c_type)((uint64_t)min + (r % range)); \
} \
public Range_t KindOfInt ## $to(c_type from, c_type to) { \
- return (Range_t){Int$from_i64(from), Int$from_i64(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \
+ return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \
} \
public c_type KindOfInt ## $from_text(CORD text, CORD *the_rest) { \
const char *str = CORD_to_const_char_star(text); \
diff --git a/builtins/integers.h b/builtins/integers.h
index 98b58b0f..05085175 100644
--- a/builtins/integers.h
+++ b/builtins/integers.h
@@ -9,7 +9,10 @@
#include <gmp.h>
#include "datatypes.h"
+#include "functions.h"
+#include "nums.h"
#include "types.h"
+#include "util.h"
#define Int64_t int64_t
#define Int32_t int32_t
@@ -78,13 +81,7 @@ Int_t Int$sqrt(Int_t i);
else mpz_init_set(mpz, *(i).big); \
} while (0)
-#define Int$as_i64(i) (__builtin_expect((i).small & 1, 1) ? (int64_t)((i).small >> 2) : \
- ({ if (!__builtin_expect(mpz_fits_slong_p(*(i).big), 1)) fail("Integer is too big to fit in a 64-bit integer!"); \
- mpz_get_si(*(i).big); }))
-Int_t Int$from_i64(int64_t i);
-Int_t Int$from_num(double n);
-double Int$as_num(Int_t i);
-#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int$from_i64(i))
+#define I(i) ((int64_t)(i) == (int32_t)(i) ? ((Int_t){.small=((uint64_t)(i)<<2)|1}) : Int64_to_Int(i))
Int_t Int$slow_plus(Int_t x, Int_t y);
Int_t Int$slow_minus(Int_t x, Int_t y);
@@ -207,4 +204,102 @@ static inline Int_t Int$negative(Int_t x)
return Int$slow_negative(x);
}
+// Conversion functions:
+
+static inline Int_t Int64_to_Int(int64_t i)
+{
+ int64_t z = i<<2;
+ if (__builtin_expect(z == (int32_t)z, 1))
+ return (Int_t){.small=z+1};
+ mpz_t result;
+ mpz_init_set_si(result, i);
+ return Int$from_mpz(result);
+}
+
+#define Int32_to_Int(i) Int64_to_Int(i)
+#define Int16_to_Int(i) Int64_to_Int(i)
+#define Int8_to_Int(i) Int64_to_Int(i)
+
+static inline Int64_t Int_to_Int64(Int_t i, bool truncate) {
+ if (__builtin_expect(i.small & 1, 1))
+ return (int64_t)(i.small >> 2);
+ if (__builtin_expect(!truncate && !mpz_fits_slong_p(*i.big), 0))
+ fail("Integer is too big to fit in a 64-bit integer!");
+ return mpz_get_si(*i.big);
+}
+
+static inline Int32_t Int_to_Int32(Int_t i, bool truncate) {
+ int64_t i64 = Int_to_Int64(i, truncate);
+ int32_t i32 = (int32_t)i64;
+ if (__builtin_expect(i64 != i32 && !truncate, 0))
+ fail("Integer is too big to fit in a 32-bit integer!");
+ return i32;
+}
+
+static inline Int16_t Int_to_Int16(Int_t i, bool truncate) {
+ int64_t i64 = Int_to_Int64(i, truncate);
+ int16_t i16 = (int16_t)i64;
+ if (__builtin_expect(i64 != i16 && !truncate, 0))
+ fail("Integer is too big to fit in a 16-bit integer!");
+ return i16;
+}
+
+static inline Int8_t Int_to_Int8(Int_t i, bool truncate) {
+ int64_t i64 = Int_to_Int64(i, truncate);
+ int8_t i8 = (int8_t)i64;
+ if (__builtin_expect(i64 != i8 && !truncate, 0))
+ fail("Integer is too big to fit in an 8-bit integer!");
+ return i8;
+}
+
+static inline Int_t Num_to_Int(double n)
+{
+ mpz_t result;
+ mpz_init_set_d(result, n);
+ return Int$from_mpz(result);
+}
+
+static inline double Int_to_Num(Int_t i)
+{
+ if (__builtin_expect(i.small & 1, 1))
+ return (double)(i.small >> 2);
+
+ return mpz_get_d(*i.big);
+}
+
+#define Int_to_Num32(i) (Num32_t)Int_to_Num(i)
+
+#define CONVERSION_FUNC(hi, lo) \
+ static inline int##lo##_t Int##hi##_to_Int##lo(int##hi##_t i, bool truncate) { \
+ if (__builtin_expect(!truncate && (i != (int##lo##_t)i), 0)) \
+ fail("Cannot truncate the Int" #hi " %ld to an Int" #lo, (int64_t)i); \
+ return (int##lo##_t)i; \
+ }
+
+CONVERSION_FUNC(64, 32)
+CONVERSION_FUNC(64, 16)
+CONVERSION_FUNC(64, 8)
+CONVERSION_FUNC(32, 16)
+CONVERSION_FUNC(32, 8)
+CONVERSION_FUNC(16, 8)
+#undef CONVERSION_FUNC
+
+#define CONVERSION_FUNC(num, int_type) \
+ static inline int_type##_t num##_to_##int_type(num##_t n, bool truncate) { \
+ num##_t rounded = round(n); \
+ if (__builtin_expect(!truncate && (num##_t)(int_type##_t)rounded != rounded, 0)) \
+ fail("Cannot truncate the " #num " %g to an " #int_type, rounded); \
+ return (int_type##_t)rounded; \
+ }
+
+CONVERSION_FUNC(Num, Int64)
+CONVERSION_FUNC(Num, Int32)
+CONVERSION_FUNC(Num, Int16)
+CONVERSION_FUNC(Num, Int8)
+CONVERSION_FUNC(Num32, Int64)
+CONVERSION_FUNC(Num32, Int32)
+CONVERSION_FUNC(Num32, Int16)
+CONVERSION_FUNC(Num32, Int8)
+#undef CONVERSION_FUNC
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/builtins/nums.c b/builtins/nums.c
index f1635fd5..2efd4cbc 100644
--- a/builtins/nums.c
+++ b/builtins/nums.c
@@ -48,11 +48,11 @@ public bool Num$near(double a, double b, double ratio, double absolute) {
}
public CORD Num$format(double f, Int_t precision) {
- return CORD_asprintf("%.*f", (int)Int$as_i64(precision), f);
+ return CORD_asprintf("%.*f", (int)Int_to_Int64(precision, false), f);
}
public CORD Num$scientific(double f, Int_t precision) {
- return CORD_asprintf("%.*e", (int)Int$as_i64(precision), f);
+ return CORD_asprintf("%.*e", (int)Int_to_Int64(precision, false), f);
}
public double Num$mod(double num, double modulus) {
@@ -130,11 +130,11 @@ public bool Num32$near(float a, float b, float ratio, float absolute) {
}
public CORD Num32$format(float f, Int_t precision) {
- return CORD_asprintf("%.*f", (int)Int$as_i64(precision), f);
+ return CORD_asprintf("%.*f", (int)Int_to_Int64(precision, false), f);
}
public CORD Num32$scientific(float f, Int_t precision) {
- return CORD_asprintf("%.*e", (int)Int$as_i64(precision), f);
+ return CORD_asprintf("%.*e", (int)Int_to_Int64(precision, false), f);
}
public float Num32$mod(float num, float modulus) {
diff --git a/builtins/text.c b/builtins/text.c
index 754eef91..22784a34 100644
--- a/builtins/text.c
+++ b/builtins/text.c
@@ -255,7 +255,7 @@ public CORD Text$replace(CORD text, CORD pat, CORD replacement, Int_t int_limit)
if (!text || !pat) return text;
CORD ret = CORD_EMPTY;
size_t pos = 0, pat_len = CORD_len(pat);
- int64_t limit = Int$as_i64(int_limit);
+ int64_t limit = Int_to_Int64(int_limit, false);
for (size_t found; limit != 0 && (found=CORD_str(text, pos, pat)) != CORD_NOT_FOUND; --limit) {
ret = CORD_all(ret, CORD_substr(text, pos, found - pos), replacement);
pos = found + pat_len;
diff --git a/compile.c b/compile.c
index 1aaae695..516ca36d 100644
--- a/compile.c
+++ b/compile.c
@@ -36,8 +36,8 @@ static bool promote(env_t *env, CORD *code, type_t *actual, type_t *needed)
return true;
}
- if (actual->tag == IntType && Match(actual, IntType)->bits == 0 && needed->tag == NumType) {
- *code = CORD_all("Int$as_num(", *code, ")");
+ if (actual->tag == IntType && needed->tag == NumType) {
+ *code = CORD_all(type_to_cord(actual), "_to_", type_to_cord(needed), "(", *code, ")");
return true;
}
@@ -991,7 +991,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
if (for_->empty) {
return CORD_all(
"{\n"
- "int64_t n = Int$as_i64(", n, ");\n"
+ "int64_t n = Int_to_Int64(", n, ", false);\n"
"if (n > 0) {\n"
"for (int64_t i = 1; i <= n; ++i) {\n",
for_->vars ? CORD_all("\tInt_t ", compile(env, for_->vars->ast), " = I(i);\n") : CORD_EMPTY,
@@ -1002,7 +1002,7 @@ CORD compile_statement(env_t *env, ast_t *ast)
"\n}");
} else {
return CORD_all(
- "for (int64_t i = 1, n = Int$as_i64(", compile(env, for_->iter), "); i <= n; ++i) {\n",
+ "for (int64_t i = 1, n = Int_to_Int64(", compile(env, for_->iter), ", false); i <= n; ++i) {\n",
for_->vars ? CORD_all("\tInt_t ", compile(env, for_->vars->ast), " = I(i);\n") : CORD_EMPTY,
"\t", body,
"\n}",
@@ -1224,7 +1224,7 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t
CORD value;
if (spec_arg->type->tag == NumType && call_arg->value->tag == Int) {
Int_t int_val = Int$from_text(Match(call_arg->value, Int)->str);
- double n = Int$as_num(int_val);
+ double n = Int_to_Num(int_val);
value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == 64
? "N64(%.9g)" : "N32(%.9g)", n);
} else {
@@ -1250,7 +1250,7 @@ CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t
CORD value;
if (spec_arg->type->tag == NumType && call_arg->value->tag == Int) {
Int_t int_val = Int$from_text(Match(call_arg->value, Int)->str);
- double n = Int$as_num(int_val);
+ double n = Int_to_Num(int_val);
value = CORD_asprintf(Match(spec_arg->type, NumType)->bits == 64
? "N64(%.9g)" : "N32(%.9g)", n);
} else {
@@ -1389,7 +1389,7 @@ CORD compile(env_t *env, ast_t *ast)
if (mpz_cmpabs_ui(i, BIGGEST_SMALL_INT) <= 0) {
return CORD_asprintf("I(%s)", str);
} else if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0) {
- return CORD_asprintf("Int$from_i64(%s)", str);
+ return CORD_asprintf("Int64_to_Int(%s)", str);
} else {
return CORD_asprintf("Int$from_text(\"%s\")", str);
}
@@ -2363,28 +2363,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");
+ } else if (t->tag == NumType || (t->tag == IntType && Match(t, IntType)->bits == 0)) {
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)
- code_err(call->fn, "This constructor takes exactly 1 argument");
+ arg_t *args = new(arg_t, .name="i", .type=actual); // No truncation argument
+ CORD arg_code = compile_arguments(env, ast, args, call->args);
+ return CORD_all(type_to_cord(actual), "_to_", type_to_cord(t), "(", arg_code, ")");
+ } else if (t->tag == IntType) {
type_t *actual = get_type(env, call->args->value);
- if (actual->tag != IntType && actual->tag != NumType)
- code_err(call->args->value, "This %T value cannot be converted to a %T", actual, t);
- if (actual->tag == IntType && Match(actual, IntType)->bits == 0)
- return CORD_all("((", compile_type(t), ")", t->tag == IntType ? "Int$as_i64" : "Int$as_num", "(",
- compile(env, call->args->value), "))");
- return CORD_all("((", compile_type(t), ")(", compile(env, call->args->value), "))");
+ arg_t *args = new(arg_t, .name="i", .type=actual, .next=new(arg_t, .name="truncate", .type=Type(BoolType),
+ .default_val=FakeAST(Bool, false)));
+ CORD arg_code = compile_arguments(env, ast, args, call->args);
+ return CORD_all(type_to_cord(actual), "_to_", type_to_cord(t), "(", arg_code, ")");
} else if (t->tag == TextType) {
// Text constructor:
if (!call->args || call->args->next)
diff --git a/repl.c b/repl.c
index a9ccd8b7..289914e7 100644
--- a/repl.c
+++ b/repl.c
@@ -166,10 +166,10 @@ static Int_t ast_to_int(env_t *env, ast_t *ast)
eval(env, ast, &num);
switch (Match(t, IntType)->bits) {
case 0: return num.integer;
- case 64: return Int$from_i64((int64_t)num.i64);
- case 32: return Int$from_i64((int64_t)num.i32);
- case 16: return Int$from_i64((int64_t)num.i16);
- case 8: return Int$from_i64((int64_t)num.i8);
+ case 64: return Int64_to_Int((int64_t)num.i64);
+ case 32: return Int32_to_Int(num.i32);
+ case 16: return Int16_to_Int(num.i16);
+ case 8: return Int8_to_Int(num.i8);
default: errx(1, "Invalid int bits");
}
}
@@ -185,7 +185,7 @@ static double ast_to_num(env_t *env, ast_t *ast)
number_t num;
eval(env, ast, &num);
switch (Match(t, IntType)->bits) {
- case 0: return Int$as_num(num.integer);
+ case 0: return Int_to_Num(num.integer);
case 64: return (double)num.i64;
case 32: return (double)num.i32;
case 16: return (double)num.i16;
@@ -395,10 +395,10 @@ void eval(env_t *env, ast_t *ast, void *dest)
Int_t result = Int$ ## method_name (lhs, rhs); \
switch (Match(t, IntType)->bits) { \
case 0: *(Int_t*)dest = result; return; \
- case 64: *(int64_t*)dest = (int64_t)Int$as_i64(result); return; \
- case 32: *(int32_t*)dest = (int32_t)Int$as_i64(result); return; \
- case 16: *(int16_t*)dest = (int16_t)Int$as_i64(result); return; \
- case 8: *(int8_t*)dest = (int8_t)Int$as_i64(result); return; \
+ case 64: *(int64_t*)dest = Int_to_Int64(result, false); return; \
+ case 32: *(int32_t*)dest = Int_to_Int32(result, false); return; \
+ case 16: *(int16_t*)dest = Int_to_Int16(result, false); return; \
+ case 8: *(int8_t*)dest = Int_to_Int8(result, false); return; \
default: errx(1, "Invalid int bits"); \
} \
break; \
@@ -461,7 +461,7 @@ void eval(env_t *env, ast_t *ast, void *dest)
case ArrayType: {
array_t arr;
eval(env, index->indexed, &arr);
- int64_t raw_index = Int$as_i64(ast_to_int(env, index->index));
+ int64_t raw_index = Int_to_Int64(ast_to_int(env, index->index), false);
int64_t index_int = raw_index;
if (index_int < 1) index_int = arr.length + index_int + 1;
if (index_int < 1 || index_int > arr.length)