From 0063922f5c8a07b78603b2da7f6a3c2094711c3d Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 23 Apr 2024 14:36:57 +0200 Subject: feat: initial and partial support of composite expressions (#9) A new `Composite` token is created. Literal composite expressions are recognized and partially handled by the parser but not yet by the code generator. Other cosmetic changes are present. --- vm/type.go | 18 ++++++++++++++++-- vm/vm.go | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'vm') diff --git a/vm/type.go b/vm/type.go index 16e3733..49215db 100644 --- a/vm/type.go +++ b/vm/type.go @@ -10,10 +10,19 @@ type Type struct { Rtype reflect.Type } +func (t *Type) String() string { + if t.Name != "" { + return t.Name + } + return t.Rtype.String() +} + +// Elem returns a type's element type. func (t *Type) Elem() *Type { return &Type{Rtype: t.Rtype.Elem()} } +// Out returns the type's i'th output parameter. func (t *Type) Out(i int) *Type { return &Type{Rtype: t.Rtype.Out(i)} } @@ -43,18 +52,22 @@ func ValueOf(v any) Value { return Value{Data: reflect.ValueOf(v)} } +// PointerTo returns the pointer type with element t. func PointerTo(t *Type) *Type { return &Type{Rtype: reflect.PointerTo(t.Rtype)} } -func ArrayOf(size int, t *Type) *Type { - return &Type{Rtype: reflect.ArrayOf(size, t.Rtype)} +// ArrayOf returns the array type with the given length and element type. +func ArrayOf(length int, t *Type) *Type { + return &Type{Rtype: reflect.ArrayOf(length, t.Rtype)} } +// SliceOf returns the slice type with the given element type. func SliceOf(t *Type) *Type { return &Type{Rtype: reflect.SliceOf(t.Rtype)} } +// FuncOf returns the function type with the given argument and result types. func FuncOf(arg, ret []*Type, variadic bool) *Type { a := make([]reflect.Type, len(arg)) for i, e := range arg { @@ -67,6 +80,7 @@ func FuncOf(arg, ret []*Type, variadic bool) *Type { return &Type{Rtype: reflect.FuncOf(a, r, variadic)} } +// StructOf returns the struct type with the given field types. func StructOf(fields []*Type) *Type { rf := make([]reflect.StructField, len(fields)) for i, f := range fields { diff --git a/vm/vm.go b/vm/vm.go index 0b2a1ad..408be6e 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -1,3 +1,4 @@ +// Package vm implement a stack based virtual machine. package vm import ( @@ -85,6 +86,7 @@ var strop = [...]string{ // for VM tracing. Vassign: "Vassign", } +// Code represents the virtual machine byte code. type Code [][]int64 // Machine represents a virtual machine. @@ -256,19 +258,24 @@ func (m *Machine) Run() (err error) { } } +// PushCode adds instructions to the machine code. func (m *Machine) PushCode(code ...[]int64) (p int) { p = len(m.code) m.code = append(m.code, code...) return p } +// SetIP sets the value of machine instruction pointer to given index. func (m *Machine) SetIP(ip int) { m.ip = ip } + +// Push pushes data values on top of machine memory stack. func (m *Machine) Push(v ...Value) (l int) { l = len(m.mem) m.mem = append(m.mem, v...) return l } +// Pop removes and returns the value on the top of machine stack. func (m *Machine) Pop() (v Value) { l := len(m.mem) - 1 v = m.mem[l] @@ -276,6 +283,7 @@ func (m *Machine) Pop() (v Value) { return v } +// Top returns (but not remove) the value on the top of machine stack. func (m *Machine) Top() (v Value) { if l := len(m.mem); l > 0 { v = m.mem[l-1] @@ -283,12 +291,14 @@ func (m *Machine) Top() (v Value) { return v } +// PopExit removes the last machine code instruction if is Exit. func (m *Machine) PopExit() { if l := len(m.code); l > 0 && m.code[l-1][1] == Exit { m.code = m.code[:l-1] } } +// CodeString returns the string representation of a machine code instruction. func CodeString(op []int64) string { switch len(op) { case 2: @@ -317,6 +327,7 @@ func slint(a []int64) []int { return r } +// Vstring returns the string repreentation of a list of values. func Vstring(lv []Value) string { s := "[" for _, v := range lv { -- cgit v1.2.3