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)
|
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>
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
13
go/vm/vm.go
13
go/vm/vm.go
@ -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) {
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user