Skip to content

Commit

Permalink
plain testing, constvals revamp, slice revamp
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
scott-cotton committed Aug 23, 2021
1 parent ad59631 commit dff995e
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 60 deletions.
64 changes: 29 additions & 35 deletions indexing/constvals.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package indexing
import (
"fmt"
"io"
"strconv"

"github.com/go-air/pal/internal/plain"
"github.com/go-air/pal/xtruth"
)

Expand All @@ -30,15 +30,14 @@ func (c C) PlainEncode(w io.Writer) error {
_, err := fmt.Fprintf(w, ".")
return err
}
_, err := w.Write(strconv.AppendInt(nil, *c.p, 16))
return err
}

func isHexLower(b byte) bool {
return (b >= byte('0') && b <= byte('9')) || (b >= byte('a') && b <= byte('f'))
err := plain.Put(w, "c")
if err != nil {
return err
}
return plain.EncodeInt64(w, *c.p)
}

func (c C) PlainDecode(r io.Reader) error {
func (c *C) PlainDecode(r io.Reader) error {
var buf [16]byte
_, err := io.ReadFull(r, buf[:1])
if err != nil {
Expand All @@ -48,20 +47,15 @@ func (c C) PlainDecode(r io.Reader) error {
c.p = nil
return nil
}
i := 1
for i < 16 {
_, err = io.ReadFull(r, buf[i:i+1])
if err != nil {
return err
}
if !isHexLower(buf[i]) {
break
}

i++
if buf[0] != byte('c') {
return fmt.Errorf("unexpected %c != c", buf[0])
}
var v int64
v, err = plain.DecodeInt64From(r)
if err != nil {
return err
}
v, _ := strconv.ParseInt(string(buf[:i]), 16, 64)
*c.p = v
c.p = &v
return nil
}

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

func (c consts) Zero() I {
z := int64(0)
return I(C{&z})
return I(&C{&z})
}

func (c consts) One() I {
o := int64(1)
return I(C{&o})
return I(&C{&o})
}

func (c consts) IsVar(v I) bool {
return v.(C).p == nil
return v.(*C).p == nil
}

func (c consts) Var() I {
return C{nil}
return &C{nil}
}

func (c consts) FromInt64(v int64) I {
return C{&v}
return &C{&v}
}

func (c consts) ToInt64(v I) (int64, bool) {
p := v.(C).p
p := v.(*C).p
if p == nil {
return 0, false
}
return *p, true
}

func (c consts) Plus(a, b I) I {
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
if pa == nil || pb == nil {
return c.Var()
}
Expand All @@ -112,7 +106,7 @@ func (c consts) Plus(a, b I) I {
}

func (c consts) Times(a, b I) I {
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
if pa == nil || pb == nil {
return c.Var()
}
Expand All @@ -125,7 +119,7 @@ func (c consts) Div(a, b I) (I, xtruth.T) {
case xtruth.True:
return c.Zero(), xtruth.False
case xtruth.False:
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
r := *pa / *pb
return c.FromInt64(r), xtruth.True
case xtruth.X:
Expand All @@ -139,7 +133,7 @@ func (c consts) Rem(a, b I) (I, xtruth.T) {
case xtruth.True:
return c.Zero(), xtruth.False
case xtruth.False:
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
r := *pa % *pb
return c.FromInt64(r), xtruth.True
case xtruth.X:
Expand All @@ -149,7 +143,7 @@ func (c consts) Rem(a, b I) (I, xtruth.T) {
}

func (c consts) Band(a, b I) I {
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
if pa == nil || pb == nil {
return c.Var()
}
Expand All @@ -158,7 +152,7 @@ func (c consts) Band(a, b I) I {
}

func (c consts) Bnot(a I) I {
pa := a.(C).p
pa := a.(*C).p
if pa == nil {
return c.Var()
}
Expand All @@ -175,7 +169,7 @@ func (c consts) Rshift(a, s I) (I, xtruth.T) {
}

func (c consts) Less(a, b I) xtruth.T {
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
if pa == nil || pb == nil {
return xtruth.X
}
Expand All @@ -186,7 +180,7 @@ func (c consts) Less(a, b I) xtruth.T {
}

func (c consts) Equal(a, b I) xtruth.T {
pa, pb := a.(C).p, b.(C).p
pa, pb := a.(*C).p, b.(*C).p
if pa == nil || pb == nil {
return xtruth.X
}
Expand Down
52 changes: 52 additions & 0 deletions indexing/constvals_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2021 The pal authors (see AUTHORS)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package indexing

import (
"testing"

"github.com/go-air/pal/internal/plain"
"github.com/go-air/pal/xtruth"
)

func TestConstVals(t *testing.T) {
idx := ConstVals()
z := idx.Zero()
o := idx.One()
v := idx.FromInt64(32)
w := idx.Var()
var err error
for _, i := range [...]I{z, o, v, w} {
err = plain.TestRoundTrip(i, true)
if err != nil {
t.Error(err)
}
}
switch x := idx.Equal(z, idx.Zero()); x {
case xtruth.True:
default:
t.Errorf("%s == %s => %s\n", z, idx.Zero(), x)
}
switch x := idx.Equal(o, idx.One()); x {
case xtruth.True:
default:
t.Errorf("%s == %s => %s\n", o, idx.One(), x)
}
switch x := idx.Equal(v, idx.FromInt64(32)); x {
case xtruth.True:
default:
t.Errorf("%s == %s => %s\n", v, idx.FromInt64(32), x)
}
}
2 changes: 1 addition & 1 deletion internal/plain/plain.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func DecodeJoin(r io.Reader, sep string, ds ...Decoder) error {
}
err = d.PlainDecode(r)
if err != nil {
return fmt.Errorf("decode joint elt %d: %w", i, err)
return fmt.Errorf("decode join elt %d: %w", i, err)
}
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion objects/array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestArray(t *testing.T) {
a.typ = 7
a.n = 17
a.elemSize = 5
if err := plain.TestRoundTripClobber(a, clobArray, true); err != nil {
if err := plain.TestRoundTripClobber(a, clobArray, false); err != nil {
t.Error(err)
}
}
24 changes: 15 additions & 9 deletions objects/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,23 @@ func (b *Builder) Slice(gty *types.Slice, length, capacity indexing.I) *Slice {
sl := b.omap[m].(*Slice)
sl.Len = length
sl.Cap = capacity
b.AddSlot(sl, b.indexing.Var())
b.AddSlot(sl, b.indexing.Zero())
return sl
}

func (b *Builder) AddSlot(slice *Slice, i indexing.I) {
elem := b.ts.Elem(slice.typ)
loc := b.Type(elem).Gen()
elemTy := b.ts.Elem(slice.typ)
ptrTy := b.ts.PointerTo(elemTy)
ptr := b.Type(ptrTy).Gen()
obj := b.Type(elemTy).Gen()
b.walkObj(obj)
b.AddTransferIndex(ptr, slice.loc, i)
b.AddAddressOf(ptr, obj)

slice.slots = append(slice.slots, Slot{
Loc: loc,
Ptr: ptr,
Obj: obj,
I: i})
b.walkObj(loc)
}

func (b *Builder) Map(gty *types.Map) *Map {
Expand Down Expand Up @@ -299,6 +305,7 @@ func (b *Builder) walkObj(m memory.Loc) {
ma.typ = ty
ma.key = b.Type(b.ts.Key(ty)).Gen()
ma.elem = b.Type(b.ts.Elem(ty)).Gen()
b.mmod.AddAddressOf(ma.loc, ma.key)
b.mmod.AddAddressOf(ma.loc, ma.elem)
b.omap[m] = ma
} else {
Expand All @@ -313,11 +320,10 @@ func (b *Builder) walkObj(m memory.Loc) {
slice = &Slice{}
slice.loc = m
slice.typ = b.mmod.Type(m)
slice.Len = b.indexing.Var()
slice.Cap = b.indexing.Var()
slice.Len = b.indexing.Zero()
slice.Cap = b.indexing.Zero()
b.AddAddressOf(slice.loc, b.mmod.Zero())
b.omap[m] = slice
} else {
slice = obj.(*Slice)
}

case typeset.Interface:
Expand Down
9 changes: 7 additions & 2 deletions objects/chan.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,22 @@ type Chan struct {
slot memory.Loc
}

// Recv retrieves the data from the c and loads
// it into dst.
func (c *Chan) Recv(dst memory.Loc, mm *memory.Model) {
mm.AddLoad(dst, c.loc)
}

// Send sends the data at src to the channel c.
//
// Send is modeled as a store.
func (c *Chan) Send(src memory.Loc, mm *memory.Model) {
mm.AddStore(c.loc, src)
}

func (c *Chan) PlainEncode(w io.Writer) error {
var err error
err = plain.Put(w, "c")
err = plain.Put(w, "c ")
if err != nil {
return err
}
Expand All @@ -53,7 +58,7 @@ func (c *Chan) PlainEncode(w io.Writer) error {

func (c *Chan) PlainDecode(r io.Reader) error {
var err error
err = plain.Expect(r, "c")
err = plain.Expect(r, "c ")
if err != nil {
return err
}
Expand Down
40 changes: 40 additions & 0 deletions objects/map_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2021 The pal authors (see AUTHORS)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package objects

import (
"testing"

"github.com/go-air/pal/internal/plain"
)

func clobMap(c plain.Coder) {
a := c.(*Map)
a.loc = 0
a.typ = 0
a.key = 0
a.elem = 0
}

func TestMap(t *testing.T) {
a := &Map{}
a.loc = 3
a.typ = 7
a.key = 17
a.elem = 5
if err := plain.TestRoundTripClobber(a, clobMap, false); err != nil {
t.Error(err)
}
}
Loading

0 comments on commit dff995e

Please sign in to comment.