Merge pull request #72 from d5/compiledset
replacing values of the compiled script
This commit is contained in:
commit
0d99cca738
4 changed files with 70 additions and 1 deletions
|
@ -70,12 +70,23 @@ func main() {
|
|||
|
||||
// retrieve value of 'a'
|
||||
a := c.Get("a")
|
||||
fmt.Println(a.Int())
|
||||
fmt.Println(a.Int()) // prints "30"
|
||||
|
||||
// re-run after replacing value of 'b'
|
||||
if err := c.Set("b", 20); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := c.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(c.Get("a").Int()) // prints "40"
|
||||
}
|
||||
```
|
||||
|
||||
A variable `b` is defined by the user before compilation using [Script.Add](https://godoc.org/github.com/d5/tengo/script#Script.Add) function. Then a compiled bytecode `c` is used to execute the bytecode and get the value of global variables. In this example, the value of global variable `a` is read using [Compiled.Get](https://godoc.org/github.com/d5/tengo/script#Compiled.Get) function. See [documentation](https://godoc.org/github.com/d5/tengo/script#Variable) for the full list of variable value functions.
|
||||
|
||||
Value of the global variables can be replaced using [Compiled.Set](https://godoc.org/github.com/d5/tengo/script#Compiled.Set) function. But it will return an error if you try to set the value of un-defined global variables _(e.g. trying to set the value of `x` in the example)_.
|
||||
|
||||
### Type Conversion Table
|
||||
|
||||
When adding a Variable _([Script.Add](https://godoc.org/github.com/d5/tengo/script#Script.Add))_, Script converts Go values into Tengo values based on the following conversion table.
|
||||
|
|
|
@ -80,6 +80,15 @@ func (v *VM) Abort() {
|
|||
|
||||
// Run starts the execution.
|
||||
func (v *VM) Run() error {
|
||||
// reset VM states
|
||||
v.sp = 0
|
||||
v.curFrame = &(v.frames[0])
|
||||
v.curInsts = v.curFrame.fn.Instructions
|
||||
v.curIPLimit = len(v.curInsts) - 1
|
||||
v.framesIndex = 1
|
||||
v.ip = -1
|
||||
atomic.StoreInt64(&v.aborting, 0)
|
||||
|
||||
for v.ip < v.curIPLimit && (atomic.LoadInt64(&v.aborting) == 0) {
|
||||
v.ip++
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package script
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/d5/tengo/compiler"
|
||||
"github.com/d5/tengo/objects"
|
||||
|
@ -92,3 +93,21 @@ func (c *Compiled) GetAll() []*Variable {
|
|||
|
||||
return vars
|
||||
}
|
||||
|
||||
// Set replaces the value of a global variable identified by the name.
|
||||
// An error will be returned if the name was not defined during compilation.
|
||||
func (c *Compiled) Set(name string, value interface{}) error {
|
||||
obj, err := objects.FromInterface(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symbol, _, ok := c.symbolTable.Resolve(name)
|
||||
if !ok || symbol.Scope != compiler.ScopeGlobal {
|
||||
return fmt.Errorf("'%s' is not defined", name)
|
||||
}
|
||||
|
||||
c.machine.Globals()[symbol.Index] = &obj
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -47,6 +47,36 @@ func TestCompiled_IsDefined(t *testing.T) {
|
|||
compiledIsDefined(t, c, "b", false)
|
||||
}
|
||||
|
||||
func TestCompiled_Set(t *testing.T) {
|
||||
c := compile(t, `a := b`, M{"b": "foo"})
|
||||
compiledRun(t, c)
|
||||
compiledGet(t, c, "a", "foo")
|
||||
|
||||
// replace value of 'b'
|
||||
err := c.Set("b", "bar")
|
||||
assert.NoError(t, err)
|
||||
compiledRun(t, c)
|
||||
compiledGet(t, c, "a", "bar")
|
||||
|
||||
// try to replace undefined variable
|
||||
err = c.Set("c", 1984)
|
||||
assert.Error(t, err) // 'c' is not defined
|
||||
|
||||
// case #2
|
||||
c = compile(t, `
|
||||
a := func() {
|
||||
return func() {
|
||||
return b + 5
|
||||
}()
|
||||
}()`, M{"b": 5})
|
||||
compiledRun(t, c)
|
||||
compiledGet(t, c, "a", int64(10))
|
||||
err = c.Set("b", 10)
|
||||
assert.NoError(t, err)
|
||||
compiledRun(t, c)
|
||||
compiledGet(t, c, "a", int64(15))
|
||||
}
|
||||
|
||||
func TestCompiled_RunContext(t *testing.T) {
|
||||
// machine completes normally
|
||||
c := compile(t, `a := 5`, nil)
|
||||
|
|
Loading…
Reference in a new issue