lots o fixes
Some checks failed
Build / build (push) Successful in 9m50s
Publish Image / publish (push) Failing after 49s
Test / build (push) Successful in 10m55s

This commit is contained in:
2024-04-01 18:18:45 -04:00
parent fe33fda0ab
commit 862119e90e
44 changed files with 326 additions and 170 deletions

View File

@@ -5,23 +5,22 @@ import (
"encoding/binary"
"errors"
"fmt"
"math"
"monkey/internal/code"
"monkey/internal/object"
"strings"
)
func Indent(text, ident string) string {
func indent(text, indent string) string {
if text[len(text)-1:] == "\n" {
result := ""
for _, j := range strings.Split(text[:len(text)-1], "\n") {
result += ident + j + "\n"
result += indent + j + "\n"
}
return result
}
result := ""
for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") {
result += ident + j + "\n"
result += indent + j + "\n"
}
return result[:len(result)-1]
}
@@ -38,7 +37,7 @@ func (b *Bytecode) String() string {
for i, c := range b.Constants {
s.WriteString(fmt.Sprintf("%02d %s\n", i, c))
if cf, ok := c.(*object.CompiledFunction); ok {
s.WriteString(fmt.Sprintf(" Instructions:\n%s\n", Indent(cf.Instructions.String(), " ")))
s.WriteString(fmt.Sprintf(" Instructions:\n%s\n", indent(cf.Instructions.String(), " ")))
}
}
@@ -51,22 +50,40 @@ type encoder struct {
bytes.Buffer
}
func (e *encoder) Write(b []byte) (err error) {
_, err = e.Buffer.Write(b)
return
func (e *encoder) WriteBytes(b []byte) error {
if err := e.WriteValue(len(b)); err != nil {
return err
}
if _, err := e.Buffer.Write(b); err != nil {
return err
}
return nil
}
func (e *encoder) WriteString(s string) (err error) {
_, err = e.Buffer.WriteString(s)
return
func (e *encoder) WriteString(s string) error {
if err := e.WriteValue(len(s)); err != nil {
return err
}
if _, err := e.Buffer.WriteString(s); err != nil {
return err
}
return nil
}
func (e *encoder) WriteValue(data any) error {
return binary.Write(&e.Buffer, binary.BigEndian, data)
switch val := data.(type) {
case int:
return binary.Write(&e.Buffer, binary.BigEndian, int64(val))
case object.Type:
return e.WriteValue(int(val))
default:
return binary.Write(&e.Buffer, binary.BigEndian, data)
}
}
func (e *encoder) WriteObjects(objs ...object.Object) (err error) {
for _, obj := range objs {
func (e *encoder) WriteObjects(objects ...object.Object) (err error) {
err = errors.Join(err, e.WriteValue(len(objects)))
for _, obj := range objects {
err = errors.Join(err, e.WriteValue(obj.Type()))
switch o := obj.(type) {
@@ -77,13 +94,11 @@ func (e *encoder) WriteObjects(objs ...object.Object) (err error) {
case object.Integer:
err = errors.Join(err, e.WriteValue(o.Value))
case object.String:
err = errors.Join(err, e.WriteValue(len(o.Value)))
err = errors.Join(err, e.WriteValue(o.Value))
err = errors.Join(err, e.WriteString(o.Value))
case *object.CompiledFunction:
err = errors.Join(err, e.WriteValue(o.NumParameters))
err = errors.Join(err, e.WriteValue(o.NumLocals))
err = errors.Join(err, e.WriteValue(len(o.Instructions)))
err = errors.Join(err, e.Write(o.Instructions))
err = errors.Join(err, e.WriteBytes(o.Instructions))
}
}
return
@@ -92,9 +107,7 @@ func (e *encoder) WriteObjects(objs ...object.Object) (err error) {
func (b Bytecode) Encode() (data []byte, err error) {
var e encoder
err = errors.Join(err, e.WriteValue(len(b.Instructions)))
err = errors.Join(err, e.Write(b.Instructions))
err = errors.Join(err, e.WriteValue(len(b.Constants)))
err = errors.Join(err, e.WriteBytes(b.Instructions))
err = errors.Join(err, e.WriteObjects(b.Constants...))
return e.Bytes(), err
}
@@ -110,10 +123,8 @@ func (d *decoder) Byte() (b byte) {
return
}
func (d *decoder) Int() (i int) {
i = int(binary.BigEndian.Uint32(d.b[d.pos:]))
d.pos += 4
return
func (d *decoder) Int() int {
return int(d.Int64())
}
func (d *decoder) Uint64() (i uint64) {
@@ -122,14 +133,10 @@ func (d *decoder) Uint64() (i uint64) {
return
}
func (d *decoder) Int64() (i int64) {
func (d *decoder) Int64() int64 {
return int64(d.Uint64())
}
func (d *decoder) Float64() (f float64) {
return math.Float64frombits(d.Uint64())
}
func (d *decoder) Bytes(len int) (b []byte) {
b = d.b[d.pos : d.pos+len]
d.pos += len
@@ -161,7 +168,7 @@ func (d *decoder) Objects(len int) (o []object.Object) {
Instructions: d.Bytes(d.Int()),
})
default:
panic(fmt.Sprintf("decoder: unsupported decoding for type %d", t))
panic(fmt.Sprintf("decoder: unsupported decoding for type %d (%s)", t, t))
}
}
return

View File

@@ -0,0 +1,55 @@
package compiler
import (
"monkey/internal/lexer"
"monkey/internal/parser"
"regexp"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var hexRe = regexp.MustCompile(`0x[0-9a-f]+`)
func compile(input string) (*Bytecode, error) {
l := lexer.New(input)
p := parser.New("<text", l)
c := New()
if err := c.Compile(p.ParseProgram()); err != nil {
return nil, err
}
return c.Bytecode(), nil
}
func TestEncodeDecode(t *testing.T) {
input := `
fib := fn(x) {
if (x == 0) {
return 0
}
if (x == 1) {
return 1
}
return fib(x-1) + fib(x-2)
}
fib(35)
`
assert := assert.New(t)
require := require.New(t)
bc, err := compile(input)
require.NoError(err)
encoded, err := bc.Encode()
require.NoError(err)
decoded := Decode(encoded)
expected := hexRe.ReplaceAllString(bc.String(), "0x1234")
actual := hexRe.ReplaceAllString(decoded.String(), "0x1234")
assert.EqualValues(expected, actual)
}

View File

@@ -948,7 +948,7 @@ func TestBuiltins(t *testing.T) {
code.Make(code.OpArray, 0),
code.Make(code.OpCall, 1),
code.Make(code.OpPop),
code.Make(code.OpGetBuiltin, 33),
code.Make(code.OpGetBuiltin, 34),
code.Make(code.OpArray, 0),
code.Make(code.OpConstant, 0),
code.Make(code.OpCall, 2),