Enfore single sink for map level
This commit is contained in:
parent
d84720d595
commit
5c5e36cdfa
@ -138,7 +138,7 @@ Compiler must croak if:
|
||||
should generate warnings if sink cannot render a single enrry (of list)
|
||||
|
||||
MAP <symbol> <maxsize> <minsize>
|
||||
SINK <symbol>
|
||||
SINK <symbol> <maxsize>
|
||||
|
||||
|
||||
---
|
||||
|
@ -14,7 +14,8 @@ type State struct {
|
||||
ExecPath []string
|
||||
Arg *string
|
||||
sizes map[string]uint16
|
||||
idx uint16
|
||||
sink *string
|
||||
//sizeIdx uint16
|
||||
}
|
||||
|
||||
func NewState(bitSize uint64) State {
|
||||
@ -66,6 +67,7 @@ func(st *State) Down(input string) {
|
||||
st.CacheMap = make(map[string]string)
|
||||
st.sizes = make(map[string]uint16)
|
||||
st.ExecPath = append(st.ExecPath, input)
|
||||
st.sink = nil
|
||||
}
|
||||
|
||||
func(st *State) Add(key string, value string, sizeHint uint16) error {
|
||||
@ -119,12 +121,19 @@ func(st *State) Update(key string, value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func(st *State) Map(k string) error {
|
||||
func(st *State) Map(key string) error {
|
||||
m, err := st.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
st.CacheMap[k] = m[k]
|
||||
l := st.sizes[key]
|
||||
if l == 0 {
|
||||
if st.sink != nil {
|
||||
return fmt.Errorf("sink already set to symbol '%v'", *st.sink)
|
||||
}
|
||||
st.sink = &key
|
||||
}
|
||||
st.CacheMap[key] = m[key]
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -161,6 +170,7 @@ func(st *State) Up() error {
|
||||
}
|
||||
st.Cache = st.Cache[:l]
|
||||
st.ExecPath = st.ExecPath[:l]
|
||||
st.sink = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -177,6 +187,7 @@ func(st *State) Check(key string) bool {
|
||||
return st.frameOf(key) == -1
|
||||
}
|
||||
|
||||
// Returns size used by values, and remaining size available
|
||||
func(st *State) Size() (uint32, uint32) {
|
||||
var l int
|
||||
var c uint16
|
||||
@ -184,7 +195,8 @@ func(st *State) Size() (uint32, uint32) {
|
||||
l += len(v)
|
||||
c += st.sizes[k]
|
||||
}
|
||||
return uint32(l), uint32(c)
|
||||
r := uint32(l)
|
||||
return r, uint32(c)-r
|
||||
}
|
||||
|
||||
// return 0-indexed frame number where key is defined. -1 if not defined
|
||||
|
@ -130,7 +130,7 @@ func TestStateCurrentSize(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = st.Add("baz", "inkypinkyblinkyclyde", 40)
|
||||
err = st.Add("baz", "inkypinkyblinkyclyde", 51)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -142,7 +142,51 @@ func TestStateCurrentSize(t *testing.T) {
|
||||
if l != 25 {
|
||||
t.Errorf("expected actual length 25, got %v", l)
|
||||
}
|
||||
if c != 50 {
|
||||
if c != 36 {
|
||||
t.Errorf("expected actual length 50, got %v", c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateMapSink(t *testing.T) {
|
||||
st := NewState(17)
|
||||
st.Down("one")
|
||||
err := st.Add("foo", "bar", 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st.Down("two")
|
||||
err = st.Add("bar", "xyzzy", 6)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = st.Add("baz", "bazbaz", 18)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = st.Add("xyzzy", "plugh", 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = st.Map("foo")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = st.Map("xyzzy")
|
||||
if err == nil {
|
||||
t.Errorf("Expected fail on duplicate sink")
|
||||
}
|
||||
err = st.Map("baz")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st.Down("three")
|
||||
err = st.Map("foo")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
st.Up()
|
||||
err = st.Map("foo")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
13
go/vm/vm.go
13
go/vm/vm.go
@ -11,7 +11,7 @@ import (
|
||||
"git.defalsify.org/festive/state"
|
||||
)
|
||||
|
||||
type Runner func(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error)
|
||||
//type Runner func(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error)
|
||||
|
||||
func argFromBytes(input []byte) (string, []byte, error) {
|
||||
if len(input) == 0 {
|
||||
@ -76,9 +76,6 @@ func Run(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Co
|
||||
case MAP:
|
||||
st, instruction, err = RunMap(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
case SINK:
|
||||
st, instruction, err = RunSink(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
case MOVE:
|
||||
st, instruction, err = RunMove(instruction[2:], st, rs, ctx)
|
||||
break
|
||||
@ -100,12 +97,8 @@ func RunMap(instruction []byte, st state.State, rs resource.Fetcher, ctx context
|
||||
if err != nil {
|
||||
return st, instruction, err
|
||||
}
|
||||
st.Map(head)
|
||||
return st, tail, nil
|
||||
}
|
||||
|
||||
func RunSink(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) {
|
||||
return st, nil, nil
|
||||
err = st.Map(head)
|
||||
return st, tail, err
|
||||
}
|
||||
|
||||
func RunCatch(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) {
|
||||
|
@ -259,7 +259,7 @@ func TestRunArgInstructions(t *testing.T) {
|
||||
b = append(b, rt.ToBytes()...)
|
||||
|
||||
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0})
|
||||
bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{0})
|
||||
bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3})
|
||||
bi = NewLine(bi, MAP, []string{"one"}, nil, nil)
|
||||
bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
|
||||
var err error
|
||||
|
Loading…
Reference in New Issue
Block a user