aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2026-01-11 19:08:32 -0500
committerBruce Hill <bruce@bruce-hill.com>2026-01-11 19:08:32 -0500
commit6068a746896407b5ef33bca72a8be6fced14439b (patch)
treeb2eaae9885555148b45c9de3d4d719fbf3ce3550
parent479788ab3a9297fc68fc6f753241291ba37a7539 (diff)
Implement some missing logic for reals
-rw-r--r--src/compile/comparisons.c3
-rw-r--r--src/compile/expressions.c5
-rw-r--r--src/stdlib/reals.c34
-rw-r--r--src/stdlib/reals.h2
4 files changed, 31 insertions, 13 deletions
diff --git a/src/compile/comparisons.c b/src/compile/comparisons.c
index afb5dc15..99f220e3 100644
--- a/src/compile/comparisons.c
+++ b/src/compile/comparisons.c
@@ -50,6 +50,8 @@ Text_t compile_comparison(env_t *env, ast_t *ast) {
switch (operand_t->tag) {
case BigIntType:
return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Int$equal_value(", lhs, ", ", rhs, ")");
+ case RealType:
+ return Texts(ast->tag == Equals ? EMPTY_TEXT : Text("!"), "Real$equal_values(", lhs, ", ", rhs, ")");
case BoolType:
case ByteType:
case IntType:
@@ -94,6 +96,7 @@ Text_t compile_comparison(env_t *env, ast_t *ast) {
const char *op = comparison_operator(ast->tag);
switch (operand_t->tag) {
case BigIntType: return Texts("(Int$compare_value(", lhs, ", ", rhs, ") ", op, " 0)");
+ case RealType: return Texts("(Real$compare_values(", lhs, ", ", rhs, ") ", op, " 0)");
case BoolType:
case ByteType:
case IntType:
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index e2c1d68a..321f5f9f 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -85,6 +85,7 @@ Text_t compile_empty(type_t *t) {
case FloatType: {
return Match(t, FloatType)->bits == TYPE_NBITS32 ? Text("F32(0.0f)") : Text("F64(0.0)");
}
+ case RealType: return Text("Real$from_float64(0.0)");
case StructType: return compile_empty_struct(t);
case EnumType: return compile_empty_enum(t);
default: return EMPTY_TEXT;
@@ -157,7 +158,7 @@ Text_t compile(env_t *env, ast_t *ast) {
return Texts(b->code, "(", compile_arguments(env, ast, fn->args, new (arg_ast_t, .value = value)), ")");
}
- if (t->tag == IntType || t->tag == FloatType) return Texts("-(", compile(env, value), ")");
+ if (t->tag == IntType || t->tag == FloatType || t->tag == RealType) return Texts("-(", compile(env, value), ")");
code_err(ast, "I don't know how to get the negative value of type ", type_to_text(t));
}
@@ -213,6 +214,8 @@ Text_t compile(env_t *env, ast_t *ast) {
if (key_t->tag == BigIntType)
comparison =
Texts("(Int$compare_value(", lhs_key, ", ", rhs_key, ")", (ast->tag == Min ? "<=" : ">="), "0)");
+ else if (key_t->tag == RealType)
+ comparison = Texts("(Real$compare_values(", lhs_key, ", ", rhs_key, ")", (ast->tag == Min ? "<=" : ">="), "0)");
else if (key_t->tag == IntType || key_t->tag == FloatType || key_t->tag == BoolType || key_t->tag == PointerType
|| key_t->tag == ByteType)
comparison = Texts("((", lhs_key, ")", (ast->tag == Min ? "<=" : ">="), "(", rhs_key, "))");
diff --git a/src/stdlib/reals.c b/src/stdlib/reals.c
index 824401c7..e9a6b2ef 100644
--- a/src/stdlib/reals.c
+++ b/src/stdlib/reals.c
@@ -291,7 +291,7 @@ Real_t Real$times(Real_t a, Real_t b) {
return sa->left;
}
// Also check if arguments are equal values (not just pointers)
- if (Real$equal(&sa->left, &sb->left, NULL)) {
+ if (Real$equal_values(sa->left, sb->left)) {
return sa->left;
}
}
@@ -414,13 +414,13 @@ Real_t Real$mix(Real_t amount, Real_t x, Real_t y) {
public
bool Real$is_between(Real_t x, Real_t low, Real_t high) {
- return Real$compare(&low, &x, NULL) <= 0 && Real$compare(&x, &high, NULL) <= 0;
+ return Real$compare_values(low, x) <= 0 && Real$compare_values(x, high) <= 0;
}
public
Real_t Real$clamped(Real_t x, Real_t low, Real_t high) {
- if (Real$compare(&x, &low, NULL) <= 0) return low;
- if (Real$compare(&x, &high, NULL) >= 0) return high;
+ if (Real$compare_values(x, low) <= 0) return low;
+ if (Real$compare_values(x, high) >= 0) return high;
return x;
}
@@ -814,10 +814,7 @@ PUREFUNC bool Real$is_none(const void *vn, const TypeInfo_t *type) {
// Equality check (may be undecidable for some symbolics)
public
-bool Real$equal(const void *va, const void *vb, const TypeInfo_t *t) {
- (void)t;
- Real_t a = *(Real_t *)va;
- Real_t b = *(Real_t *)vb;
+bool Real$equal_values(Real_t a, Real_t b) {
if (!Real$is_boxed(a) && !Real$is_boxed(b)) return a.d == b.d;
if (Real$is_boxed(a) != Real$is_boxed(b)) return 0;
@@ -834,6 +831,14 @@ bool Real$equal(const void *va, const void *vb, const TypeInfo_t *t) {
}
public
+bool Real$equal(const void *va, const void *vb, const TypeInfo_t *t) {
+ (void)t;
+ Real_t a = *(Real_t *)va;
+ Real_t b = *(Real_t *)vb;
+ return Real$equal_values(a, b);
+}
+
+public
uint64_t Real$hash(const void *vr, const TypeInfo_t *type) {
(void)type;
Text_t text = Real$value_as_text(*(Real_t *)vr);
@@ -842,10 +847,7 @@ uint64_t Real$hash(const void *vr, const TypeInfo_t *type) {
// Comparison: -1 (less), 0 (equal), 1 (greater)
public
-int32_t Real$compare(const void *va, const void *vb, const TypeInfo_t *t) {
- (void)t;
- Real_t a = *(Real_t *)va;
- Real_t b = *(Real_t *)vb;
+int32_t Real$compare_values(Real_t a, Real_t b) {
if (!Real$is_boxed(a) && !Real$is_boxed(b)) {
return (a.d > b.d) - (a.d < b.d);
}
@@ -861,6 +863,14 @@ int32_t Real$compare(const void *va, const void *vb, const TypeInfo_t *t) {
return (da > db) - (da < db);
}
+public
+int32_t Real$compare(const void *va, const void *vb, const TypeInfo_t *t) {
+ (void)t;
+ Real_t a = *(Real_t *)va;
+ Real_t b = *(Real_t *)vb;
+ return Real$compare_values(a, b);
+}
+
// Unary negation
public
Real_t Real$negative(Real_t a) {
diff --git a/src/stdlib/reals.h b/src/stdlib/reals.h
index 6d30063e..e6d47f5c 100644
--- a/src/stdlib/reals.h
+++ b/src/stdlib/reals.h
@@ -57,10 +57,12 @@ Real_t Real$times(Real_t x, Real_t y);
Text_t Real$as_text(const void *n, bool colorize, const TypeInfo_t *type);
Text_t Real$value_as_text(Real_t x);
bool Real$equal(const void *va, const void *vb, const TypeInfo_t *t);
+bool Real$equal_values(Real_t a, Real_t b);
bool Real$get_rational(Real_t x, int64_t *num, int64_t *den);
bool Real$is_between(Real_t x, Real_t low, Real_t high);
double Real$as_float64(Real_t n, bool truncate);
int32_t Real$compare(const void *va, const void *vb, const TypeInfo_t *t);
+int32_t Real$compare_values(Real_t a, Real_t b);
int Real$test();