Skip to content

Commit f9403dc

Browse files
authored
Several more clojure-test-suite fixes (#116)
* symbol implements ifn, regen code after set fix Signed-off-by: James Hamlin <[email protected]> * Fix ratio -> int Signed-off-by: James Hamlin <[email protected]> * Read zero ratios as 0 ints Signed-off-by: James Hamlin <[email protected]> * Support intern Signed-off-by: James Hamlin <[email protected]> * Fix for keys/vals and keyword namespace Signed-off-by: James Hamlin <[email protected]> * Fixes for mod Signed-off-by: James Hamlin <[email protected]> * Add sym method to keyword Signed-off-by: James Hamlin <[email protected]> * Fixes for nth Signed-off-by: James Hamlin <[email protected]> * Fix for long range count Signed-off-by: James Hamlin <[email protected]> * Implement rationalize Signed-off-by: James Hamlin <[email protected]> * Fix prefixed map regression Signed-off-by: James Hamlin <[email protected]> --------- Signed-off-by: James Hamlin <[email protected]>
1 parent 80dc1ff commit f9403dc

File tree

16 files changed

+151
-215
lines changed

16 files changed

+151
-215
lines changed

pkg/lang/bigdecimal.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,17 @@ import (
77
"bitbucket.org/pcastools/hash"
88
)
99

10-
// BigDec is an arbitrary-precision decimal number. It wraps and has
11-
// the same semantics as big.Float. big.Float is not used directly
12-
// because it is mutable, and the core BigDecimal should not be.
10+
// BigDec is an arbitrary-precision floating point number. It wraps
11+
// and has the same semantics as big.Float. big.Float is not used
12+
// directly because it is mutable, and the core BigDecimal should not
13+
// be.
14+
//
15+
// TODO: swap out with a *decimal* representation. The go standard
16+
// library big.Float is a binary floating point representation,
17+
// which means that some decimal fractions cannot be represented
18+
// exactly. This can lead to unexpected results when doing
19+
// arithmetic with decimal fractions. A decimal representation
20+
// would avoid this problem.
1321
type BigDecimal struct {
1422
val *big.Float
1523
}
@@ -107,7 +115,12 @@ func (n *BigDecimal) Quotient(other *BigDecimal) *BigDecimal {
107115
}
108116

109117
func (n *BigDecimal) Remainder(other *BigDecimal) *BigDecimal {
110-
panic("not implemented")
118+
quotient := new(big.Float).Quo(n.val, other.val)
119+
intQuotient, _ := quotient.Int(nil)
120+
intQuotientFloat := new(big.Float).SetInt(intQuotient)
121+
product := new(big.Float).Mul(intQuotientFloat, other.val)
122+
remainder := new(big.Float).Sub(n.val, product)
123+
return &BigDecimal{val: remainder}
111124
}
112125

113126
func (n *BigDecimal) Cmp(other *BigDecimal) int {

pkg/lang/equals_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func TestEquiv(t *testing.T) {
2020
{NewMap(1, 2).Seq(), NewVector(NewList(1, 2)), NewList(NewVector(1, 2))},
2121
// empty lazy seqs are equal
2222
{NewLazySeq(func() interface{} { return nil }), NewLazySeq(func() interface{} { return nil })},
23+
{NewList(1, 2), NewLongRange(0, 3, 1).Next()},
2324
}
2425

2526
for _, els := range equivs {

pkg/lang/interfaces.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -486,12 +486,14 @@ func Count(coll any) int {
486486
return count
487487
}
488488

489-
func Keys(m Associative) ISeq {
490-
return NewMapKeySeq(Seq(m))
489+
func Keys(x any) ISeq {
490+
// TODO: optimize for map case
491+
return NewMapKeySeq(Seq(x))
491492
}
492493

493-
func Vals(m Associative) ISeq {
494-
return NewMapValSeq(Seq(m))
494+
func Vals(x any) ISeq {
495+
// TODO: optimize for map case
496+
return NewMapValSeq(Seq(x))
495497
}
496498

497499
func Subvec(v IPersistentVector, start, end int) IPersistentVector {

pkg/lang/iteration.go

Lines changed: 7 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,15 @@ func MustNth(x interface{}, i int) interface{} {
2323

2424
func Nth(x interface{}, n int) (interface{}, bool) {
2525
switch x := x.(type) {
26+
// Deprecate this
2627
case Nther:
2728
return x.Nth(n)
29+
case Indexed:
30+
val := x.NthDefault(n, notFound)
31+
if val == notFound {
32+
return nil, false
33+
}
34+
return val, true
2835
case ISeq:
2936
x = Seq(x)
3037
for i := 0; i <= n; i++ {
@@ -61,156 +68,3 @@ func Nth(x interface{}, n int) (interface{}, bool) {
6168

6269
return nil, false
6370
}
64-
65-
// // NewIterator returns a lazy sequence of x, f(x), f(f(x)), ....
66-
// func NewIterator(f func(interface{}) interface{}, x interface{}) ISeq {
67-
// return iterator{f: f, x: x}
68-
// }
69-
70-
// type iterator struct {
71-
// f func(interface{}) interface{}
72-
// x interface{}
73-
// }
74-
75-
// func (i iterator) xxx_sequential() {}
76-
77-
// func (i iterator) Seq() ISeq {
78-
// return i
79-
// }
80-
81-
// func (i iterator) First() interface{} {
82-
// return i.x
83-
// }
84-
85-
// func (i iterator) Next() ISeq {
86-
// return NewIterator(i.f, i.f(i.x))
87-
// }
88-
89-
// func (i iterator) More() ISeq {
90-
// nxt := i.Next()
91-
// if nxt == nil {
92-
// return emptyList
93-
// }
94-
// return nxt
95-
// }
96-
97-
// // NewValueIterator returns a lazy sequence of the values of x.
98-
// func NewVectorIterator(x IPersistentVector, start, step int) ISeq {
99-
// if x.Count() == 0 {
100-
// return emptyList
101-
// }
102-
// return vectorIterator{v: x, start: start, step: step}
103-
// }
104-
105-
// type vectorIterator struct {
106-
// v IPersistentVector
107-
// start int
108-
// step int
109-
// }
110-
111-
// func (it vectorIterator) xxx_sequential() {}
112-
113-
// func (it vectorIterator) Seq() ISeq {
114-
// return it
115-
// }
116-
117-
// func (it vectorIterator) First() interface{} {
118-
// return it.v.Nth(it.start)
119-
// }
120-
121-
// func (it vectorIterator) Next() ISeq {
122-
// next := it.start + it.step
123-
// if next >= it.v.Count() || next < 0 {
124-
// return nil
125-
// }
126-
// return &vectorIterator{v: it.v, start: next, step: it.step}
127-
// }
128-
129-
// func (it vectorIterator) More() ISeq {
130-
// nxt := it.Next()
131-
// if nxt == nil {
132-
// return emptyList
133-
// }
134-
// return nxt
135-
// }
136-
137-
// // NewConcatIterator returns a sequence concatenating the given
138-
// // sequences.
139-
// func NewConcatIterator(colls ...interface{}) ISeq {
140-
// var it *concatIterator
141-
// for i := len(colls) - 1; i >= 0; i-- {
142-
// iseq := Seq(colls[i])
143-
// if iseq == nil {
144-
// continue
145-
// }
146-
// it = &concatIterator{seq: iseq, next: it}
147-
// }
148-
// if it == nil {
149-
// return emptyList
150-
// }
151-
// return it
152-
// }
153-
154-
// type concatIterator struct {
155-
// seq ISeq
156-
// next *concatIterator
157-
// }
158-
159-
// func (i *concatIterator) xxx_sequential() {}
160-
161-
// func (i *concatIterator) Seq() ISeq {
162-
// return i
163-
// }
164-
165-
// func (i *concatIterator) First() interface{} {
166-
// return i.seq.First()
167-
// }
168-
169-
// func (i *concatIterator) Next() ISeq {
170-
// i = &concatIterator{seq: i.seq.Next(), next: i.next}
171-
// for i.seq == nil {
172-
// i = i.next
173-
// if i == nil {
174-
// return nil
175-
// }
176-
// }
177-
// return i
178-
// }
179-
180-
// func (i *concatIterator) More() ISeq {
181-
// nxt := i.Next()
182-
// if nxt == nil {
183-
// return emptyList
184-
// }
185-
// return nxt
186-
// }
187-
188-
// ////////////////////////////////////////////////////////////////////////////////
189-
190-
// func chunkIteratorSeq(iter *reflect.MapIter) ISeq {
191-
// const chunkSize = 32
192-
193-
// return NewLazySeq(func() interface{} {
194-
// chunk := make([]interface{}, 0, chunkSize)
195-
// exhausted := false
196-
// for n := 0; n < chunkSize; n++ {
197-
// chunk = append(chunk, NewMapEntry(iter.Key().Interface(), iter.Value().Interface()))
198-
// if !iter.Next() {
199-
// exhausted = true
200-
// break
201-
// }
202-
// }
203-
// if exhausted {
204-
// return NewChunkedCons(NewSliceChunk(chunk), nil)
205-
// }
206-
// return NewChunkedCons(NewSliceChunk(chunk), chunkIteratorSeq(iter))
207-
// })
208-
// }
209-
210-
// func NewGoMapSeq(x interface{}) ISeq {
211-
// rng := reflect.ValueOf(x).MapRange()
212-
// if !rng.Next() {
213-
// return nil
214-
// }
215-
// return chunkIteratorSeq(rng)
216-
// }

pkg/lang/keyword.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ func (k Keyword) value() string {
4343
return k.kw.Get().(string)
4444
}
4545

46-
func (k Keyword) Namespace() string {
47-
// Return the namespace of the keyword, or the empty string if it
48-
// doesn't have one.
46+
func (k Keyword) Namespace() any {
47+
// Return the namespace of the keyword, or nil if it doesn't have
48+
// one.
49+
// TODO: support both nil and empty string namespace as clojure does
4950
if i := strings.Index(k.value(), "/"); i != -1 {
5051
return k.value()[:i]
5152
}
52-
return ""
53+
return nil
5354
}
5455

5556
func (k Keyword) Name() string {
@@ -61,6 +62,10 @@ func (k Keyword) Name() string {
6162
return k.value()
6263
}
6364

65+
func (k Keyword) Sym() *Symbol {
66+
return InternSymbol(k.Namespace(), k.Name())
67+
}
68+
6469
func (k Keyword) String() string {
6570
return ":" + k.value()
6671
}
@@ -106,14 +111,14 @@ func (k Keyword) Compare(other any) int {
106111
if s == os {
107112
return 0
108113
}
109-
ns := k.Namespace()
110-
if ns == "" {
111-
if otherKw.Namespace() != "" {
114+
ns, ok := k.Namespace().(string)
115+
if !ok {
116+
if otherKw.Namespace() != nil {
112117
return -1
113118
}
114119
} else {
115-
ons := otherKw.Namespace()
116-
if ons == "" {
120+
ons, ok := otherKw.Namespace().(string)
121+
if !ok {
117122
return 1
118123
}
119124
nsc := strings.Compare(ns, ons)

pkg/lang/longrange.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (r *LongRange) Next() ISeq {
104104
if next >= r.end {
105105
return nil
106106
}
107-
return &LongRange{start: next, end: r.end, step: r.step}
107+
return &LongRange{start: next, end: r.end, step: r.step, count: r.count - 1}
108108
}
109109

110110
func (r *LongRange) More() ISeq {

pkg/lang/numberops.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -427,16 +427,20 @@ func (o ratioOps) Quotient(x, y any) any {
427427
return AsRatio(x).Quotient(AsRatio(y))
428428
}
429429
func (o ratioOps) Remainder(x, y any) any {
430-
xRat := AsRatio(x)
431-
yRat := AsRatio(y)
430+
xRat := AsRatio(x).val
431+
yRat := AsRatio(y).val
432432

433-
q := new(big.Int)
434-
q.Mul(xRat.val.Num(), yRat.val.Denom())
433+
// BigInteger q = rx.numerator.multiply(ry.denominator).divide(
434+
// rx.denominator.multiply(ry.numerator));
435+
// Number ret = Numbers.minus(x, Numbers.multiply(q, y));
436+
// return ret
435437

436-
qd := new(big.Int)
437-
qd.Mul(xRat.val.Denom(), yRat.val.Num())
438+
// result should be a BigInt
439+
qn := new(big.Int).Mul(xRat.Num(), yRat.Denom())
440+
qd := new(big.Int).Mul(xRat.Denom(), yRat.Num())
441+
rem := new(big.Int)
442+
q, rem := qn.QuoRem(qn, qd, rem)
438443

439-
q.Div(q, qd)
440444
return Sub(x, Multiply(q, y))
441445
}
442446
func (o ratioOps) LT(x, y any) bool {

pkg/lang/numbers.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ func (nm *NumberMethods) Remainder(x, y any) any {
9898
return Ops(x).Combine(yops).Remainder(x, y)
9999
}
100100

101+
func (nm *NumberMethods) Rationalize(x any) any {
102+
switch x := x.(type) {
103+
case float32:
104+
return nm.Rationalize(NewBigDecimalFromFloat64(float64(x)))
105+
case float64:
106+
return nm.Rationalize(NewBigDecimalFromFloat64(x))
107+
case *BigDecimal:
108+
bx := x.val
109+
rat, _ := bx.Rat(nil)
110+
if rat.IsInt() {
111+
return NewBigIntFromGoBigInt(rat.Num())
112+
}
113+
return &Ratio{val: rat}
114+
}
115+
if !IsNumber(x) {
116+
panic(fmt.Errorf("cannot rationalize %T", x))
117+
}
118+
return x
119+
}
120+
101121
func (nm *NumberMethods) And(x, y any) any {
102122
return bitOpsCast(x) & bitOpsCast(y)
103123
}

pkg/lang/persistentarraymap.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ func (s *MapSeq) Drop(n int) Sequential {
490490
////////////////////////////////////////////////////////////////////////////////
491491

492492
func NewMapKeySeq(s ISeq) ISeq {
493-
if s == nil {
493+
if IsNil(s) {
494494
return nil
495495
}
496496
return &MapKeySeq{s: s}
@@ -566,7 +566,7 @@ func (s *MapKeySeq) HashEq() uint32 {
566566
////////////////////////////////////////////////////////////////////////////////
567567

568568
func NewMapValSeq(s ISeq) ISeq {
569-
if s == nil {
569+
if IsNil(s) {
570570
return nil
571571
}
572572
return &MapValSeq{s: s}

pkg/lang/ratio.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ func (r *Ratio) Denominator() *big.Int {
3737
}
3838

3939
func (r *Ratio) BigIntegerValue() *big.Int {
40-
return new(big.Int).Div(r.val.Num(), r.val.Denom())
40+
var tmp big.Int
41+
res, _ := new(big.Int).QuoRem(r.val.Num(), r.val.Denom(), &tmp)
42+
return res
4143
}
4244

4345
func (r *Ratio) String() string {

0 commit comments

Comments
 (0)