fieldPath is now selectionReader

master
Jordan Orelli 8 years ago
parent 6d340e119b
commit 372d236fe7

@ -17,8 +17,6 @@ type Class struct {
// maps field names back to their indexes. Entities use this to access
// their own fields by name instead of by slot.
fieldNames map[string]int
fp *fieldPath
}
func (c *Class) New() *Entity {

@ -16,17 +16,19 @@ func (e *Entity) Read(br bit.Reader) error {
}
Debug.Printf("entity %v read", e)
fp := newFieldPath()
if err := fp.read(br, htree, e.Class); err != nil {
r := newSelectionReader()
if err := r.read(br, htree); err != nil {
return fmt.Errorf("unable to read entity: %v", err)
}
for i := 0; i <= fp.hlast; i++ {
if fp.history[i][0] == 0 {
Debug.Printf("direct selection: %v", fp.history[i][1])
Debug.Printf("field: %v", e.Class.Fields[fp.history[i][1]])
} else {
Debug.Printf("child selection: %v (%v)", fp.history[i],
fp.history[i][1:fp.history[i][0]+2])
for _, s := range r.selections() {
switch s.count {
case 0:
Debug.Printf("FUCK!")
case 1:
Debug.Printf("direct selection: %v", s.path())
default:
Debug.Printf("child selection: %v", s.path())
}
}
return nil

@ -1,106 +0,0 @@
package ent
import (
"fmt"
"github.com/jordanorelli/hyperstone/bit"
)
type fieldPath struct {
// slice of values, to be reused over and over
vals [6]int
// index of the last valid value. e.g., the head of the stack.
last int
// history of fieldpath values. that is, all selections thus far.
// Everything is fixed width to avoid allocations as much as possible
// inside of the fieldpath stuff. history lengths are known to go over 500,
// but I honestly have no idea if there is or isn't a limit. this is a
// hazard.
history [1024][7]int
// last valid index of a history entry
hlast int
}
func newFieldPath() *fieldPath {
f := new(fieldPath)
f.vals[f.last] = -1
f.hlast = -1
return f
}
func (f *fieldPath) add(i int) {
f.vals[f.last] += i
}
func (f *fieldPath) push(i int) {
f.last++
f.vals[f.last] = i
}
func (f *fieldPath) pop() int {
f.last--
return f.vals[f.last+1]
}
func (f *fieldPath) replaceAll(fn func(v int) int) {
for i := 0; i <= f.last; i++ {
f.vals[i] = fn(f.vals[i])
}
}
// reads the sequence of id values off of the provided bit reader given the
// huffman tree of fieldpath ops rooted at the node n
func (f *fieldPath) read(br bit.Reader, n node, class *Class) error {
f.last = 0
for fn := walk(n, br); fn != nil; fn = walk(n, br) {
if err := br.Err(); err != nil {
return fmt.Errorf("unable to read fieldpath: reader error: %v", err)
}
fn(f, br)
Debug.Printf("fieldpath: %v", f.path())
f.keep()
}
return nil
}
// adds our current vals to the history list.
// a history list entry is an array of ints, 7 ints wide. a fieldPath value is
// 6 ints wide. a history value encodes the number of valid entries in its
// first position. e.g., this:
// [0 0 0 0 0 0 0]
// would indicate the selection [0]
// [0 4 0 0 0 0 0]
// would indicate the selection [4]
// [1 4 2 0 0 0 0]
// would indicate the selection [4 2]
func (f *fieldPath) keep() {
f.hlast++
f.history[f.hlast][0] = f.last
for i := 0; i <= f.last; i++ {
f.history[f.hlast][i+1] = f.vals[i]
}
}
func (f *fieldPath) getField(class *Class) *Field {
if f.last > 0 {
for i := 0; i < f.last; i++ {
if f.vals[i] >= len(class.Fields) {
Info.Fatalf("bad access for field %d on class %v; class has only %d fields", f.vals[i], class, len(class.Fields))
}
field := class.Fields[f.vals[i]]
if field.class == nil {
Info.Fatalf("class %s field at %d is %v, has no class", class, f.vals[i], field)
} else {
class = class.Fields[f.vals[i]].class
}
}
}
return class.Fields[f.vals[f.last]]
}
// the subslice of valid index values that has been read on the fieldpath
func (f *fieldPath) path() []int {
return f.vals[:f.last+1]
}

@ -33,7 +33,7 @@ type lNode struct {
name string
_rank int
freq int
fn func(*fieldPath, bit.Reader)
fn selectionOp
}
func (n lNode) String() string {
@ -91,7 +91,9 @@ func makeTree(l nodeList) node {
return l[0]
}
func walk(n node, br bit.Reader) func(*fieldPath, bit.Reader) {
// walks the huffman tree rooted at the node n, returning the selection op
// encoded by the tree.
func walk(n node, br bit.Reader) selectionOp {
switch v := n.(type) {
case lNode:
// Debug.Printf("fieldpath fn: %s", v.name)
@ -118,89 +120,89 @@ func dump(n node, prefix string, w io.Writer) {
}
var hlist = nodeList{
lNode{"PlusOne", 0, 36271, func(fp *fieldPath, br bit.Reader) {
fp.add(1)
lNode{"PlusOne", 0, 36271, func(r *selectionReader, br bit.Reader) {
r.add(1)
}},
lNode{"FieldPathEncodeFinish", 39, 25474, nil},
lNode{"PushOneLeftDeltaNRightNonZeroPack6Bits", 11, 10530, func(fp *fieldPath, br bit.Reader) {
lNode{"PushOneLeftDeltaNRightNonZeroPack6Bits", 11, 10530, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushOneLeftDeltaNRightNonZeroPack6Bits")
}},
lNode{"PlusTwo", 1, 10334, func(fp *fieldPath, br bit.Reader) {
fp.add(2)
lNode{"PlusTwo", 1, 10334, func(r *selectionReader, br bit.Reader) {
r.add(2)
}},
lNode{"PlusN", 4, 4128, func(fp *fieldPath, br bit.Reader) {
fp.add(int(bit.ReadUBitVarFP(br)) + 5)
lNode{"PlusN", 4, 4128, func(r *selectionReader, br bit.Reader) {
r.add(int(bit.ReadUBitVarFP(br)) + 5)
}},
lNode{"PushOneLeftDeltaOneRightNonZero", 8, 2942, func(fp *fieldPath, br bit.Reader) {
lNode{"PushOneLeftDeltaOneRightNonZero", 8, 2942, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushOneLeftDeltaOneRightNonZero")
}},
lNode{"PopAllButOnePlusOne", 29, 1837, func(fp *fieldPath, br bit.Reader) {
fp.last = 0
fp.add(1)
lNode{"PopAllButOnePlusOne", 29, 1837, func(r *selectionReader, br bit.Reader) {
r.cur.count = 1
r.add(1)
}},
lNode{"PlusThree", 2, 1375, func(fp *fieldPath, br bit.Reader) {
fp.add(3)
lNode{"PlusThree", 2, 1375, func(r *selectionReader, br bit.Reader) {
r.add(3)
}},
lNode{"PlusFour", 3, 646, func(fp *fieldPath, br bit.Reader) {
lNode{"PlusFour", 3, 646, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PlusFour")
}},
lNode{"PopAllButOnePlusNPack6Bits", 32, 634, func(fp *fieldPath, br bit.Reader) {
lNode{"PopAllButOnePlusNPack6Bits", 32, 634, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopAllButOnePlusNPack6Bits")
}},
lNode{"PushOneLeftDeltaNRightZero", 9, 560, func(fp *fieldPath, br bit.Reader) {
lNode{"PushOneLeftDeltaNRightZero", 9, 560, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushOneLeftDeltaNRightZero")
}},
lNode{"PushOneLeftDeltaOneRightZero", 7, 521, func(fp *fieldPath, br bit.Reader) {
fp.add(1)
fp.push(0)
lNode{"PushOneLeftDeltaOneRightZero", 7, 521, func(r *selectionReader, br bit.Reader) {
r.add(1)
r.push(0)
}},
lNode{"PushOneLeftDeltaNRightNonZero", 10, 471, func(fp *fieldPath, br bit.Reader) {
lNode{"PushOneLeftDeltaNRightNonZero", 10, 471, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushOneLeftDeltaNRightNonZero")
}},
lNode{"PushNAndNonTopological", 26, 310, func(fp *fieldPath, br bit.Reader) {
lNode{"PushNAndNonTopological", 26, 310, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushNAndNonTopological")
}},
lNode{"PopAllButOnePlusNPack3Bits", 31, 300, func(fp *fieldPath, br bit.Reader) {
lNode{"PopAllButOnePlusNPack3Bits", 31, 300, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopAllButOnePlusNPack3Bits")
}},
lNode{"NonTopoPenultimatePlusOne", 37, 271, func(fp *fieldPath, br bit.Reader) {
lNode{"NonTopoPenultimatePlusOne", 37, 271, func(r *selectionReader, br bit.Reader) {
panic("not implemented: NonTopoPenultimatePlusOne")
}},
lNode{"PushOneLeftDeltaNRightNonZeroPack8Bits", 12, 251, func(fp *fieldPath, br bit.Reader) {
lNode{"PushOneLeftDeltaNRightNonZeroPack8Bits", 12, 251, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushOneLeftDeltaNRightNonZeroPack8Bits")
}},
lNode{"PopAllButOnePlusN", 30, 149, func(fp *fieldPath, br bit.Reader) {
lNode{"PopAllButOnePlusN", 30, 149, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopAllButOnePlusN")
}},
lNode{"NonTopoComplexPack4Bits", 38, 99, func(fp *fieldPath, br bit.Reader) {
fp.replaceAll(func(i int) int {
lNode{"NonTopoComplexPack4Bits", 38, 99, func(r *selectionReader, br bit.Reader) {
r.måp(func(i int) int {
if bit.ReadBool(br) {
return i + int(br.ReadBits(4)) - 7 // ?!
}
return i
})
}},
lNode{"NonTopoComplex", 36, 76, func(fp *fieldPath, br bit.Reader) {
fp.replaceAll(func(i int) int {
lNode{"NonTopoComplex", 36, 76, func(r *selectionReader, br bit.Reader) {
r.måp(func(i int) int {
if bit.ReadBool(br) {
return i + int(bit.ReadZigZag32(br))
}
return i
})
}},
lNode{"PushOneLeftDeltaZeroRightZero", 5, 35, func(fp *fieldPath, br bit.Reader) {
fp.push(0)
lNode{"PushOneLeftDeltaZeroRightZero", 5, 35, func(r *selectionReader, br bit.Reader) {
r.push(0)
}},
lNode{"PushOneLeftDeltaZeroRightNonZero", 6, 3, func(fp *fieldPath, br bit.Reader) {
fp.push(int(bit.ReadUBitVarFP(br)))
lNode{"PushOneLeftDeltaZeroRightNonZero", 6, 3, func(r *selectionReader, br bit.Reader) {
r.push(int(bit.ReadUBitVarFP(br)))
}},
lNode{"PopOnePlusOne", 27, 2, func(fp *fieldPath, br bit.Reader) {
fp.pop()
fp.add(1)
lNode{"PopOnePlusOne", 27, 2, func(r *selectionReader, br bit.Reader) {
r.pop()
r.add(1)
}},
lNode{"PopNAndNonTopographical", 35, 1, func(fp *fieldPath, br bit.Reader) {
fp.last -= int(bit.ReadUBitVarFP(br))
fp.replaceAll(func(i int) int {
lNode{"PopNAndNonTopographical", 35, 1, func(r *selectionReader, br bit.Reader) {
r.count -= int(bit.ReadUBitVarFP(br))
r.måp(func(i int) int {
if bit.ReadBool(br) {
return i + int(bit.ReadZigZag32(br))
}
@ -210,53 +212,53 @@ var hlist = nodeList{
// all the other operations have weights of 0 in clarity, which makes no
// sense.
lNode{"PopNPlusN", 34, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PopNPlusN", 34, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopNPlusN")
}},
lNode{"PopNPlusOne", 33, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PopNPlusOne", 33, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopNPlusOne")
}},
lNode{"PopOnePlusN", 28, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PopOnePlusN", 28, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PopOnePlusN")
}},
lNode{"PushN", 25, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushN", 25, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushN")
}},
lNode{"PushThreePack5LeftDeltaN", 24, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreePack5LeftDeltaN", 24, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreePack5LeftDeltaN")
}},
lNode{"PushThreeLeftDeltaN", 23, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreeLeftDeltaN", 23, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreeLeftDeltaN")
}},
lNode{"PushTwoPack5LeftDeltaN", 22, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushTwoPack5LeftDeltaN", 22, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushTwoPack5LeftDeltaN")
}},
lNode{"PushTwoLeftDeltaN", 21, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushTwoLeftDeltaN", 21, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushTwoLeftDeltaN")
}},
lNode{"PushThreePack5LeftDeltaOne", 20, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreePack5LeftDeltaOne", 20, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreePack5LeftDeltaOne")
}},
lNode{"PushThreeLeftDeltaOne", 19, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreeLeftDeltaOne", 19, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreeLeftDeltaOne")
}},
lNode{"PushTwoPack5LeftDeltaOne", 18, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushTwoPack5LeftDeltaOne", 18, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushTwoPack5LeftDeltaOne")
}},
lNode{"PushTwoLeftDeltaOne", 17, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushTwoLeftDeltaOne", 17, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushTwoLeftDeltaOne")
}},
lNode{"PushThreePack5LeftDeltaZero", 16, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreePack5LeftDeltaZero", 16, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreePack5LeftDeltaZero")
}},
lNode{"PushThreeLeftDeltaZero", 15, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushThreeLeftDeltaZero", 15, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushThreeLeftDeltaZero")
}},
lNode{"PushTwoPack5LeftDeltaZero", 14, 1, func(fp *fieldPath, br bit.Reader) {
fp.push(int(br.ReadBits(5)))
fp.push(int(br.ReadBits(5)))
lNode{"PushTwoPack5LeftDeltaZero", 14, 1, func(r *selectionReader, br bit.Reader) {
r.push(int(br.ReadBits(5)))
r.push(int(br.ReadBits(5)))
}},
lNode{"PushTwoLeftDeltaZero", 13, 1, func(fp *fieldPath, br bit.Reader) {
lNode{"PushTwoLeftDeltaZero", 13, 1, func(r *selectionReader, br bit.Reader) {
panic("not implemented: PushTwoLeftDeltaZero")
}},
}

@ -0,0 +1,82 @@
package ent
import (
"fmt"
"github.com/jordanorelli/hyperstone/bit"
)
type selectionOp func(*selectionReader, bit.Reader)
// selection represents the selection of an individual entity slot. a count of
// 1 indicates that the selection is to be made directly on an entity. counts
// higher than 1 indiciate that the selection is to be made on either a member
// entity or an element of a member array.
type selection struct {
count int
vals [6]int
}
func (s selection) path() []int { return s.vals[:s.count] }
// selectionReader reads a set of field selections off of the wire. the
// selections are represented as arrays of slot positions to be traversed in
// order to select an entity slot.
type selectionReader struct {
// current selection; the selection being read off the wire right now
cur selection
// the number of valid selections made thus far
count int
// a list of past selections. values up to the index count-1 are considered
// valid.
all [1024]selection
}
func newSelectionReader() *selectionReader {
r := new(selectionReader)
r.cur.count = 1
r.cur.vals[0] = -1
return r
}
func (r *selectionReader) read(br bit.Reader, n node) error {
for fn := walk(n, br); fn != nil; fn = walk(n, br) {
if err := br.Err(); err != nil {
return fmt.Errorf("unable to read selection: bit reader error: %v", err)
}
fn(r, br)
Debug.Printf("selection: %v", r.cur.path())
r.keep()
}
return nil
}
func (r *selectionReader) selections() []selection { return r.all[:r.count] }
// adds i to the current selection
func (r *selectionReader) add(i int) {
r.cur.vals[r.cur.count-1] += i
}
// pushes the value i to the end of the current selection
func (r *selectionReader) push(i int) {
r.cur.vals[r.cur.count] = i
r.cur.count++
}
// pops the last value off of the current selection
func (r *selectionReader) pop() { r.cur.count-- }
// maps a function over the current set of values in the current selection
func (r *selectionReader) måp(fn func(int) int) {
for i := 0; i < r.cur.count; i++ {
r.cur.vals[i] = fn(r.cur.vals[i])
}
}
// keep the current selection and move on to the next one
func (r *selectionReader) keep() {
r.all[r.count] = r.cur
r.count++
}
Loading…
Cancel
Save