Initial commit

This commit is contained in:
lash
2023-03-31 10:52:04 +01:00
commit c0d38513d3
10 changed files with 416 additions and 0 deletions

3
go/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.defalsify.org/festive
go 1.20

25
go/resource/fs.go Normal file
View File

@@ -0,0 +1,25 @@
package resource
import (
"context"
)
type FsResource struct {
path string
ctx context.Context
}
func NewFsResource(path string, ctx context.Context) (FsResource) {
return FsResource{
path: path,
ctx: ctx,
}
}
func(fs *FsResource) Get(sym string) (string, error) {
return "", nil
}
func(fs *FsResource) Render(sym string, values []string) (string, error) {
return "", nil
}

11
go/resource/fs_test.go Normal file
View File

@@ -0,0 +1,11 @@
package resource
import (
"context"
"testing"
)
func TestNewFs(t *testing.T) {
n := NewFsResource("./testdata", context.TODO())
_ = n
}

7
go/resource/resource.go Normal file
View File

@@ -0,0 +1,7 @@
package resource
type Fetcher interface {
Get(symbol string) (string, error)
Render(symbol string, values map[string]string) (string, error)
}

36
go/state/state.go Normal file
View File

@@ -0,0 +1,36 @@
package state
import (
"io"
)
type State struct {
Flags []byte
OutputSize uint16
CacheSize uint32
CacheUseSize uint32
Cache io.ReadWriteSeeker
}
func NewState(bitSize uint64, outputSize uint16) State {
if bitSize == 0 {
panic("bitsize cannot be 0")
}
n := bitSize % 8
if n > 0 {
bitSize += (8 - n)
}
return State{
Flags: make([]byte, bitSize / 8),
OutputSize: outputSize,
CacheSize: 0,
CacheUseSize: 0,
Cache: nil,
}
}
func(st State) WithCacheSize(cacheSize uint32) State {
st.CacheSize = cacheSize
return st
}

33
go/state/state_test.go Normal file
View File

@@ -0,0 +1,33 @@
package state
import (
"testing"
)
func TestNewStateFlags(t *testing.T) {
st := NewState(5, 0)
if len(st.Flags) != 1 {
t.Errorf("invalid state flag length: %v", len(st.Flags))
}
st = NewState(8, 0)
if len(st.Flags) != 1 {
t.Errorf("invalid state flag length: %v", len(st.Flags))
}
st = NewState(17, 0)
if len(st.Flags) != 3 {
t.Errorf("invalid state flag length: %v", len(st.Flags))
}
}
func TestNewStateCache(t *testing.T) {
st := NewState(17, 0)
if st.CacheSize != 0 {
t.Errorf("cache size not 0")
}
st = st.WithCacheSize(102525)
if st.CacheSize != 102525 {
t.Errorf("cache size not 102525")
}
}

11
go/vm/opcodes.go Normal file
View File

@@ -0,0 +1,11 @@
package vm
const VERSION = 0
const (
CATCH = iota
CROAK
LOAD
RELOAD
_MAX
)

50
go/vm/vm.go Normal file
View File

@@ -0,0 +1,50 @@
package vm
import (
"encoding/binary"
"fmt"
"context"
"git.defalsify.org/festive/state"
"git.defalsify.org/festive/resource"
)
type Runner func(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error)
func Run(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error) {
op := binary.BigEndian.Uint16(instruction[:2])
if op > _MAX {
return st, fmt.Errorf("opcode value %v out of range (%v)", op, _MAX)
}
switch op {
case CATCH:
RunCatch(instruction[2:], st, rs, ctx)
case CROAK:
RunCroak(instruction[2:], st, rs, ctx)
case LOAD:
RunLoad(instruction[2:], st, rs, ctx)
case RELOAD:
RunReload(instruction[2:], st, rs, ctx)
default:
err := fmt.Errorf("Unhandled state: %v", op)
return st, err
}
return st, nil
}
func RunCatch(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error) {
return st, nil
}
func RunCroak(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error) {
return st, nil
}
func RunLoad(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error) {
return st, nil
}
func RunReload(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, error) {
return st, nil
}

44
go/vm/vm_test.go Normal file
View File

@@ -0,0 +1,44 @@
package vm
import (
"context"
"fmt"
"testing"
"git.defalsify.org/festive/state"
)
type TestResource struct {
}
func (r *TestResource) Get(sym string) (string, error) {
switch sym {
case "foo":
return "inky pinky blinky clyde", nil
case "bar":
return "inky pinky {.one} blinky {.two} clyde", nil
}
return "", fmt.Errorf("unknown symbol %s", sym)
}
func (r *TestResource) Render(sym string, values map[string]string) (string, error) {
v, err := r.Get(sym)
return v, err
}
func TestRun(t *testing.T) {
st := state.NewState(5, 255)
rs := TestResource{}
b := []byte{0x00, 0x02}
r, err := Run(b, st, &rs, context.TODO())
if err != nil {
t.Errorf("error on valid opcode: %v", err)
}
b = []byte{0x01, 0x02}
r, err = Run(b, st, &rs, context.TODO())
if err == nil {
t.Errorf("no error on invalid opcode")
}
_ = r
}