mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
Hide fields in vm.Program
This commit is contained in:
+12
-13
@@ -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")
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user