Hide fields in vm.Program

This commit is contained in:
Anton Medvedev
2023-11-27 13:52:56 +01:00
parent b842f902b4
commit 2cf93593f4
5 changed files with 60 additions and 34 deletions
+12 -13
View File
@@ -47,17 +47,16 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro
c.emit(OpCast, 2)
}
program = &Program{
Node: tree.Node,
Source: tree.Source,
Locations: c.locations,
Variables: c.variables,
Constants: c.constants,
Bytecode: c.bytecode,
Arguments: c.arguments,
Functions: c.functions,
DebugInfo: c.debugInfo,
}
program = NewProgram(
tree.Source,
c.locations,
c.variables,
c.constants,
c.bytecode,
c.arguments,
c.functions,
c.debugInfo,
)
return
}
@@ -145,7 +144,7 @@ func (c *compiler) addVariable(name string) int {
return p
}
// emitFunction adds builtin.Function.Func to the program.Functions and emits call opcode.
// emitFunction adds builtin.Function.Func to the program.functions and emits call opcode.
func (c *compiler) emitFunction(fn *ast.Function, argsLen int) {
switch argsLen {
case 0:
@@ -162,7 +161,7 @@ func (c *compiler) emitFunction(fn *ast.Function, argsLen int) {
}
}
// addFunction adds builtin.Function.Func to the program.Functions and returns its index.
// addFunction adds builtin.Function.Func to the program.functions and returns its index.
func (c *compiler) addFunction(fn *ast.Function) int {
if fn == nil {
panic("function is nil")
+3
View File
@@ -40,6 +40,9 @@ func (s *Source) Content() string {
}
func (s *Source) Snippet(line int) (string, bool) {
if s == nil {
return "", false
}
charStart, found := s.findLineOffset(line)
if !found || len(s.contents) == 0 {
return "", false
+30 -9
View File
@@ -9,22 +9,43 @@ import (
"strings"
"text/tabwriter"
"github.com/antonmedv/expr/ast"
"github.com/antonmedv/expr/builtin"
"github.com/antonmedv/expr/file"
"github.com/antonmedv/expr/vm/runtime"
)
type Program struct {
Node ast.Node
Source *file.Source
Locations []file.Location
Variables []any
Constants []any
Bytecode []Opcode
Arguments []int
Functions []Function
DebugInfo map[string]string
Constants []any
source *file.Source
locations []file.Location
variables []any
functions []Function
debugInfo map[string]string
}
func NewProgram(
source *file.Source,
locations []file.Location,
variables []any,
constants []any,
bytecode []Opcode,
arguments []int,
functions []Function,
debugInfo map[string]string,
) *Program {
return &Program{
source: source,
locations: locations,
variables: variables,
Constants: constants,
Bytecode: bytecode,
Arguments: arguments,
functions: functions,
debugInfo: debugInfo,
}
}
func (program *Program) Disassemble() string {
@@ -56,7 +77,7 @@ func (program *Program) Opcodes(w io.Writer) {
_, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\n", pp, label, arg)
}
argumentWithInfo := func(label string, prefix string) {
_, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, program.DebugInfo[fmt.Sprintf("%s_%d", prefix, arg)])
_, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, program.debugInfo[fmt.Sprintf("%s_%d", prefix, arg)])
}
constant := func(label string) {
var c any
+13 -9
View File
@@ -59,14 +59,18 @@ func Debug() *VM {
func (vm *VM) Run(program *Program, env any) (_ any, err error) {
defer func() {
if r := recover(); r != nil {
var location file.Location
if vm.ip-1 < len(program.locations) {
location = program.locations[vm.ip-1]
}
f := &file.Error{
Location: program.Locations[vm.ip-1],
Location: location,
Message: fmt.Sprintf("%v", r),
}
if err, ok := r.(error); ok {
f.Wrap(err)
}
err = f.Bind(program.Source)
err = f.Bind(program.source)
}
}()
@@ -108,10 +112,10 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
vm.pop()
case OpStore:
program.Variables[arg] = vm.pop()
program.variables[arg] = vm.pop()
case OpLoadVar:
vm.push(program.Variables[arg])
vm.push(program.variables[arg])
case OpLoadConst:
vm.push(runtime.Fetch(env, program.Constants[arg]))
@@ -126,7 +130,7 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
vm.push(runtime.FetchMethod(env, program.Constants[arg].(*runtime.Method)))
case OpLoadFunc:
vm.push(program.Functions[arg])
vm.push(program.functions[arg])
case OpFetch:
b := vm.pop()
@@ -332,7 +336,7 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
vm.push(out[0].Interface())
case OpCall0:
out, err := program.Functions[arg]()
out, err := program.functions[arg]()
if err != nil {
panic(err)
}
@@ -340,7 +344,7 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
case OpCall1:
a := vm.pop()
out, err := program.Functions[arg](a)
out, err := program.functions[arg](a)
if err != nil {
panic(err)
}
@@ -349,7 +353,7 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
case OpCall2:
b := vm.pop()
a := vm.pop()
out, err := program.Functions[arg](a, b)
out, err := program.functions[arg](a, b)
if err != nil {
panic(err)
}
@@ -359,7 +363,7 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
c := vm.pop()
b := vm.pop()
a := vm.pop()
out, err := program.Functions[arg](a, b, c)
out, err := program.functions[arg](a, b, c)
if err != nil {
panic(err)
}
+2 -3
View File
@@ -6,14 +6,14 @@ import (
"reflect"
"testing"
"github.com/stretchr/testify/require"
"github.com/antonmedv/expr/ast"
"github.com/antonmedv/expr/checker"
"github.com/antonmedv/expr/compiler"
"github.com/antonmedv/expr/conf"
"github.com/antonmedv/expr/file"
"github.com/antonmedv/expr/parser"
"github.com/antonmedv/expr/vm"
"github.com/stretchr/testify/require"
)
func TestRun_NilProgram(t *testing.T) {
@@ -282,7 +282,6 @@ func TestRun_TaggedFieldName(t *testing.T) {
func TestRun_OpInvalid(t *testing.T) {
program := &vm.Program{
Locations: []file.Location{{0, 0}},
Bytecode: []vm.Opcode{vm.OpInvalid},
Arguments: []int{0},
}