Skip to content

Commit dff995e

Browse files
committed
plain testing, constvals revamp, slice revamp
it turns out we need the zero value of indexing.I to be decodable. This commit does not quite achieve this, but fixes numerous bugs and provides a better model of slices // Slices are modelled as follows. // // Each slice `s` has a principal pointer `ptr(s)` stored in object.loc, and a Len and a Cap // which are of type indexing.I, and a single memory.Loc "elem" representing // what is stored in the slice. // // Each slice has 0 or more slots. A slot is a triple (p, m, i) such that // 1. p = &m // 2. p = ptr(s) + i // // For the moment, we set ptr(s) == &nil to guarantee that nil derefs // are considered possible. When indexing gets richer, perhaps we // can do more.
1 parent ad59631 commit dff995e

File tree

11 files changed

+251
-60
lines changed

11 files changed

+251
-60
lines changed

indexing/constvals.go

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ package indexing
1717
import (
1818
"fmt"
1919
"io"
20-
"strconv"
2120

21+
"github.com/go-air/pal/internal/plain"
2222
"github.com/go-air/pal/xtruth"
2323
)
2424

@@ -30,15 +30,14 @@ func (c C) PlainEncode(w io.Writer) error {
3030
_, err := fmt.Fprintf(w, ".")
3131
return err
3232
}
33-
_, err := w.Write(strconv.AppendInt(nil, *c.p, 16))
34-
return err
35-
}
36-
37-
func isHexLower(b byte) bool {
38-
return (b >= byte('0') && b <= byte('9')) || (b >= byte('a') && b <= byte('f'))
33+
err := plain.Put(w, "c")
34+
if err != nil {
35+
return err
36+
}
37+
return plain.EncodeInt64(w, *c.p)
3938
}
4039

41-
func (c C) PlainDecode(r io.Reader) error {
40+
func (c *C) PlainDecode(r io.Reader) error {
4241
var buf [16]byte
4342
_, err := io.ReadFull(r, buf[:1])
4443
if err != nil {
@@ -48,20 +47,15 @@ func (c C) PlainDecode(r io.Reader) error {
4847
c.p = nil
4948
return nil
5049
}
51-
i := 1
52-
for i < 16 {
53-
_, err = io.ReadFull(r, buf[i:i+1])
54-
if err != nil {
55-
return err
56-
}
57-
if !isHexLower(buf[i]) {
58-
break
59-
}
60-
61-
i++
50+
if buf[0] != byte('c') {
51+
return fmt.Errorf("unexpected %c != c", buf[0])
52+
}
53+
var v int64
54+
v, err = plain.DecodeInt64From(r)
55+
if err != nil {
56+
return err
6257
}
63-
v, _ := strconv.ParseInt(string(buf[:i]), 16, 64)
64-
*c.p = v
58+
c.p = &v
6559
return nil
6660
}
6761

@@ -74,36 +68,36 @@ var one int64 = 1
7468

7569
func (c consts) Zero() I {
7670
z := int64(0)
77-
return I(C{&z})
71+
return I(&C{&z})
7872
}
7973

8074
func (c consts) One() I {
8175
o := int64(1)
82-
return I(C{&o})
76+
return I(&C{&o})
8377
}
8478

8579
func (c consts) IsVar(v I) bool {
86-
return v.(C).p == nil
80+
return v.(*C).p == nil
8781
}
8882

8983
func (c consts) Var() I {
90-
return C{nil}
84+
return &C{nil}
9185
}
9286

9387
func (c consts) FromInt64(v int64) I {
94-
return C{&v}
88+
return &C{&v}
9589
}
9690

9791
func (c consts) ToInt64(v I) (int64, bool) {
98-
p := v.(C).p
92+
p := v.(*C).p
9993
if p == nil {
10094
return 0, false
10195
}
10296
return *p, true
10397
}
10498

10599
func (c consts) Plus(a, b I) I {
106-
pa, pb := a.(C).p, b.(C).p
100+
pa, pb := a.(*C).p, b.(*C).p
107101
if pa == nil || pb == nil {
108102
return c.Var()
109103
}
@@ -112,7 +106,7 @@ func (c consts) Plus(a, b I) I {
112106
}
113107

114108
func (c consts) Times(a, b I) I {
115-
pa, pb := a.(C).p, b.(C).p
109+
pa, pb := a.(*C).p, b.(*C).p
116110
if pa == nil || pb == nil {
117111
return c.Var()
118112
}
@@ -125,7 +119,7 @@ func (c consts) Div(a, b I) (I, xtruth.T) {
125119
case xtruth.True:
126120
return c.Zero(), xtruth.False
127121
case xtruth.False:
128-
pa, pb := a.(C).p, b.(C).p
122+
pa, pb := a.(*C).p, b.(*C).p
129123
r := *pa / *pb
130124
return c.FromInt64(r), xtruth.True
131125
case xtruth.X:
@@ -139,7 +133,7 @@ func (c consts) Rem(a, b I) (I, xtruth.T) {
139133
case xtruth.True:
140134
return c.Zero(), xtruth.False
141135
case xtruth.False:
142-
pa, pb := a.(C).p, b.(C).p
136+
pa, pb := a.(*C).p, b.(*C).p
143137
r := *pa % *pb
144138
return c.FromInt64(r), xtruth.True
145139
case xtruth.X:
@@ -149,7 +143,7 @@ func (c consts) Rem(a, b I) (I, xtruth.T) {
149143
}
150144

151145
func (c consts) Band(a, b I) I {
152-
pa, pb := a.(C).p, b.(C).p
146+
pa, pb := a.(*C).p, b.(*C).p
153147
if pa == nil || pb == nil {
154148
return c.Var()
155149
}
@@ -158,7 +152,7 @@ func (c consts) Band(a, b I) I {
158152
}
159153

160154
func (c consts) Bnot(a I) I {
161-
pa := a.(C).p
155+
pa := a.(*C).p
162156
if pa == nil {
163157
return c.Var()
164158
}
@@ -175,7 +169,7 @@ func (c consts) Rshift(a, s I) (I, xtruth.T) {
175169
}
176170

177171
func (c consts) Less(a, b I) xtruth.T {
178-
pa, pb := a.(C).p, b.(C).p
172+
pa, pb := a.(*C).p, b.(*C).p
179173
if pa == nil || pb == nil {
180174
return xtruth.X
181175
}
@@ -186,7 +180,7 @@ func (c consts) Less(a, b I) xtruth.T {
186180
}
187181

188182
func (c consts) Equal(a, b I) xtruth.T {
189-
pa, pb := a.(C).p, b.(C).p
183+
pa, pb := a.(*C).p, b.(*C).p
190184
if pa == nil || pb == nil {
191185
return xtruth.X
192186
}

indexing/constvals_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2021 The pal authors (see AUTHORS)
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package indexing
16+
17+
import (
18+
"testing"
19+
20+
"github.com/go-air/pal/internal/plain"
21+
"github.com/go-air/pal/xtruth"
22+
)
23+
24+
func TestConstVals(t *testing.T) {
25+
idx := ConstVals()
26+
z := idx.Zero()
27+
o := idx.One()
28+
v := idx.FromInt64(32)
29+
w := idx.Var()
30+
var err error
31+
for _, i := range [...]I{z, o, v, w} {
32+
err = plain.TestRoundTrip(i, true)
33+
if err != nil {
34+
t.Error(err)
35+
}
36+
}
37+
switch x := idx.Equal(z, idx.Zero()); x {
38+
case xtruth.True:
39+
default:
40+
t.Errorf("%s == %s => %s\n", z, idx.Zero(), x)
41+
}
42+
switch x := idx.Equal(o, idx.One()); x {
43+
case xtruth.True:
44+
default:
45+
t.Errorf("%s == %s => %s\n", o, idx.One(), x)
46+
}
47+
switch x := idx.Equal(v, idx.FromInt64(32)); x {
48+
case xtruth.True:
49+
default:
50+
t.Errorf("%s == %s => %s\n", v, idx.FromInt64(32), x)
51+
}
52+
}

internal/plain/plain.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func DecodeJoin(r io.Reader, sep string, ds ...Decoder) error {
8484
}
8585
err = d.PlainDecode(r)
8686
if err != nil {
87-
return fmt.Errorf("decode joint elt %d: %w", i, err)
87+
return fmt.Errorf("decode join elt %d: %w", i, err)
8888
}
8989
}
9090
return nil

objects/array_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestArray(t *testing.T) {
3434
a.typ = 7
3535
a.n = 17
3636
a.elemSize = 5
37-
if err := plain.TestRoundTripClobber(a, clobArray, true); err != nil {
37+
if err := plain.TestRoundTripClobber(a, clobArray, false); err != nil {
3838
t.Error(err)
3939
}
4040
}

objects/builder.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,23 @@ func (b *Builder) Slice(gty *types.Slice, length, capacity indexing.I) *Slice {
127127
sl := b.omap[m].(*Slice)
128128
sl.Len = length
129129
sl.Cap = capacity
130-
b.AddSlot(sl, b.indexing.Var())
130+
b.AddSlot(sl, b.indexing.Zero())
131131
return sl
132132
}
133133

134134
func (b *Builder) AddSlot(slice *Slice, i indexing.I) {
135-
elem := b.ts.Elem(slice.typ)
136-
loc := b.Type(elem).Gen()
135+
elemTy := b.ts.Elem(slice.typ)
136+
ptrTy := b.ts.PointerTo(elemTy)
137+
ptr := b.Type(ptrTy).Gen()
138+
obj := b.Type(elemTy).Gen()
139+
b.walkObj(obj)
140+
b.AddTransferIndex(ptr, slice.loc, i)
141+
b.AddAddressOf(ptr, obj)
142+
137143
slice.slots = append(slice.slots, Slot{
138-
Loc: loc,
144+
Ptr: ptr,
145+
Obj: obj,
139146
I: i})
140-
b.walkObj(loc)
141147
}
142148

143149
func (b *Builder) Map(gty *types.Map) *Map {
@@ -299,6 +305,7 @@ func (b *Builder) walkObj(m memory.Loc) {
299305
ma.typ = ty
300306
ma.key = b.Type(b.ts.Key(ty)).Gen()
301307
ma.elem = b.Type(b.ts.Elem(ty)).Gen()
308+
b.mmod.AddAddressOf(ma.loc, ma.key)
302309
b.mmod.AddAddressOf(ma.loc, ma.elem)
303310
b.omap[m] = ma
304311
} else {
@@ -313,11 +320,10 @@ func (b *Builder) walkObj(m memory.Loc) {
313320
slice = &Slice{}
314321
slice.loc = m
315322
slice.typ = b.mmod.Type(m)
316-
slice.Len = b.indexing.Var()
317-
slice.Cap = b.indexing.Var()
323+
slice.Len = b.indexing.Zero()
324+
slice.Cap = b.indexing.Zero()
325+
b.AddAddressOf(slice.loc, b.mmod.Zero())
318326
b.omap[m] = slice
319-
} else {
320-
slice = obj.(*Slice)
321327
}
322328

323329
case typeset.Interface:

objects/chan.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,22 @@ type Chan struct {
3131
slot memory.Loc
3232
}
3333

34+
// Recv retrieves the data from the c and loads
35+
// it into dst.
3436
func (c *Chan) Recv(dst memory.Loc, mm *memory.Model) {
3537
mm.AddLoad(dst, c.loc)
3638
}
3739

40+
// Send sends the data at src to the channel c.
41+
//
42+
// Send is modeled as a store.
3843
func (c *Chan) Send(src memory.Loc, mm *memory.Model) {
3944
mm.AddStore(c.loc, src)
4045
}
4146

4247
func (c *Chan) PlainEncode(w io.Writer) error {
4348
var err error
44-
err = plain.Put(w, "c")
49+
err = plain.Put(w, "c ")
4550
if err != nil {
4651
return err
4752
}
@@ -53,7 +58,7 @@ func (c *Chan) PlainEncode(w io.Writer) error {
5358

5459
func (c *Chan) PlainDecode(r io.Reader) error {
5560
var err error
56-
err = plain.Expect(r, "c")
61+
err = plain.Expect(r, "c ")
5762
if err != nil {
5863
return err
5964
}

objects/map_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2021 The pal authors (see AUTHORS)
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package objects
16+
17+
import (
18+
"testing"
19+
20+
"github.com/go-air/pal/internal/plain"
21+
)
22+
23+
func clobMap(c plain.Coder) {
24+
a := c.(*Map)
25+
a.loc = 0
26+
a.typ = 0
27+
a.key = 0
28+
a.elem = 0
29+
}
30+
31+
func TestMap(t *testing.T) {
32+
a := &Map{}
33+
a.loc = 3
34+
a.typ = 7
35+
a.key = 17
36+
a.elem = 5
37+
if err := plain.TestRoundTripClobber(a, clobMap, false); err != nil {
38+
t.Error(err)
39+
}
40+
}

0 commit comments

Comments
 (0)