about summary refs log tree commit diff
path: root/pkg/lang/vm/code
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/vm/code')
-rw-r--r--pkg/lang/vm/code/code.go59
-rw-r--r--pkg/lang/vm/code/op.go34
2 files changed, 93 insertions, 0 deletions
diff --git a/pkg/lang/vm/code/code.go b/pkg/lang/vm/code/code.go
new file mode 100644
index 0000000..ab06d27
--- /dev/null
+++ b/pkg/lang/vm/code/code.go
@@ -0,0 +1,59 @@
+package code
+
+import (
+	"bytes"
+	"encoding/binary"
+	"math"
+	"strings"
+)
+
+type Code struct {
+	code []byte
+}
+
+func (c *Code) Len() int {
+	return len(c.code)
+}
+
+func (c *Code) GetOp(at int) (Op, int) {
+	return Op(c.code[at]), 1
+}
+
+func (c *Code) GetUint(at int) (uint64, int) {
+	advance := 8
+	x := binary.LittleEndian.Uint64(c.code[at : at+advance])
+	return x, advance
+}
+
+func (c *Code) GetInt(at int) (int64, int) {
+	x, advance := c.GetUint(at)
+	return int64(x), advance
+}
+
+func (c *Code) GetFloat(at int) (float64, int) {
+	x, advance := c.GetUint(at)
+	return math.Float64frombits(x), advance
+}
+
+func (c *Code) GetString(at int) (string, int) {
+	advance := 0
+	reader := bytes.NewReader(c.code[at:])
+	builder := strings.Builder{}
+
+	for {
+		r, size, err := reader.ReadRune()
+		advance += size
+
+		if err != nil {
+			break
+		}
+
+		if r == 0 {
+			break
+		}
+
+		builder.WriteRune(r)
+	}
+
+	return builder.String(), advance
+}
diff --git a/pkg/lang/vm/code/op.go b/pkg/lang/vm/code/op.go
new file mode 100644
index 0000000..ae37603
--- /dev/null
+++ b/pkg/lang/vm/code/op.go
@@ -0,0 +1,34 @@
+package code
+
+type Op uint8
+
+const (
+	OpNop Op = iota
+	OpHalt
+
+	OpPushInt
+	OpPushFloat
+	OpPushString
+	OpPushTrue
+	OpPushFalse
+	OpPushNull
+	OpPushArray
+	OpPushFunction
+	OpPushObject
+
+	OpGetGlobal
+	OpGetLocal
+	OpGetMember
+	OpGetArg
+	OpGetEnv
+
+	OpAdd
+	OpSub
+	OpIndex
+	OpCall
+
+	OpJmp
+	OpJez
+
+	OpRet
+)