Enfore single sink for map level

This commit is contained in:
lash 2023-03-31 21:08:06 +01:00
parent d84720d595
commit 5c5e36cdfa
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
5 changed files with 67 additions and 18 deletions

View File

@ -138,7 +138,7 @@ Compiler must croak if:
should generate warnings if sink cannot render a single enrry (of list) should generate warnings if sink cannot render a single enrry (of list)
MAP <symbol> <maxsize> <minsize> MAP <symbol> <maxsize> <minsize>
SINK <symbol> SINK <symbol> <maxsize>
--- ---

View File

@ -14,7 +14,8 @@ type State struct {
ExecPath []string ExecPath []string
Arg *string Arg *string
sizes map[string]uint16 sizes map[string]uint16
idx uint16 sink *string
//sizeIdx uint16
} }
func NewState(bitSize uint64) State { func NewState(bitSize uint64) State {
@ -66,6 +67,7 @@ func(st *State) Down(input string) {
st.CacheMap = make(map[string]string) st.CacheMap = make(map[string]string)
st.sizes = make(map[string]uint16) st.sizes = make(map[string]uint16)
st.ExecPath = append(st.ExecPath, input) st.ExecPath = append(st.ExecPath, input)
st.sink = nil
} }
func(st *State) Add(key string, value string, sizeHint uint16) error { 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 return nil
} }
func(st *State) Map(k string) error { func(st *State) Map(key string) error {
m, err := st.Get() m, err := st.Get()
if err != nil { if err != nil {
return err 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 return nil
} }
@ -161,6 +170,7 @@ func(st *State) Up() error {
} }
st.Cache = st.Cache[:l] st.Cache = st.Cache[:l]
st.ExecPath = st.ExecPath[:l] st.ExecPath = st.ExecPath[:l]
st.sink = nil
return nil return nil
} }
@ -177,6 +187,7 @@ func(st *State) Check(key string) bool {
return st.frameOf(key) == -1 return st.frameOf(key) == -1
} }
// Returns size used by values, and remaining size available
func(st *State) Size() (uint32, uint32) { func(st *State) Size() (uint32, uint32) {
var l int var l int
var c uint16 var c uint16
@ -184,7 +195,8 @@ func(st *State) Size() (uint32, uint32) {
l += len(v) l += len(v)
c += st.sizes[k] 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 // return 0-indexed frame number where key is defined. -1 if not defined

View File

@ -130,7 +130,7 @@ func TestStateCurrentSize(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
err = st.Add("baz", "inkypinkyblinkyclyde", 40) err = st.Add("baz", "inkypinkyblinkyclyde", 51)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -142,7 +142,51 @@ func TestStateCurrentSize(t *testing.T) {
if l != 25 { if l != 25 {
t.Errorf("expected actual length 25, got %v", l) t.Errorf("expected actual length 25, got %v", l)
} }
if c != 50 { if c != 36 {
t.Errorf("expected actual length 50, got %v", c) 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)
}
}

View File

@ -11,7 +11,7 @@ import (
"git.defalsify.org/festive/state" "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) { func argFromBytes(input []byte) (string, []byte, error) {
if len(input) == 0 { if len(input) == 0 {
@ -76,9 +76,6 @@ func Run(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Co
case MAP: case MAP:
st, instruction, err = RunMap(instruction[2:], st, rs, ctx) st, instruction, err = RunMap(instruction[2:], st, rs, ctx)
break break
case SINK:
st, instruction, err = RunSink(instruction[2:], st, rs, ctx)
break
case MOVE: case MOVE:
st, instruction, err = RunMove(instruction[2:], st, rs, ctx) st, instruction, err = RunMove(instruction[2:], st, rs, ctx)
break break
@ -100,12 +97,8 @@ func RunMap(instruction []byte, st state.State, rs resource.Fetcher, ctx context
if err != nil { if err != nil {
return st, instruction, err return st, instruction, err
} }
st.Map(head) err = st.Map(head)
return st, tail, nil return st, tail, err
}
func RunSink(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) {
return st, nil, nil
} }
func RunCatch(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) { func RunCatch(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) {

View File

@ -259,7 +259,7 @@ func TestRunArgInstructions(t *testing.T) {
b = append(b, rt.ToBytes()...) b = append(b, rt.ToBytes()...)
bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) 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{"one"}, nil, nil)
bi = NewLine(bi, MAP, []string{"two"}, nil, nil) bi = NewLine(bi, MAP, []string{"two"}, nil, nil)
var err error var err error