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 // maps field names back to their indexes. Entities use this to access
// their own fields by name instead of by slot. // their own fields by name instead of by slot.
fieldNames map[string]int fieldNames map[string]int
fp *fieldPath
} }
func (c *Class) New() *Entity { func (c *Class) New() *Entity {

@ -16,17 +16,19 @@ func (e *Entity) Read(br bit.Reader) error {
} }
Debug.Printf("entity %v read", e) Debug.Printf("entity %v read", e)
fp := newFieldPath() r := newSelectionReader()
if err := fp.read(br, htree, e.Class); err != nil { if err := r.read(br, htree); err != nil {
return fmt.Errorf("unable to read entity: %v", err) return fmt.Errorf("unable to read entity: %v", err)
} }
for i := 0; i <= fp.hlast; i++ {
if fp.history[i][0] == 0 { for _, s := range r.selections() {
Debug.Printf("direct selection: %v", fp.history[i][1]) switch s.count {
Debug.Printf("field: %v", e.Class.Fields[fp.history[i][1]]) case 0:
} else { Debug.Printf("FUCK!")
Debug.Printf("child selection: %v (%v)", fp.history[i], case 1:
fp.history[i][1:fp.history[i][0]+2]) Debug.Printf("direct selection: %v", s.path())
default:
Debug.Printf("child selection: %v", s.path())
} }
} }
return nil 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 name string
_rank int _rank int
freq int freq int
fn func(*fieldPath, bit.Reader) fn selectionOp
} }
func (n lNode) String() string { func (n lNode) String() string {
@ -91,7 +91,9 @@ func makeTree(l nodeList) node {
return l[0] 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) { switch v := n.(type) {
case lNode: case lNode:
// Debug.Printf("fieldpath fn: %s", v.name) // Debug.Printf("fieldpath fn: %s", v.name)
@ -118,89 +120,89 @@ func dump(n node, prefix string, w io.Writer) {
} }
var hlist = nodeList{ var hlist = nodeList{
lNode{"PlusOne", 0, 36271, func(fp *fieldPath, br bit.Reader) { lNode{"PlusOne", 0, 36271, func(r *selectionReader, br bit.Reader) {
fp.add(1) r.add(1)
}}, }},
lNode{"FieldPathEncodeFinish", 39, 25474, nil}, 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") panic("not implemented: PushOneLeftDeltaNRightNonZeroPack6Bits")
}}, }},
lNode{"PlusTwo", 1, 10334, func(fp *fieldPath, br bit.Reader) { lNode{"PlusTwo", 1, 10334, func(r *selectionReader, br bit.Reader) {
fp.add(2) r.add(2)
}}, }},
lNode{"PlusN", 4, 4128, func(fp *fieldPath, br bit.Reader) { lNode{"PlusN", 4, 4128, func(r *selectionReader, br bit.Reader) {
fp.add(int(bit.ReadUBitVarFP(br)) + 5) 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") panic("not implemented: PushOneLeftDeltaOneRightNonZero")
}}, }},
lNode{"PopAllButOnePlusOne", 29, 1837, func(fp *fieldPath, br bit.Reader) { lNode{"PopAllButOnePlusOne", 29, 1837, func(r *selectionReader, br bit.Reader) {
fp.last = 0 r.cur.count = 1
fp.add(1) r.add(1)
}}, }},
lNode{"PlusThree", 2, 1375, func(fp *fieldPath, br bit.Reader) { lNode{"PlusThree", 2, 1375, func(r *selectionReader, br bit.Reader) {
fp.add(3) 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") 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") 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") panic("not implemented: PushOneLeftDeltaNRightZero")
}}, }},
lNode{"PushOneLeftDeltaOneRightZero", 7, 521, func(fp *fieldPath, br bit.Reader) { lNode{"PushOneLeftDeltaOneRightZero", 7, 521, func(r *selectionReader, br bit.Reader) {
fp.add(1) r.add(1)
fp.push(0) 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") 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") 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") 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") 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") 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") panic("not implemented: PopAllButOnePlusN")
}}, }},
lNode{"NonTopoComplexPack4Bits", 38, 99, func(fp *fieldPath, br bit.Reader) { lNode{"NonTopoComplexPack4Bits", 38, 99, func(r *selectionReader, br bit.Reader) {
fp.replaceAll(func(i int) int { r.måp(func(i int) int {
if bit.ReadBool(br) { if bit.ReadBool(br) {
return i + int(br.ReadBits(4)) - 7 // ?! return i + int(br.ReadBits(4)) - 7 // ?!
} }
return i return i
}) })
}}, }},
lNode{"NonTopoComplex", 36, 76, func(fp *fieldPath, br bit.Reader) { lNode{"NonTopoComplex", 36, 76, func(r *selectionReader, br bit.Reader) {
fp.replaceAll(func(i int) int { r.måp(func(i int) int {
if bit.ReadBool(br) { if bit.ReadBool(br) {
return i + int(bit.ReadZigZag32(br)) return i + int(bit.ReadZigZag32(br))
} }
return i return i
}) })
}}, }},
lNode{"PushOneLeftDeltaZeroRightZero", 5, 35, func(fp *fieldPath, br bit.Reader) { lNode{"PushOneLeftDeltaZeroRightZero", 5, 35, func(r *selectionReader, br bit.Reader) {
fp.push(0) r.push(0)
}}, }},
lNode{"PushOneLeftDeltaZeroRightNonZero", 6, 3, func(fp *fieldPath, br bit.Reader) { lNode{"PushOneLeftDeltaZeroRightNonZero", 6, 3, func(r *selectionReader, br bit.Reader) {
fp.push(int(bit.ReadUBitVarFP(br))) r.push(int(bit.ReadUBitVarFP(br)))
}}, }},
lNode{"PopOnePlusOne", 27, 2, func(fp *fieldPath, br bit.Reader) { lNode{"PopOnePlusOne", 27, 2, func(r *selectionReader, br bit.Reader) {
fp.pop() r.pop()
fp.add(1) r.add(1)
}}, }},
lNode{"PopNAndNonTopographical", 35, 1, func(fp *fieldPath, br bit.Reader) { lNode{"PopNAndNonTopographical", 35, 1, func(r *selectionReader, br bit.Reader) {
fp.last -= int(bit.ReadUBitVarFP(br)) r.count -= int(bit.ReadUBitVarFP(br))
fp.replaceAll(func(i int) int { r.måp(func(i int) int {
if bit.ReadBool(br) { if bit.ReadBool(br) {
return i + int(bit.ReadZigZag32(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 // all the other operations have weights of 0 in clarity, which makes no
// sense. // 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") 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") 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") 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") 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") 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") 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") 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") 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") 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") 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") 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") 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") 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") panic("not implemented: PushThreeLeftDeltaZero")
}}, }},
lNode{"PushTwoPack5LeftDeltaZero", 14, 1, func(fp *fieldPath, br bit.Reader) { lNode{"PushTwoPack5LeftDeltaZero", 14, 1, func(r *selectionReader, br bit.Reader) {
fp.push(int(br.ReadBits(5))) r.push(int(br.ReadBits(5)))
fp.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") 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