Skip to content

Commit 851172e

Browse files
authored
Fix equality for integers and floats (#89)
* fix equality for integers and floats * remove warning * handle more equality cases * pointer equality on bignums
1 parent c593836 commit 851172e

File tree

6 files changed

+176
-117
lines changed

6 files changed

+176
-117
lines changed

cogs/r5rs.scm

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@
190190

191191
(check-equal? "equality with float and int" #f (equal? 2.0 2))
192192

193+
(check-equal? "numeric equality with float and int" #t (= 1 1.0))
194+
195+
(check-equal? "pointer equality with int and int" #t (eq? 1 1))
196+
197+
(check-equal? "pointer equality with floats" #t (eq? 1.0 1.0))
198+
199+
(check-equal? "numeric equality with float and float" #t (= 1.0 1.0))
200+
193201
(skip-compile (check-equal #f (eqv? 2 2.0))
194202
;; TODO: Add make-vector function
195203
(check-equal #t (equal? (make-vector 5 'a) (make-vector 5 'a))))
@@ -475,11 +483,13 @@
475483
; (s a b c))))
476484
(check-equal 'ok
477485
(let ()
478-
(let-syntax () (define internal-def 'ok))
486+
(let-syntax ()
487+
(define internal-def 'ok))
479488
internal-def))
480489
(check-equal 'ok
481490
(let ()
482-
(letrec-syntax () (define internal-def 'ok))
491+
(letrec-syntax ()
492+
(define internal-def 'ok))
483493
internal-def)))
484494

485495
; TODO: This causes a free identifier error

cogs/sorting/trie-sort.scm

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,84 +8,77 @@
88

99
;; Throw in a mediocre flatten definition
1010
(define (flatten lst)
11-
(cond ((null? lst) empty)
12-
((list? lst)
13-
(append (flatten (car lst)) (flatten (cdr lst))))
14-
(else (list lst))))
11+
(cond
12+
[(null? lst) empty]
13+
[(list? lst) (append (flatten (car lst)) (flatten (cdr lst)))]
14+
[else (list lst)]))
1515

1616
;; contract: (listof char?) (listof tries?) integer? -> (listof trie?)
1717
(define (create-children char-list lst prefix-chars)
18-
(cond [(= (length char-list) 1)
19-
(handle-last-letter char-list lst prefix-chars)]
20-
[else ;; you are in the middle of the word
21-
(handle-intern-letter char-list lst prefix-chars)]))
18+
(cond
19+
[(= (length char-list) 1) (handle-last-letter char-list lst prefix-chars)]
20+
;; you are in the middle of the word
21+
[else (handle-intern-letter char-list lst prefix-chars)]))
2222

2323
;; contract: (listof char?) (listof trie?) integer? -> (listof trie?)
2424
(define (handle-last-letter char-list lst prefix-chars)
2525
(define char (first char-list))
26-
; (define next-prefix (append prefix-chars (list char)))
26+
; (define next-prefix (append prefix-chars (list char)))
2727
(define next-prefix (push-back prefix-chars char))
28-
(cond [(empty? lst) ;; children are empty, return list of empty children
29-
(list (trie char empty #t next-prefix))]
30-
[(< char (trie-char (first lst))) ;; less than, put it to the left
31-
(cons (trie char empty #t next-prefix) lst)]
32-
[(= char (trie-char (first lst))) ;; equal, step down a level
33-
(cons (trie char (trie-children (first lst)) #t next-prefix) (rest lst))]
34-
[else ;; move to the right
35-
(cons (first lst)
36-
(create-children char-list (rest lst) prefix-chars))]))
28+
(cond
29+
;; children are empty, return list of empty children
30+
[(empty? lst) (list (trie char empty #t next-prefix))]
31+
;; less than, put it to the left
32+
[(< char (trie-char (first lst))) (cons (trie char empty #t next-prefix) lst)]
33+
[(equal? char (trie-char (first lst))) ;; equal, step down a level
34+
(cons (trie char (trie-children (first lst)) #t next-prefix) (rest lst))]
35+
;; move to the right
36+
[else (cons (first lst) (create-children char-list (rest lst) prefix-chars))]))
3737

3838
;; contract: (listof char?) (listof trie?) integer? -> (listof trie?)
3939
(define (handle-intern-letter char-list lst prefix-chars)
4040
(define char (first char-list))
41-
; (define next-prefix (append prefix-chars (list char)))
41+
; (define next-prefix (append prefix-chars (list char)))
4242
(define next-prefix (push-back prefix-chars char))
43-
(cond [(empty? lst) ;; no children, pop off front and step down
44-
(list (trie char (create-children
45-
(rest char-list) empty next-prefix) #f next-prefix))]
46-
[(< char (trie-char (first lst))) ;; place where it is, pop off front and go
47-
(cons (trie char (create-children
48-
(rest char-list) empty next-prefix) #f next-prefix) lst)]
49-
[(= char (trie-char (first lst))) ;; equal, step down
50-
(cons (trie char (create-children (rest char-list) (trie-children (first lst)) next-prefix)
51-
(trie-end-word? (first lst))
52-
(trie-word-up-to (first lst)))
53-
(rest lst))]
54-
[else ; move to the right
55-
(cons (first lst)
56-
(create-children char-list (rest lst) prefix-chars))]))
43+
(cond
44+
[(empty? lst) ;; no children, pop off front and step down
45+
(list (trie char (create-children (rest char-list) empty next-prefix) #f next-prefix))]
46+
[(< char (trie-char (first lst))) ;; place where it is, pop off front and go
47+
(cons (trie char (create-children (rest char-list) empty next-prefix) #f next-prefix) lst)]
48+
[(equal? char (trie-char (first lst))) ;; equal, step down
49+
(cons (trie char
50+
(create-children (rest char-list) (trie-children (first lst)) next-prefix)
51+
(trie-end-word? (first lst))
52+
(trie-word-up-to (first lst)))
53+
(rest lst))]
54+
; move to the right
55+
[else (cons (first lst) (create-children char-list (rest lst) prefix-chars))]))
5756

5857
;; contract: trie? string? integer? -> trie?
5958
(define (insert root-trie word)
6059
(define char-list (string->list word))
61-
(trie
62-
(trie-char root-trie)
63-
(create-children char-list (trie-children root-trie) empty)
64-
(trie-end-word? root-trie)
65-
(trie-word-up-to root-trie)))
60+
(trie (trie-char root-trie)
61+
(create-children char-list (trie-children root-trie) empty)
62+
(trie-end-word? root-trie)
63+
(trie-word-up-to root-trie)))
6664

6765
;; contract: trie? trie? -> boolean?
6866
(define (trie<? trie-node1 trie-node2)
6967
(< (trie-char trie-node1) (trie-char trie-node2)))
7068

71-
7269
;; contract: trie? (listof string?) -> trie?
7370
(define (build-trie-from-list-of-words trie list-of-words)
7471
(cond
75-
[(= (length list-of-words) 1)
76-
(insert trie (first list-of-words))]
77-
[else
78-
(build-trie-from-list-of-words
79-
(insert trie (first list-of-words))
80-
(rest list-of-words))]))
72+
[(= (length list-of-words) 1) (insert trie (first list-of-words))]
73+
[else (build-trie-from-list-of-words (insert trie (first list-of-words)) (rest list-of-words))]))
8174

8275
;; ------------------ SORTING ---------------------- ;;
8376

8477
(define (trie-sort list-of-words)
8578
(define new-trie (build-trie-from-list-of-words empty-trie list-of-words))
8679
(pre-order new-trie))
8780

88-
;; THIS ONE WORKS (using con and flatten)
81+
;; THIS ONE WORKS (using con and flatten)
8982
;; contract: trie? -> (listof string?)
9083
(define (pre-order trie-node)
9184
(if (trie-end-word? trie-node)

crates/steel-core/src/rvals.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ use futures_util::future::Shared;
6969
use futures_util::FutureExt;
7070

7171
use im_lists::list::List;
72+
use num::ToPrimitive;
7273
use steel_parser::tokens::MaybeBigInt;
7374

7475
use self::cycles::CycleDetector;
@@ -1253,6 +1254,9 @@ impl SteelVal {
12531254

12541255
pub(crate) fn ptr_eq(&self, other: &SteelVal) -> bool {
12551256
match (self, other) {
1257+
// Integers are a special case of ptr eq -> if integers are equal? they are also eq?
1258+
(IntV(l), IntV(r)) => l == r,
1259+
(NumV(l), NumV(r)) => l == r,
12561260
(BoolV(l), BoolV(r)) => l == r,
12571261
(VectorV(l), VectorV(r)) => Gc::ptr_eq(l, r),
12581262
(Void, Void) => true,
@@ -1279,6 +1283,7 @@ impl SteelVal {
12791283
(MutFunc(l), MutFunc(r)) => *l as usize == *r as usize,
12801284
(BuiltIn(l), BuiltIn(r)) => *l as usize == *r as usize,
12811285
(MutableVector(l), MutableVector(r)) => Gc::ptr_eq(l, r),
1286+
(BigNum(l), BigNum(r)) => Gc::ptr_eq(l, r),
12821287
(_, _) => false,
12831288
}
12841289
}
@@ -1627,6 +1632,46 @@ impl SteelVal {
16271632

16281633
impl Eq for SteelVal {}
16291634

1635+
fn integer_float_equality(int: isize, float: f64) -> bool {
1636+
let converted = float as isize;
1637+
1638+
if float == converted as f64 {
1639+
int == converted
1640+
} else {
1641+
false
1642+
}
1643+
}
1644+
1645+
fn bignum_float_equality(bigint: &Gc<num::BigInt>, float: f64) -> bool {
1646+
if float.fract() == 0.0 {
1647+
if let Some(promoted) = bigint.to_f64() {
1648+
promoted == float
1649+
} else {
1650+
false
1651+
}
1652+
} else {
1653+
false
1654+
}
1655+
}
1656+
1657+
#[steel_derive::function(name = "=", constant = true)]
1658+
pub fn number_equality(left: &SteelVal, right: &SteelVal) -> Result<SteelVal> {
1659+
let result = match (left, right) {
1660+
(IntV(l), IntV(r)) => l == r,
1661+
(NumV(l), NumV(r)) => l == r,
1662+
(IntV(l), NumV(r)) | (NumV(r), IntV(l)) => integer_float_equality(*l, *r),
1663+
(BigNum(l), BigNum(r)) => l == r,
1664+
(BigNum(l), NumV(r)) | (NumV(r), BigNum(l)) => bignum_float_equality(l, *r),
1665+
1666+
// Should be impossible to have an integer and a bignum be the same value
1667+
(IntV(_), BigNum(_)) | (BigNum(_), IntV(_)) => false,
1668+
1669+
_ => stop!(TypeMismatch => "= expects two numbers, found: {:?} and {:?}", left, right),
1670+
};
1671+
1672+
Ok(SteelVal::BoolV(result))
1673+
}
1674+
16301675
// TODO add tests
16311676
impl PartialEq for SteelVal {
16321677
fn eq(&self, other: &Self) -> bool {
@@ -1636,6 +1681,10 @@ impl PartialEq for SteelVal {
16361681
(BigNum(l), BigNum(r)) => l == r,
16371682
// (NumV(l), NumV(r)) => l == r,
16381683
(IntV(l), IntV(r)) => l == r,
1684+
1685+
// Floats shouls also be considered equal
1686+
(NumV(l), NumV(r)) => l == r,
1687+
16391688
// (NumV(l), IntV(r)) => *l == *r as f64,
16401689
// (IntV(l), NumV(r)) => *l as f64 == *r,
16411690
(StringV(l), StringV(r)) => l == r,

crates/steel-core/src/steel_vm/contracts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl ContractedFunction {
2323
{
2424
let mut parent = self.contract.parent();
2525
while let Some(p) = parent {
26-
println!("Applying parents");
26+
// println!("Applying parents");
2727
p.apply(&self.name, &self.function, &arguments, cur_inst_span, ctx)?;
2828

2929
parent = p.parent()

crates/steel-core/src/steel_vm/primitives.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
StreamOperations, SymbolOperations, VectorOperations,
2727
},
2828
rerrs::ErrorKind,
29-
rvals::FromSteelVal,
29+
rvals::{FromSteelVal, NUMBER_EQUALITY_DEFINITION},
3030
steel_vm::{
3131
builtin::{get_function_name, Arity},
3232
vm::threads::threading_module,
@@ -751,7 +751,11 @@ fn equality_module() -> BuiltInModule {
751751
|a: &SteelVal, b: &SteelVal| a.ptr_eq(b)
752752
)),
753753
)
754-
.register_value("=", SteelVal::FuncV(ensure_tonicity_two!(|a, b| a == b)));
754+
.register_native_fn_definition(NUMBER_EQUALITY_DEFINITION);
755+
756+
// TODO: Replace this with just numeric equality!
757+
// .register_value("=", SteelVal::FuncV(ensure_tonicity_two!(|a, b| a == b)));
758+
755759
module
756760
}
757761

0 commit comments

Comments
 (0)