github.com/mattn/anko@v0.1.10/vm/vm_test.go (about)

     1  package vm
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"reflect"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/mattn/anko/ast"
    14  	"github.com/mattn/anko/ast/astutil"
    15  	"github.com/mattn/anko/env"
    16  	"github.com/mattn/anko/parser"
    17  )
    18  
    19  func TestNumbers(t *testing.T) {
    20  	t.Parallel()
    21  
    22  	tests := []Test{
    23  		{Script: ``},
    24  		{Script: `;`},
    25  		{Script: `
    26  `},
    27  		{Script: `
    28  1
    29  `, RunOutput: int64(1)},
    30  
    31  		{Script: `1..1`, ParseError: fmt.Errorf("invalid number: 1..1")},
    32  		{Script: `1e.1`, ParseError: fmt.Errorf("invalid number: 1e.1")},
    33  		{Script: `1ee1`, ParseError: fmt.Errorf("syntax error")},
    34  		{Script: `1e+e1`, ParseError: fmt.Errorf("syntax error")},
    35  		{Script: `0x1g`, ParseError: fmt.Errorf("syntax error")},
    36  		{Script: `9223372036854775808`, ParseError: fmt.Errorf("invalid number: 9223372036854775808")},
    37  		{Script: `-9223372036854775809`, ParseError: fmt.Errorf("invalid number: -9223372036854775809")},
    38  
    39  		{Script: `1`, RunOutput: int64(1)},
    40  		{Script: `-1`, RunOutput: int64(-1)},
    41  		{Script: `9223372036854775807`, RunOutput: int64(9223372036854775807)},
    42  		{Script: `-9223372036854775808`, RunOutput: int64(-9223372036854775808)},
    43  		{Script: `-9223372036854775807-1`, RunOutput: int64(-9223372036854775808)},
    44  		{Script: `-9223372036854775807 -1`, RunOutput: int64(-9223372036854775808)},
    45  		{Script: `-9223372036854775807 - 1`, RunOutput: int64(-9223372036854775808)},
    46  		{Script: `1.1`, RunOutput: float64(1.1)},
    47  		{Script: `-1.1`, RunOutput: float64(-1.1)},
    48  
    49  		{Script: `1e1`, RunOutput: float64(10)},
    50  		{Script: `1.5e1`, RunOutput: float64(15)},
    51  		{Script: `1e-1`, RunOutput: float64(0.1)},
    52  
    53  		{Script: `-1e1`, RunOutput: float64(-10)},
    54  		{Script: `-1.5e1`, RunOutput: float64(-15)},
    55  		{Script: `-1e-1`, RunOutput: float64(-0.1)},
    56  
    57  		{Script: `0x1`, RunOutput: int64(1)},
    58  		{Script: `0xa`, RunOutput: int64(10)},
    59  		{Script: `0xb`, RunOutput: int64(11)},
    60  		{Script: `0xc`, RunOutput: int64(12)},
    61  		{Script: `0xe`, RunOutput: int64(14)},
    62  		{Script: `0xf`, RunOutput: int64(15)},
    63  		{Script: `0Xf`, RunOutput: int64(15)},
    64  		{Script: `0XF`, RunOutput: int64(15)},
    65  		{Script: `0x7FFFFFFFFFFFFFFF`, RunOutput: int64(9223372036854775807)},
    66  
    67  		{Script: `-0x1`, RunOutput: int64(-1)},
    68  		{Script: `-0xc`, RunOutput: int64(-12)},
    69  		{Script: `-0xe`, RunOutput: int64(-14)},
    70  		{Script: `-0xf`, RunOutput: int64(-15)},
    71  		{Script: `-0Xf`, RunOutput: int64(-15)},
    72  		{Script: `-0x7FFFFFFFFFFFFFFF`, RunOutput: int64(-9223372036854775807)},
    73  	}
    74  	runTests(t, tests, nil, &Options{Debug: true})
    75  }
    76  
    77  func TestStrings(t *testing.T) {
    78  	t.Parallel()
    79  
    80  	tests := []Test{
    81  		{Script: `a`, Input: map[string]interface{}{"a": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a'}},
    82  		{Script: `a.b`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support member operation"), Output: map[string]interface{}{"a": 'a'}},
    83  		{Script: `a[0]`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support index operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}},
    84  		{Script: `a[0:1]`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support slice operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}},
    85  
    86  		{Script: `a.b = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support member operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}},
    87  		{Script: `a[0] = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support index operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}},
    88  		{Script: `a[0:1] = "a"`, Input: map[string]interface{}{"a": 'a'}, RunError: fmt.Errorf("type int32 does not support slice operation"), RunOutput: nil, Output: map[string]interface{}{"a": 'a'}},
    89  
    90  		{Script: `a.b = "a"`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("type string does not support member operation"), Output: map[string]interface{}{"a": "test"}},
    91  		{Script: `a[0:1] = "a"`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("type string does not support slice operation for assignment"), Output: map[string]interface{}{"a": "test"}},
    92  
    93  		{Script: `a`, Input: map[string]interface{}{"a": "test"}, RunOutput: "test", Output: map[string]interface{}{"a": "test"}},
    94  		{Script: `a["a"]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index must be a number"), Output: map[string]interface{}{"a": "test"}},
    95  		{Script: `a[0]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}},
    96  		{Script: `a[-1]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test"}},
    97  		{Script: `a[0]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "t", Output: map[string]interface{}{"a": "test"}},
    98  		{Script: `a[1]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "e", Output: map[string]interface{}{"a": "test"}},
    99  		{Script: `a[3]`, Input: map[string]interface{}{"a": "test"}, RunOutput: "t", Output: map[string]interface{}{"a": "test"}},
   100  		{Script: `a[4]`, Input: map[string]interface{}{"a": "test"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test"}},
   101  
   102  		{Script: `a`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}},
   103  		{Script: `a[0]`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: `"`, Output: map[string]interface{}{"a": `"a"`}},
   104  		{Script: `a[1]`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: "a", Output: map[string]interface{}{"a": `"a"`}},
   105  
   106  		{Script: `a = "\"a\""`, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}},
   107  		{Script: `a = "\"a\""; a`, RunOutput: `"a"`, Output: map[string]interface{}{"a": `"a"`}},
   108  		{Script: `a = "\"a\""; a[0]`, RunOutput: `"`, Output: map[string]interface{}{"a": `"a"`}},
   109  		{Script: `a = "\"a\""; a[1]`, RunOutput: "a", Output: map[string]interface{}{"a": `"a"`}},
   110  
   111  		{Script: `a`, Input: map[string]interface{}{"a": "a\\b"}, RunOutput: "a\\b", Output: map[string]interface{}{"a": "a\\b"}},
   112  		{Script: `a`, Input: map[string]interface{}{"a": "a\\\\b"}, RunOutput: "a\\\\b", Output: map[string]interface{}{"a": "a\\\\b"}},
   113  		{Script: `a = "a\b"`, RunOutput: "a\b", Output: map[string]interface{}{"a": "a\b"}},
   114  		{Script: `a = "a\\b"`, RunOutput: "a\\b", Output: map[string]interface{}{"a": "a\\b"}},
   115  
   116  		{Script: `a[:]`, Input: map[string]interface{}{"a": "test data"}, ParseError: fmt.Errorf("syntax error"), Output: map[string]interface{}{"a": "test data"}},
   117  
   118  		{Script: `a[0:]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}},
   119  		{Script: `a[1:]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}},
   120  		{Script: `a[:0]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}},
   121  		{Script: `a[:1]`, Input: map[string]interface{}{"a": ""}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}},
   122  		{Script: `a[0:0]`, Input: map[string]interface{}{"a": ""}, RunOutput: "", Output: map[string]interface{}{"a": ""}},
   123  
   124  		{Script: `a[1:0]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   125  		{Script: `a[-1:2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   126  		{Script: `a[1:-2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   127  		{Script: `a[-1:]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   128  		{Script: `a[:-2]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   129  
   130  		{Script: `a[0:0]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}},
   131  		{Script: `a[0:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t", Output: map[string]interface{}{"a": "test data"}},
   132  		{Script: `a[0:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "te", Output: map[string]interface{}{"a": "test data"}},
   133  		{Script: `a[0:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "tes", Output: map[string]interface{}{"a": "test data"}},
   134  		{Script: `a[0:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test da", Output: map[string]interface{}{"a": "test data"}},
   135  		{Script: `a[0:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test dat", Output: map[string]interface{}{"a": "test data"}},
   136  		{Script: `a[0:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}},
   137  		{Script: `a[0:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   138  
   139  		{Script: `a[1:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}},
   140  		{Script: `a[1:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "e", Output: map[string]interface{}{"a": "test data"}},
   141  		{Script: `a[1:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "es", Output: map[string]interface{}{"a": "test data"}},
   142  		{Script: `a[1:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est da", Output: map[string]interface{}{"a": "test data"}},
   143  		{Script: `a[1:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est dat", Output: map[string]interface{}{"a": "test data"}},
   144  		{Script: `a[1:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}},
   145  		{Script: `a[1:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   146  
   147  		{Script: `a[0:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}},
   148  		{Script: `a[1:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}},
   149  		{Script: `a[2:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "st data", Output: map[string]interface{}{"a": "test data"}},
   150  		{Script: `a[3:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t data", Output: map[string]interface{}{"a": "test data"}},
   151  		{Script: `a[7:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "ta", Output: map[string]interface{}{"a": "test data"}},
   152  		{Script: `a[8:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "a", Output: map[string]interface{}{"a": "test data"}},
   153  		{Script: `a[9:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}},
   154  
   155  		{Script: `a[:0]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}},
   156  		{Script: `a[:1]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t", Output: map[string]interface{}{"a": "test data"}},
   157  		{Script: `a[:2]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "te", Output: map[string]interface{}{"a": "test data"}},
   158  		{Script: `a[:3]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "tes", Output: map[string]interface{}{"a": "test data"}},
   159  		{Script: `a[:7]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test da", Output: map[string]interface{}{"a": "test data"}},
   160  		{Script: `a[:8]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test dat", Output: map[string]interface{}{"a": "test data"}},
   161  		{Script: `a[:9]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}},
   162  		{Script: `a[:10]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   163  
   164  		{Script: `a[0:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "test data", Output: map[string]interface{}{"a": "test data"}},
   165  		{Script: `a[1:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "est data", Output: map[string]interface{}{"a": "test data"}},
   166  		{Script: `a[2:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "st data", Output: map[string]interface{}{"a": "test data"}},
   167  		{Script: `a[3:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "t data", Output: map[string]interface{}{"a": "test data"}},
   168  		{Script: `a[7:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "ta", Output: map[string]interface{}{"a": "test data"}},
   169  		{Script: `a[8:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "a", Output: map[string]interface{}{"a": "test data"}},
   170  		{Script: `a[9:]`, Input: map[string]interface{}{"a": "test data"}, RunOutput: "", Output: map[string]interface{}{"a": "test data"}},
   171  		{Script: `a[10:]`, Input: map[string]interface{}{"a": "test data"}, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "test data"}},
   172  
   173  		// index assignment - len 0
   174  		{Script: `a = ""; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "x"}},
   175  		{Script: `a = ""; a[1] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": ""}},
   176  
   177  		// index assignment - len 1
   178  		{Script: `a = "a"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "x"}},
   179  		{Script: `a = "a"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "ax"}},
   180  		{Script: `a = "a"; a[2] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "a"}},
   181  
   182  		// index assignment - len 2
   183  		{Script: `a = "ab"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "xb"}},
   184  		{Script: `a = "ab"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "ax"}},
   185  		{Script: `a = "ab"; a[2] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abx"}},
   186  		{Script: `a = "ab"; a[3] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "ab"}},
   187  
   188  		// index assignment - len 3
   189  		{Script: `a = "abc"; a[0] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "xbc"}},
   190  		{Script: `a = "abc"; a[1] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "axc"}},
   191  		{Script: `a = "abc"; a[2] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abx"}},
   192  		{Script: `a = "abc"; a[3] = "x"`, RunOutput: "x", Output: map[string]interface{}{"a": "abcx"}},
   193  		{Script: `a = "abc"; a[4] = "x"`, RunError: fmt.Errorf("index out of range"), Output: map[string]interface{}{"a": "abc"}},
   194  
   195  		// index assignment - vm types
   196  		{Script: `a = "abc"; a[1] = nil`, RunOutput: nil, Output: map[string]interface{}{"a": "ac"}},
   197  		{Script: `a = "abc"; a[1] = true`, RunError: fmt.Errorf("type bool cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   198  		{Script: `a = "abc"; a[1] = 120`, RunOutput: int64(120), Output: map[string]interface{}{"a": "axc"}},
   199  		{Script: `a = "abc"; a[1] = 2.2`, RunError: fmt.Errorf("type float64 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   200  		{Script: `a = "abc"; a[1] = ["a"]`, RunError: fmt.Errorf("type []interface {} cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   201  
   202  		// index assignment - Go types
   203  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunError: fmt.Errorf("type reflect.Value cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   204  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": "ac"}},
   205  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": true}, RunError: fmt.Errorf("type bool cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   206  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": int32(120)}, RunOutput: int32(120), Output: map[string]interface{}{"a": "axc"}},
   207  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": int64(120)}, RunOutput: int64(120), Output: map[string]interface{}{"a": "axc"}},
   208  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunError: fmt.Errorf("type float32 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   209  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": float64(2.2)}, RunError: fmt.Errorf("type float64 cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   210  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": "x"}, RunOutput: "x", Output: map[string]interface{}{"a": "axc"}},
   211  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": 'x'}, RunOutput: 'x', Output: map[string]interface{}{"a": "axc"}},
   212  		{Script: `a = "abc"; a[1] = b`, Input: map[string]interface{}{"b": struct{}{}}, RunError: fmt.Errorf("type struct {} cannot be assigned to type string"), Output: map[string]interface{}{"a": "abc"}},
   213  	}
   214  	runTests(t, tests, nil, &Options{Debug: true})
   215  }
   216  
   217  func TestVar(t *testing.T) {
   218  	t.Parallel()
   219  
   220  	testInput1 := map[string]interface{}{"b": func() {}}
   221  	tests := []Test{
   222  		// simple one variable
   223  		{Script: `1 = 2`, RunError: fmt.Errorf("invalid operation")},
   224  		{Script: `var 1 = 2`, ParseError: fmt.Errorf("syntax error")},
   225  		{Script: `a = 1++`, RunError: fmt.Errorf("invalid operation")},
   226  		{Script: `var a = 1++`, RunError: fmt.Errorf("invalid operation")},
   227  		{Script: `a := 1`, ParseError: fmt.Errorf("syntax error")},
   228  		{Script: `var a := 1`, ParseError: fmt.Errorf("syntax error")},
   229  		{Script: `y = z`, RunError: fmt.Errorf("undefined symbol 'z'")},
   230  
   231  		{Script: `a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   232  		{Script: `a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}},
   233  		{Script: `a = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   234  		{Script: `a = 1.1`, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}},
   235  		{Script: `a = "a"`, RunOutput: "a", Output: map[string]interface{}{"a": "a"}},
   236  
   237  		{Script: `var a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   238  		{Script: `var a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}},
   239  		{Script: `var a = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   240  		{Script: `var a = 1.1`, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}},
   241  		{Script: `var a = "a"`, RunOutput: "a", Output: map[string]interface{}{"a": "a"}},
   242  
   243  		{Script: `a = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunOutput: reflect.Value{}, Output: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}},
   244  		{Script: `a = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": nil, "b": nil}},
   245  		{Script: `a = b`, Input: map[string]interface{}{"b": true}, RunOutput: true, Output: map[string]interface{}{"a": true, "b": true}},
   246  		{Script: `a = b`, Input: map[string]interface{}{"b": int32(1)}, RunOutput: int32(1), Output: map[string]interface{}{"a": int32(1), "b": int32(1)}},
   247  		{Script: `a = b`, Input: map[string]interface{}{"b": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1), "b": int64(1)}},
   248  		{Script: `a = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunOutput: float32(1.1), Output: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}},
   249  		{Script: `a = b`, Input: map[string]interface{}{"b": float64(1.1)}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}},
   250  		{Script: `a = b`, Input: map[string]interface{}{"b": "a"}, RunOutput: "a", Output: map[string]interface{}{"a": "a", "b": "a"}},
   251  		{Script: `a = b`, Input: map[string]interface{}{"b": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a', "b": 'a'}},
   252  		{Script: `a = b`, Input: map[string]interface{}{"b": struct{}{}}, RunOutput: struct{}{}, Output: map[string]interface{}{"a": struct{}{}, "b": struct{}{}}},
   253  
   254  		{Script: `var a = b`, Input: map[string]interface{}{"b": reflect.Value{}}, RunOutput: reflect.Value{}, Output: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}},
   255  		{Script: `var a = b`, Input: map[string]interface{}{"b": nil}, RunOutput: nil, Output: map[string]interface{}{"a": nil, "b": nil}},
   256  		{Script: `var a = b`, Input: map[string]interface{}{"b": true}, RunOutput: true, Output: map[string]interface{}{"a": true, "b": true}},
   257  		{Script: `var a = b`, Input: map[string]interface{}{"b": int32(1)}, RunOutput: int32(1), Output: map[string]interface{}{"a": int32(1), "b": int32(1)}},
   258  		{Script: `var a = b`, Input: map[string]interface{}{"b": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1), "b": int64(1)}},
   259  		{Script: `var a = b`, Input: map[string]interface{}{"b": float32(1.1)}, RunOutput: float32(1.1), Output: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}},
   260  		{Script: `var a = b`, Input: map[string]interface{}{"b": float64(1.1)}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}},
   261  		{Script: `var a = b`, Input: map[string]interface{}{"b": "a"}, RunOutput: "a", Output: map[string]interface{}{"a": "a", "b": "a"}},
   262  		{Script: `var a = b`, Input: map[string]interface{}{"b": 'a'}, RunOutput: 'a', Output: map[string]interface{}{"a": 'a', "b": 'a'}},
   263  		{Script: `var a = b`, Input: map[string]interface{}{"b": struct{}{}}, RunOutput: struct{}{}, Output: map[string]interface{}{"a": struct{}{}, "b": struct{}{}}},
   264  
   265  		// simple one variable overwrite
   266  		{Script: `a = true; a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   267  		{Script: `a = nil; a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}},
   268  		{Script: `a = 1; a = 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   269  		{Script: `a = 1.1; a = 2.2`, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   270  		{Script: `a = "a"; a = "b"`, RunOutput: "b", Output: map[string]interface{}{"a": "b"}},
   271  
   272  		{Script: `var a = true; var a = nil`, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   273  		{Script: `var a = nil; var a = true`, RunOutput: true, Output: map[string]interface{}{"a": true}},
   274  		{Script: `var a = 1; var a = 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   275  		{Script: `var a = 1.1; var a = 2.2`, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   276  		{Script: `var a = "a"; var a = "b"`, RunOutput: "b", Output: map[string]interface{}{"a": "b"}},
   277  
   278  		{Script: `a = nil`, Input: map[string]interface{}{"a": true}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   279  		{Script: `a = true`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": true}},
   280  		{Script: `a = 2`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   281  		{Script: `a = 2`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   282  		{Script: `a = 2.2`, Input: map[string]interface{}{"a": float32(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   283  		{Script: `a = 2.2`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   284  		{Script: `a = "b"`, Input: map[string]interface{}{"a": "a"}, RunOutput: "b", Output: map[string]interface{}{"a": "b"}},
   285  
   286  		{Script: `var a = nil`, Input: map[string]interface{}{"a": true}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   287  		{Script: `var a = true`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": true}},
   288  		{Script: `var a = 2`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   289  		{Script: `var a = 2`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   290  		{Script: `var a = 2.2`, Input: map[string]interface{}{"a": float32(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   291  		{Script: `var a = 2.2`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: float64(2.2), Output: map[string]interface{}{"a": float64(2.2)}},
   292  		{Script: `var a = "b"`, Input: map[string]interface{}{"a": "a"}, RunOutput: "b", Output: map[string]interface{}{"a": "b"}},
   293  
   294  		// Go variable copy
   295  		{Script: `a = b`, Input: testInput1, RunOutput: testInput1["b"], Output: map[string]interface{}{"a": testInput1["b"], "b": testInput1["b"]}},
   296  		{Script: `var a = b`, Input: testInput1, RunOutput: testInput1["b"], Output: map[string]interface{}{"a": testInput1["b"], "b": testInput1["b"]}},
   297  
   298  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValue}, RunOutput: testVarValue, Output: map[string]interface{}{"a": testVarValue, "b": testVarValue}},
   299  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarBoolP}, RunOutput: testVarBoolP, Output: map[string]interface{}{"a": testVarBoolP, "b": testVarBoolP}},
   300  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarInt32P}, RunOutput: testVarInt32P, Output: map[string]interface{}{"a": testVarInt32P, "b": testVarInt32P}},
   301  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarInt64P}, RunOutput: testVarInt64P, Output: map[string]interface{}{"a": testVarInt64P, "b": testVarInt64P}},
   302  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarFloat32P}, RunOutput: testVarFloat32P, Output: map[string]interface{}{"a": testVarFloat32P, "b": testVarFloat32P}},
   303  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarFloat64P}, RunOutput: testVarFloat64P, Output: map[string]interface{}{"a": testVarFloat64P, "b": testVarFloat64P}},
   304  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarStringP}, RunOutput: testVarStringP, Output: map[string]interface{}{"a": testVarStringP, "b": testVarStringP}},
   305  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarFuncP}, RunOutput: testVarFuncP, Output: map[string]interface{}{"a": testVarFuncP, "b": testVarFuncP}},
   306  
   307  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValue}, RunOutput: testVarValue, Output: map[string]interface{}{"a": testVarValue, "b": testVarValue}},
   308  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarBoolP}, RunOutput: testVarBoolP, Output: map[string]interface{}{"a": testVarBoolP, "b": testVarBoolP}},
   309  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarInt32P}, RunOutput: testVarInt32P, Output: map[string]interface{}{"a": testVarInt32P, "b": testVarInt32P}},
   310  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarInt64P}, RunOutput: testVarInt64P, Output: map[string]interface{}{"a": testVarInt64P, "b": testVarInt64P}},
   311  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarFloat32P}, RunOutput: testVarFloat32P, Output: map[string]interface{}{"a": testVarFloat32P, "b": testVarFloat32P}},
   312  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarFloat64P}, RunOutput: testVarFloat64P, Output: map[string]interface{}{"a": testVarFloat64P, "b": testVarFloat64P}},
   313  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarStringP}, RunOutput: testVarStringP, Output: map[string]interface{}{"a": testVarStringP, "b": testVarStringP}},
   314  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarFuncP}, RunOutput: testVarFuncP, Output: map[string]interface{}{"a": testVarFuncP, "b": testVarFuncP}},
   315  
   316  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueBool}, RunOutput: testVarValueBool, Output: map[string]interface{}{"a": testVarValueBool, "b": testVarValueBool}},
   317  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueInt32}, RunOutput: testVarValueInt32, Output: map[string]interface{}{"a": testVarValueInt32, "b": testVarValueInt32}},
   318  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueInt64}, RunOutput: testVarValueInt64, Output: map[string]interface{}{"a": testVarValueInt64, "b": testVarValueInt64}},
   319  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueFloat32}, RunOutput: testVarValueFloat32, Output: map[string]interface{}{"a": testVarValueFloat32, "b": testVarValueFloat32}},
   320  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueFloat64}, RunOutput: testVarValueFloat64, Output: map[string]interface{}{"a": testVarValueFloat64, "b": testVarValueFloat64}},
   321  		{Script: `a = b`, Input: map[string]interface{}{"b": testVarValueString}, RunOutput: testVarValueString, Output: map[string]interface{}{"a": testVarValueString, "b": testVarValueString}},
   322  
   323  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueBool}, RunOutput: testVarValueBool, Output: map[string]interface{}{"a": testVarValueBool, "b": testVarValueBool}},
   324  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueInt32}, RunOutput: testVarValueInt32, Output: map[string]interface{}{"a": testVarValueInt32, "b": testVarValueInt32}},
   325  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueInt64}, RunOutput: testVarValueInt64, Output: map[string]interface{}{"a": testVarValueInt64, "b": testVarValueInt64}},
   326  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueFloat32}, RunOutput: testVarValueFloat32, Output: map[string]interface{}{"a": testVarValueFloat32, "b": testVarValueFloat32}},
   327  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueFloat64}, RunOutput: testVarValueFloat64, Output: map[string]interface{}{"a": testVarValueFloat64, "b": testVarValueFloat64}},
   328  		{Script: `var a = b`, Input: map[string]interface{}{"b": testVarValueString}, RunOutput: testVarValueString, Output: map[string]interface{}{"a": testVarValueString, "b": testVarValueString}},
   329  
   330  		// one variable spacing
   331  		{Script: `
   332  a  =  1
   333  `, RunOutput: int64(1)},
   334  		{Script: `
   335  a  =  1;
   336  `, RunOutput: int64(1)},
   337  
   338  		// one variable many values
   339  		{Script: `, b = 1, 2`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(2), Output: map[string]interface{}{"b": int64(1)}},
   340  		{Script: `var , b = 1, 2`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(2), Output: map[string]interface{}{"b": int64(1)}},
   341  		{Script: `a,  = 1, 2`, ParseError: fmt.Errorf("syntax error")},
   342  		{Script: `var a,  = 1, 2`, ParseError: fmt.Errorf("syntax error")},
   343  
   344  		// TOFIX: should not error?
   345  		{Script: `a = 1, 2`, ParseError: fmt.Errorf("syntax error")},
   346  		{Script: `var a = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}},
   347  		// TOFIX: should not error?
   348  		{Script: `a = 1, 2, 3`, ParseError: fmt.Errorf("syntax error")},
   349  		{Script: `var a = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1)}},
   350  
   351  		// two variables many values
   352  		{Script: `a, b  = 1,`, ParseError: fmt.Errorf("syntax error")},
   353  		{Script: `var a, b  = 1,`, ParseError: fmt.Errorf("syntax error")},
   354  		{Script: `a, b  = ,1`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(1)},
   355  		{Script: `var a, b  = ,1`, ParseError: fmt.Errorf("syntax error: unexpected ','"), RunOutput: int64(1)},
   356  		{Script: `a, b  = 1,,`, ParseError: fmt.Errorf("syntax error")},
   357  		{Script: `var a, b  = 1,,`, ParseError: fmt.Errorf("syntax error")},
   358  		{Script: `a, b  = ,1,`, ParseError: fmt.Errorf("syntax error")},
   359  		{Script: `var a, b  = ,1,`, ParseError: fmt.Errorf("syntax error")},
   360  		{Script: `a, b  = ,,1`, ParseError: fmt.Errorf("syntax error")},
   361  		{Script: `var a, b  = ,,1`, ParseError: fmt.Errorf("syntax error")},
   362  
   363  		{Script: `a.c, b = 1, 2`, RunError: fmt.Errorf("undefined symbol 'a'")},
   364  		{Script: `a, b.c = 1, 2`, RunError: fmt.Errorf("undefined symbol 'b'")},
   365  
   366  		{Script: `a, b = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   367  		{Script: `var a, b = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   368  		{Script: `a, b = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   369  		{Script: `var a, b = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   370  		{Script: `a, b = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   371  		{Script: `var a, b = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   372  
   373  		// three variables many values
   374  		{Script: `a, b, c = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   375  		{Script: `var a, b, c = 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   376  		{Script: `a, b, c = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   377  		{Script: `var a, b, c = 1, 2`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   378  		{Script: `a, b, c = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}},
   379  		{Script: `var a, b, c = 1, 2, 3`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}},
   380  		{Script: `a, b, c = 1, 2, 3, 4`, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}},
   381  		{Script: `var a, b, c = 1, 2, 3, 4`, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(1), "b": int64(2), "c": int64(3)}},
   382  
   383  		// scope
   384  		{Script: `func(){ a = 1 }(); a`, RunError: fmt.Errorf("undefined symbol 'a'")},
   385  		{Script: `func(){ var a = 1 }(); a`, RunError: fmt.Errorf("undefined symbol 'a'")},
   386  
   387  		{Script: `a = 1; func(){ a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   388  		{Script: `var a = 1; func(){ a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   389  		{Script: `a = 1; func(){ var a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}},
   390  		{Script: `var a = 1; func(){ var a = 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}},
   391  
   392  		// function return
   393  		{Script: `a, 1++ = func(){ return 1, 2 }()`, RunError: fmt.Errorf("invalid operation"), Output: map[string]interface{}{"a": int64(1)}},
   394  
   395  		{Script: `a = func(){ return 1 }()`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   396  		{Script: `var a = func(){ return 1 }()`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   397  		{Script: `a, b = func(){ return 1, 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   398  		{Script: `var a, b = func(){ return 1, 2 }()`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   399  	}
   400  	runTests(t, tests, nil, &Options{Debug: true})
   401  }
   402  
   403  func TestModule(t *testing.T) {
   404  	t.Parallel()
   405  
   406  	tests := []Test{
   407  		{Script: `module a.b { }`, ParseError: fmt.Errorf("syntax error")},
   408  		{Script: `module a { 1++ }`, RunError: fmt.Errorf("invalid operation")},
   409  		{Script: `module a { }; a.b`, RunError: fmt.Errorf("undefined symbol 'b'")},
   410  
   411  		{Script: `module a { b = 1 }`, RunOutput: nil},
   412  
   413  		{Script: `module a { b = nil }; a.b`, RunOutput: nil},
   414  		{Script: `module a { b = true }; a.b`, RunOutput: true},
   415  		{Script: `module a { b = 1 }; a.b`, RunOutput: int64(1)},
   416  		{Script: `module a { b = 1.5 }; a.b`, RunOutput: float64(1.5)},
   417  		{Script: `module a { b = "a" }; a.b`, RunOutput: "a"},
   418  		{Script: `module a { func b() { return "b"} }; a.b()`, RunOutput: "b"},
   419  
   420  		{Script: `module a { _b = "b"; func c() { return _b} }`, RunOutput: nil},
   421  		{Script: `module a { _b = "b"; func c() { return _b} }; a.c()`, RunOutput: "b"},
   422  
   423  		{Script: `module a { b = 1 }; var c = a; c.b = 2; c.b`, RunOutput: int64(2)},
   424  
   425  		// test module copy
   426  		{Script: `module a { b = 1 }; c = a; d = a; a.b = 2; a.b`, RunOutput: int64(2)},
   427  		{Script: `module a { b = 1 }; c = a; d = a; a.b = 2; c.b`, RunOutput: int64(1)},
   428  		{Script: `module a { b = 1 }; c = a; d = a; a.b = 2; d.b`, RunOutput: int64(1)},
   429  		{Script: `module a { b = 1 }; c = a; d = a; c.b = 2; a.b`, RunOutput: int64(1)},
   430  		{Script: `module a { b = 1 }; c = a; d = a; c.b = 2; c.b`, RunOutput: int64(2)},
   431  		{Script: `module a { b = 1 }; c = a; d = a; c.b = 2; d.b`, RunOutput: int64(1)},
   432  		{Script: `module a { b = 1 }; c = a; d = a; d.b = 2; a.b`, RunOutput: int64(1)},
   433  		{Script: `module a { b = 1 }; c = a; d = a; d.b = 2; c.b`, RunOutput: int64(1)},
   434  		{Script: `module a { b = 1 }; c = a; d = a; d.b = 2; d.b`, RunOutput: int64(2)},
   435  
   436  		{Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; a.b`, RunOutput: int64(2)},
   437  		{Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; c.b`, RunOutput: int64(1)},
   438  		{Script: `module a { b = 1 }; var c = a; var d = a; a.b = 2; d.b`, RunOutput: int64(1)},
   439  		{Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; a.b`, RunOutput: int64(1)},
   440  		{Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; c.b`, RunOutput: int64(2)},
   441  		{Script: `module a { b = 1 }; var c = a; var d = a; c.b = 2; d.b`, RunOutput: int64(1)},
   442  		{Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; a.b`, RunOutput: int64(1)},
   443  		{Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; c.b`, RunOutput: int64(1)},
   444  		{Script: `module a { b = 1 }; var c = a; var d = a; d.b = 2; d.b`, RunOutput: int64(2)},
   445  
   446  		// test type scope
   447  		{Script: `module b { make(type Duration, a) }; func c() { d = new(time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: time")},
   448  		{Script: `module time { make(type Duration, a) }; func c() { d = new(time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunOutput: time.Duration(0)},
   449  		{Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(x.time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunOutput: time.Duration(0)},
   450  		{Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(y.time.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: y")},
   451  		{Script: `module x { module time { make(type Duration, a) } }; func c() { d = new(x.y.Duration); return *d }; c()`, Input: map[string]interface{}{"a": time.Duration(0)}, RunError: fmt.Errorf("no namespace called: y")},
   452  	}
   453  	runTests(t, tests, nil, &Options{Debug: true})
   454  }
   455  
   456  func TestNew(t *testing.T) {
   457  	t.Parallel()
   458  
   459  	tests := []Test{
   460  		{Script: `new(foo)`, RunError: fmt.Errorf("undefined type 'foo'")},
   461  		{Script: `new(nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   462  
   463  		// default
   464  		{Script: `a = new(bool); *a`, RunOutput: false},
   465  		{Script: `a = new(int32); *a`, RunOutput: int32(0)},
   466  		{Script: `a = new(int64); *a`, RunOutput: int64(0)},
   467  		{Script: `a = new(float32); *a`, RunOutput: float32(0)},
   468  		{Script: `a = new(float64); *a`, RunOutput: float64(0)},
   469  		{Script: `a = new(string); *a`, RunOutput: ""},
   470  
   471  		// ptr
   472  		{Script: `a = new(*string); b = *a; *b`, RunOutput: ""},
   473  		{Script: `a = new(*string); **a`, RunOutput: ""},
   474  
   475  		// slice
   476  		{Script: `a = new([]int64); *a`, RunOutput: []int64{}},
   477  
   478  		// map
   479  		{Script: `a = new(map[string]int64); *a`, RunOutput: map[string]int64{}},
   480  
   481  		// chan
   482  		{Script: `a = new(chan int64); go func(){ (*a) <- 1 }(); <- *a`, RunOutput: int64(1)},
   483  		{Script: `a = new(chan int64); go func(){ *a <- 1 }(); <- *a`, RunOutput: int64(1)},
   484  
   485  		// struct
   486  		{Script: `a = new(struct{ A int64 }); *a`, RunOutput: struct{ A int64 }{}},
   487  	}
   488  	runTests(t, tests, nil, &Options{Debug: true})
   489  }
   490  
   491  func TestMake(t *testing.T) {
   492  	t.Parallel()
   493  
   494  	tests := []Test{
   495  		{Script: `make(map[[]string]int64)`, RunError: fmt.Errorf("reflect.MapOf: invalid key type []string")},
   496  	}
   497  	runTests(t, tests, nil, &Options{Debug: false})
   498  
   499  	tests = []Test{
   500  		{Script: `make(struct {})`, ParseError: fmt.Errorf("syntax error")},
   501  		{Script: `make(struct { , })`, ParseError: fmt.Errorf("syntax error")},
   502  		{Script: `make(struct { A map })`, ParseError: fmt.Errorf("syntax error")},
   503  		{Script: `make(struct { , A int64})`, ParseError: fmt.Errorf("syntax error")},
   504  		{Script: `make(struct { A int64, })`, ParseError: fmt.Errorf("syntax error")},
   505  
   506  		{Script: `make(foo)`, RunError: fmt.Errorf("undefined type 'foo'")},
   507  		{Script: `make(a.b)`, Types: map[string]interface{}{"a": true}, RunError: fmt.Errorf("no namespace called: a")},
   508  		{Script: `make(a.b)`, Types: map[string]interface{}{"b": true}, RunError: fmt.Errorf("no namespace called: a")},
   509  		{Script: `make([]int64, 1++)`, RunError: fmt.Errorf("invalid operation")},
   510  		{Script: `make([]int64, 1, 1++)`, RunError: fmt.Errorf("invalid operation")},
   511  		{Script: `make([]int64, 2, 1)`, RunError: fmt.Errorf("make slice len > cap")},
   512  		{Script: `make(map[foo]int64)`, RunError: fmt.Errorf("undefined type 'foo'")},
   513  		{Script: `make(map[int64]foo)`, RunError: fmt.Errorf("undefined type 'foo'")},
   514  		{Script: `make(chan foo)`, RunError: fmt.Errorf("undefined type 'foo'")},
   515  		{Script: `make(chan int64, 1++)`, RunError: fmt.Errorf("invalid operation")},
   516  		{Script: `make(struct { A foo })`, RunError: fmt.Errorf("undefined type 'foo'")},
   517  
   518  		// nill type
   519  		{Script: `make(nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   520  		{Script: `make(*nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   521  		{Script: `make([]nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   522  		{Script: `make(map[nilT]string)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   523  		{Script: `make(map[string]nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   524  		{Script: `make(chan nilT)`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   525  		{Script: `make(struct { A nilT })`, Types: map[string]interface{}{"nilT": nil}, RunError: fmt.Errorf("cannot make type nil")},
   526  
   527  		// default
   528  		{Script: `make(bool)`, RunOutput: false},
   529  		{Script: `make(int32)`, RunOutput: int32(0)},
   530  		{Script: `make(int64)`, RunOutput: int64(0)},
   531  		{Script: `make(float32)`, RunOutput: float32(0)},
   532  		{Script: `make(float64)`, RunOutput: float64(0)},
   533  		{Script: `make(string)`, RunOutput: ""},
   534  
   535  		// ptr
   536  		{Script: `a = make(*int64); *a`, RunOutput: int64(0)},
   537  		{Script: `a = make(**int64); **a`, RunOutput: int64(0)},
   538  		{Script: `a = make(***int64); ***a`, RunOutput: int64(0)},
   539  		{Script: `a = make(*[]int64); *a`, RunOutput: []int64{}},
   540  		{Script: `a = make(*map[string]int64); *a`, RunOutput: map[string]int64{}},
   541  		{Script: `a = make(*chan int64); go func(){ (*a) <- 1 }(); <- *a`, RunOutput: int64(1)},
   542  		{Script: `a = make(*chan int64); go func(){ *a <- 1 }(); <- *a`, RunOutput: int64(1)},
   543  
   544  		// slice
   545  		{Script: `make([]int64)`, RunOutput: []int64{}},
   546  		{Script: `a = make([]int64, 1); a[0]`, RunOutput: int64(0)},
   547  		{Script: `a = make([]int64, 1, 2); a[0]`, RunOutput: int64(0)},
   548  		{Script: `make([]*int64)`, RunOutput: []*int64{}},
   549  		{Script: `make([][]int64)`, RunOutput: [][]int64{}},
   550  		{Script: `make([]map[string]int64)`, RunOutput: []map[string]int64{}},
   551  
   552  		// map
   553  		{Script: `make(map[string]int64)`, RunOutput: map[string]int64{}},
   554  		{Script: `make(map[string]*int64)`, RunOutput: map[string]*int64{}},
   555  		{Script: `make(map[*string]int64)`, RunOutput: map[*string]int64{}},
   556  		{Script: `make(map[*string]*int64)`, RunOutput: map[*string]*int64{}},
   557  		{Script: `make(map[string][]int64)`, RunOutput: map[string][]int64{}},
   558  		{Script: `make(map[string]chan int64)`, RunOutput: map[string]chan int64{}},
   559  		{Script: `make(map[chan string]int64)`, RunOutput: map[chan string]int64{}},
   560  
   561  		// chan
   562  		{Script: `a = make(chan int64); go func(){ a <- 1 }(); <- a`, RunOutput: int64(1)},
   563  		{Script: `a = make(chan int64, 1); a <- 1; <- a`, RunOutput: int64(1)},
   564  		{Script: `a = make(chan *int64, 1); b = 1; a <- &b; c = <- a; *c`, RunOutput: int64(1)},
   565  		{Script: `a = make(chan []int64, 1); a <- [1]; <- a`, RunOutput: []int64{1}},
   566  		{Script: `a = make(chan map[string]int64, 1); b = make(map[string]int64); a <- b; <- a`, RunOutput: map[string]int64{}},
   567  		{Script: `a = make(chan int64, 1); b = &a; *b <- 1; <- *b`, RunOutput: int64(1)},
   568  
   569  		// struct
   570  		{Script: `make(struct { A int64 })`, RunOutput: struct{ A int64 }{}},
   571  		{Script: `make(struct { A *int64 })`, RunOutput: struct{ A *int64 }{}},
   572  		{Script: `make(struct { A []int64 })`, RunOutput: struct{ A []int64 }{A: []int64{}}},
   573  		{Script: `make(struct { A map[string]int64 })`, RunOutput: struct{ A map[string]int64 }{A: map[string]int64{}}},
   574  		{Script: `a = make(struct { A chan int64 }); go func(){ a.A <- 1 }(); <- a.A`, RunOutput: int64(1)},
   575  	}
   576  	runTests(t, tests, nil, &Options{Debug: true})
   577  }
   578  
   579  func TestMakeType(t *testing.T) {
   580  	t.Parallel()
   581  
   582  	tests := []Test{
   583  		{Script: `make(type a, 1++)`, RunError: fmt.Errorf("invalid operation")},
   584  
   585  		{Script: `make(type a, true)`, RunOutput: reflect.TypeOf(true)},
   586  		{Script: `a = make(type a, true)`, RunOutput: reflect.TypeOf(true), Output: map[string]interface{}{"a": reflect.TypeOf(true)}},
   587  		{Script: `make(type a, true); a = make([]a)`, RunOutput: []bool{}, Output: map[string]interface{}{"a": []bool{}}},
   588  		{Script: `make(type a, make([]bool))`, RunOutput: reflect.TypeOf([]bool{})},
   589  		{Script: `make(type a, make([]bool)); a = make(a)`, RunOutput: []bool{}, Output: map[string]interface{}{"a": []bool{}}},
   590  	}
   591  	runTests(t, tests, nil, &Options{Debug: true})
   592  }
   593  
   594  func TestReferencingAndDereference(t *testing.T) {
   595  	t.Parallel()
   596  
   597  	tests := []Test{
   598  		// TOFIX:
   599  		// {Script: `a = 1; b = &a; *b = 2; *b`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   600  	}
   601  	runTests(t, tests, nil, &Options{Debug: true})
   602  }
   603  
   604  func TestChan(t *testing.T) {
   605  	t.Parallel()
   606  
   607  	tests := []Test{
   608  		// send on closed channel
   609  		{Script: `a = make(chan int64, 2); close(a); a <- 1`, RunError: fmt.Errorf("send on closed channel")},
   610  	}
   611  	runTests(t, tests, nil, &Options{Debug: false})
   612  
   613  	tests = []Test{
   614  		{Script: `a = make(chan int64, 2); a <- 1; = <- a`, ParseError: fmt.Errorf("missing expressions on left side of channel operator"), RunError: fmt.Errorf("invalid operation")},
   615  
   616  		{Script: `<- 1++`, RunError: fmt.Errorf("invalid operation")},
   617  		{Script: `1++ <- 1`, RunError: fmt.Errorf("invalid operation")},
   618  		{Script: `1 <- 1++`, RunError: fmt.Errorf("invalid operation")},
   619  		{Script: `a = make(chan int64, 2); a <- 1++`, RunError: fmt.Errorf("invalid operation")},
   620  		{Script: `<- 1`, RunError: fmt.Errorf("receive from non-chan type int64")},
   621  		{Script: `1 <- 1`, RunError: fmt.Errorf("send to non-chan type int64")},
   622  		{Script: `a = make(chan int64, 2); 1 <- a`, RunError: fmt.Errorf("send to non-chan type int64")},
   623  		{Script: `a = make(chan bool, 2); a <- 1`, RunError: fmt.Errorf("cannot use type int64 as type bool to send to chan")},
   624  		{Script: `close(1++)`, RunError: fmt.Errorf("invalid operation")},
   625  		{Script: `close(1)`, RunError: fmt.Errorf("type cannot be int64 for close")},
   626  
   627  		// let channel errors
   628  		{Script: `a = <- c`, RunError: fmt.Errorf("undefined symbol 'c'")},
   629  		{Script: `a, b = <- c`, RunError: fmt.Errorf("undefined symbol 'c'")},
   630  		{Script: `a = <- 1++`, RunError: fmt.Errorf("invalid operation")},
   631  		{Script: `a, b = <- 1++`, RunError: fmt.Errorf("invalid operation")},
   632  		{Script: `c = 1; a = <- c`, RunError: fmt.Errorf("receive from non-chan type int64")},
   633  		{Script: `c = 1; a, b = <- c`, RunError: fmt.Errorf("receive from non-chan type int64")},
   634  		{Script: `a = make(chan int64, 2); a <- 1; 1++ = <- a`, RunError: fmt.Errorf("invalid operation")},
   635  		{Script: `a = make(chan int64, 2); a <- 1; 1++, b = <- a`, RunError: fmt.Errorf("invalid operation")},
   636  
   637  		// send to channel
   638  		{Script: `a <- nil`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}},
   639  		{Script: `a <- true`, Input: map[string]interface{}{"a": make(chan bool, 2)}},
   640  		{Script: `a <- 1`, Input: map[string]interface{}{"a": make(chan int32, 2)}},
   641  		{Script: `a <- 2`, Input: map[string]interface{}{"a": make(chan int64, 2)}},
   642  		{Script: `a <- 1.5`, Input: map[string]interface{}{"a": make(chan float32, 2)}},
   643  		{Script: `a <- 2.5`, Input: map[string]interface{}{"a": make(chan float64, 2)}},
   644  		{Script: `a <- "b"`, Input: map[string]interface{}{"a": make(chan string, 2)}},
   645  
   646  		{Script: `a = make(chan interface, 2); a <- nil`},
   647  		{Script: `a = make(chan bool, 2); a <- true`},
   648  		{Script: `a = make(chan int32, 2); a <- 1`},
   649  		{Script: `a = make(chan int64, 2); a <- 2`},
   650  		{Script: `a = make(chan float32, 2); a <- 1.5`},
   651  		{Script: `a = make(chan float64, 2); a <- 2.5`},
   652  		{Script: `a = make(chan string, 2); a <- "b"`},
   653  
   654  		// send to channel then receive from channel
   655  		{Script: `a <- nil; <- a`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}, RunOutput: nil},
   656  		{Script: `a <- true; <- a`, Input: map[string]interface{}{"a": make(chan bool, 2)}, RunOutput: true},
   657  		{Script: `a <- 1; <- a`, Input: map[string]interface{}{"a": make(chan int32, 2)}, RunOutput: int32(1)},
   658  		{Script: `a <- 2; <- a`, Input: map[string]interface{}{"a": make(chan int64, 2)}, RunOutput: int64(2)},
   659  		{Script: `a <- 1.5; <- a`, Input: map[string]interface{}{"a": make(chan float32, 2)}, RunOutput: float32(1.5)},
   660  		{Script: `a <- 2.5; <- a`, Input: map[string]interface{}{"a": make(chan float64, 2)}, RunOutput: float64(2.5)},
   661  		{Script: `a <- "b"; <- a`, Input: map[string]interface{}{"a": make(chan string, 2)}, RunOutput: "b"},
   662  
   663  		{Script: `a = make(chan interface, 2); a <- nil; <- a`, RunOutput: nil},
   664  		{Script: `a = make(chan bool, 2); a <- true; <- a`, RunOutput: true},
   665  		{Script: `a = make(chan int32, 2); a <- 1; <- a`, RunOutput: int32(1)},
   666  		{Script: `a = make(chan int64, 2); a <- 2; <- a`, RunOutput: int64(2)},
   667  		{Script: `a = make(chan float32, 2); a <- 1.5; <- a`, RunOutput: float32(1.5)},
   668  		{Script: `a = make(chan float64, 2); a <- 2.5; <- a`, RunOutput: float64(2.5)},
   669  		{Script: `a = make(chan string, 2); a <- "b"; <- a`, RunOutput: "b"},
   670  
   671  		// send to channel, receive from channel, then assign to variable
   672  		{Script: `a <- nil; b = <- a`, Input: map[string]interface{}{"a": make(chan interface{}, 2)}, RunOutput: nil, Output: map[string]interface{}{"b": nil}},
   673  		{Script: `a <- true; b = <- a`, Input: map[string]interface{}{"a": make(chan bool, 2)}, RunOutput: true, Output: map[string]interface{}{"b": true}},
   674  		{Script: `a <- 1; b = <- a`, Input: map[string]interface{}{"a": make(chan int32, 2)}, RunOutput: int32(1), Output: map[string]interface{}{"b": int32(1)}},
   675  		{Script: `a <- 2; b = <- a`, Input: map[string]interface{}{"a": make(chan int64, 2)}, RunOutput: int64(2), Output: map[string]interface{}{"b": int64(2)}},
   676  		{Script: `a <- 1.5; b = <- a`, Input: map[string]interface{}{"a": make(chan float32, 2)}, RunOutput: float32(1.5), Output: map[string]interface{}{"b": float32(1.5)}},
   677  		{Script: `a <- 2.5; b = <- a`, Input: map[string]interface{}{"a": make(chan float64, 2)}, RunOutput: float64(2.5), Output: map[string]interface{}{"b": float64(2.5)}},
   678  		{Script: `a <- "b"; b = <- a`, Input: map[string]interface{}{"a": make(chan string, 2)}, RunOutput: "b", Output: map[string]interface{}{"b": "b"}},
   679  
   680  		{Script: `a = make(chan interface, 2); a <- nil; b = <- a`, RunOutput: nil, Output: map[string]interface{}{"b": nil}},
   681  		{Script: `a = make(chan bool, 2); a <- true; b = <- a`, RunOutput: true, Output: map[string]interface{}{"b": true}},
   682  		{Script: `a = make(chan int32, 2); a <- 1; b = <- a`, RunOutput: int32(1), Output: map[string]interface{}{"b": int32(1)}},
   683  		{Script: `a = make(chan int64, 2); a <- 2; b = <- a`, RunOutput: int64(2), Output: map[string]interface{}{"b": int64(2)}},
   684  		{Script: `a = make(chan float32, 2); a <- 1.5; b = <- a`, RunOutput: float32(1.5), Output: map[string]interface{}{"b": float32(1.5)}},
   685  		{Script: `a = make(chan float64, 2); a <- 2.5; b = <- a`, RunOutput: float64(2.5), Output: map[string]interface{}{"b": float64(2.5)}},
   686  		{Script: `a = make(chan string, 2); a <- "b"; b = <- a`, RunOutput: "b", Output: map[string]interface{}{"b": "b"}},
   687  
   688  		// receive from closed channel
   689  		{Script: `a = make(chan int64, 2); a <- 1; close(a); <- a`, RunOutput: int64(1)},
   690  		{Script: `a = make(chan int64, 2); a <- 1; close(a); <- a; <- a`, RunOutput: nil},
   691  
   692  		// receive & send from same channel
   693  		{Script: `a = make(chan int64, 2); a <- 1; a <- <- a`, RunOutput: nil},
   694  		{Script: `a = make(chan int64, 2); a <- 1; a <- <- a; <- a`, RunOutput: int64(1)},
   695  		{Script: `a = make(chan int64, 2); a <- 1; a <- <- a; b = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}},
   696  		{Script: `a = make(chan int64, 2); a <- 1; a <- (<- a)`, RunOutput: nil},
   697  		{Script: `a = make(chan int64, 2); a <- 1; a <- (<- a); <- a`, RunOutput: int64(1)},
   698  		{Script: `a = make(chan int64, 2); a <- 1; a <- (<- a); b = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}},
   699  
   700  		// 1 then null into a
   701  		{Script: `a = make(chan int64, 2); a <- a <- 1`, RunOutput: nil},
   702  		{Script: `a = make(chan int64, 2); a <- a <- 1; <- a`, RunOutput: int64(1)},
   703  		{Script: `a = make(chan int64, 2); a <- a <- 1; <- a; <- a`, RunOutput: int64(0)},
   704  
   705  		// receive & send different channel
   706  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a`, RunOutput: nil},
   707  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a; <- b`, RunOutput: int64(1)},
   708  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- <- a; c = <- b`, RunOutput: int64(1), Output: map[string]interface{}{"c": int64(1)}},
   709  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a)`, RunOutput: nil},
   710  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a); <- b`, RunOutput: int64(1)},
   711  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); a <- 1; b <- (<- a); c = <- b`, RunOutput: int64(1), Output: map[string]interface{}{"c": int64(1)}},
   712  
   713  		// 1 into a then null into b
   714  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1`, RunOutput: nil},
   715  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1; <- a`, RunOutput: int64(1)},
   716  		{Script: `a = make(chan int64, 2); b = make(chan int64, 2); b <- a <- 1; <- a; <- b`, RunOutput: int64(0)},
   717  
   718  		// test ok
   719  		{Script: `a = make(chan int64, 2); a <- 1; b, ok = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1), "ok": true}},
   720  		{Script: `a = make(chan int64, 2); a <- 1; b, 1++ = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1)}},
   721  		{Script: `a = make(chan int64, 2); a <- 1; close(a); b, ok = <- a`, RunOutput: int64(1), Output: map[string]interface{}{"b": int64(1), "ok": true}},
   722  		{Script: `a = make(chan int64, 2); a <- 1; close(a); b = <- a; b, ok = <- a`, RunOutput: nil, Output: map[string]interface{}{"b": int64(1), "ok": false}},
   723  
   724  		// test let ++
   725  		{Script: `a = make(chan int64, 2); b = [1, 2, 3, 4]; c = 0; a <- 11; b[c++] = <- a; b[1]`, RunOutput: int64(11)},
   726  	}
   727  	runTests(t, tests, nil, &Options{Debug: true})
   728  }
   729  
   730  func TestVMDelete(t *testing.T) {
   731  	t.Parallel()
   732  
   733  	tests := []Test{
   734  		{Script: `delete(1++)`, RunError: fmt.Errorf("invalid operation")},
   735  		{Script: `delete(1)`, RunError: fmt.Errorf("first argument to delete cannot be type int64")},
   736  		{Script: `a = 1; delete("a"); a`, RunError: fmt.Errorf("undefined symbol 'a'")},
   737  		{Script: `a = {"b": "b"}; delete(a)`, RunError: fmt.Errorf("second argument to delete cannot be nil for map")},
   738  
   739  		{Script: `delete("a", 1++)`, RunError: fmt.Errorf("invalid operation")},
   740  		{Script: `b = []; delete(a, b)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, RunError: fmt.Errorf("cannot use type int32 as type []interface {} in delete"), Output: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}},
   741  
   742  		// test no variable
   743  		{Script: `delete("a")`},
   744  		{Script: `delete("a", false)`},
   745  		{Script: `delete("a", true)`},
   746  		{Script: `delete("a", nil)`},
   747  
   748  		// test DeleteGlobal
   749  		{Script: `a = 1; func b() { delete("a") }; b()`, Output: map[string]interface{}{"a": int64(1)}},
   750  		{Script: `a = 1; func b() { delete("a", false) }; b()`, Output: map[string]interface{}{"a": int64(1)}},
   751  		{Script: `a = 1; func b() { delete("a", true) }; b(); a`, RunError: fmt.Errorf("undefined symbol 'a'")},
   752  		{Script: `a = 2; func b() { a = 3; delete("a"); return a }; b()`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   753  		{Script: `a = 2; func b() { a = 3; delete("a", false); return a }; b()`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   754  		{Script: `a = 2; func b() { a = 3; delete("a", true); return a }; b()`, RunError: fmt.Errorf("undefined symbol 'a'")},
   755  		{Script: `a = 2; func b() { a = 3; delete("a") }; b(); a`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   756  		{Script: `a = 2; func b() { a = 3; delete("a", false) }; b(); a`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   757  		{Script: `a = 2; func b() { a = 3; delete("a", true) }; b(); a`, RunError: fmt.Errorf("undefined symbol 'a'")},
   758  
   759  		// test empty map
   760  		{Script: `delete(a, "a")`, Input: map[string]interface{}{"a": testMapEmpty}, Output: map[string]interface{}{"a": testMapEmpty}},
   761  
   762  		// test map
   763  		{Script: `a = {"b": "b"}; delete(a, "b")`, Output: map[string]interface{}{"a": map[interface{}]interface{}{}}},
   764  		{Script: `a = {"b": "b"}; delete(a, "b"); a.b`, Output: map[string]interface{}{"a": map[interface{}]interface{}{}}},
   765  		{Script: `a = {"b": "b", "c":"c"}; delete(a, "b")`, Output: map[string]interface{}{"a": map[interface{}]interface{}{"c": "c"}}},
   766  		{Script: `a = {"b": "b", "c":"c"}; delete(a, "b"); a.b`, Output: map[string]interface{}{"a": map[interface{}]interface{}{"c": "c"}}},
   767  
   768  		// test key convert
   769  		{Script: `delete(a, 2)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, Output: map[string]interface{}{"a": map[int32]interface{}{}}},
   770  		{Script: `delete(a, 2); a[2]`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2)}}, Output: map[string]interface{}{"a": map[int32]interface{}{}}},
   771  		{Script: `delete(a, 2)`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2), 3: int32(3)}}, Output: map[string]interface{}{"a": map[int32]interface{}{3: int32(3)}}},
   772  		{Script: `delete(a, 2); a[2]`, Input: map[string]interface{}{"a": map[int32]interface{}{2: int32(2), 3: int32(3)}}, Output: map[string]interface{}{"a": map[int32]interface{}{3: int32(3)}}},
   773  	}
   774  	runTests(t, tests, nil, &Options{Debug: true})
   775  }
   776  
   777  func TestComment(t *testing.T) {
   778  	t.Parallel()
   779  
   780  	tests := []Test{
   781  		{Script: `# 1`},
   782  		{Script: `# 1;`},
   783  		{Script: `# 1 // 2`},
   784  		{Script: `# 1 \n 2`},
   785  		{Script: `# 1 # 2`},
   786  
   787  		{Script: `1# 1`, RunOutput: int64(1)},
   788  		{Script: `1# 1;`, RunOutput: int64(1)},
   789  		{Script: `1# 1 // 2`, RunOutput: int64(1)},
   790  		{Script: `1# 1 \n 2`, RunOutput: int64(1)},
   791  		{Script: `1# 1 # 2`, RunOutput: int64(1)},
   792  
   793  		{Script: `1
   794  # 1`, RunOutput: int64(1)},
   795  		{Script: `1
   796  # 1;`, RunOutput: int64(1)},
   797  		{Script: `1
   798  # 1 // 2`, RunOutput: int64(1)},
   799  		{Script: `1
   800  # 1 \n 2`, RunOutput: int64(1)},
   801  		{Script: `1
   802  # 1 # 2`, RunOutput: int64(1)},
   803  
   804  		{Script: `// 1`},
   805  		{Script: `// 1;`},
   806  		{Script: `// 1 // 2`},
   807  		{Script: `// 1 \n 2`},
   808  		{Script: `// 1 # 2`},
   809  
   810  		{Script: `1// 1`, RunOutput: int64(1)},
   811  		{Script: `1// 1;`, RunOutput: int64(1)},
   812  		{Script: `1// 1 // 2`, RunOutput: int64(1)},
   813  		{Script: `1// 1 \n 2`, RunOutput: int64(1)},
   814  		{Script: `1// 1 # 2`, RunOutput: int64(1)},
   815  
   816  		{Script: `1
   817  // 1`, RunOutput: int64(1)},
   818  		{Script: `1
   819  // 1;`, RunOutput: int64(1)},
   820  		{Script: `1
   821  // 1 // 2`, RunOutput: int64(1)},
   822  		{Script: `1
   823  // 1 \n 2`, RunOutput: int64(1)},
   824  		{Script: `1
   825  // 1 # 2`, RunOutput: int64(1)},
   826  
   827  		{Script: `/* 1 */`},
   828  		{Script: `/* * 1 */`},
   829  		{Script: `/* 1 * */`},
   830  		{Script: `/** 1 */`},
   831  		{Script: `/*** 1 */`},
   832  		{Script: `/**** 1 */`},
   833  		{Script: `/* 1 **/`},
   834  		{Script: `/* 1 ***/`},
   835  		{Script: `/* 1 ****/`},
   836  		{Script: `/** 1 ****/`},
   837  		{Script: `/*** 1 ****/`},
   838  		{Script: `/**** 1 ****/`},
   839  
   840  		{Script: `1/* 1 */`, RunOutput: int64(1)},
   841  		{Script: `1/* * 1 */`, RunOutput: int64(1)},
   842  		{Script: `1/* 1 * */`, RunOutput: int64(1)},
   843  		{Script: `1/** 1 */`, RunOutput: int64(1)},
   844  		{Script: `1/*** 1 */`, RunOutput: int64(1)},
   845  		{Script: `1/**** 1 */`, RunOutput: int64(1)},
   846  		{Script: `1/* 1 **/`, RunOutput: int64(1)},
   847  		{Script: `1/* 1 ***/`, RunOutput: int64(1)},
   848  		{Script: `1/* 1 ****/`, RunOutput: int64(1)},
   849  		{Script: `1/** 1 ****/`, RunOutput: int64(1)},
   850  		{Script: `1/*** 1 ****/`, RunOutput: int64(1)},
   851  		{Script: `1/**** 1 ****/`, RunOutput: int64(1)},
   852  
   853  		{Script: `/* 1 */1`, RunOutput: int64(1)},
   854  		{Script: `/* * 1 */1`, RunOutput: int64(1)},
   855  		{Script: `/* 1 * */1`, RunOutput: int64(1)},
   856  		{Script: `/** 1 */1`, RunOutput: int64(1)},
   857  		{Script: `/*** 1 */1`, RunOutput: int64(1)},
   858  		{Script: `/**** 1 */1`, RunOutput: int64(1)},
   859  		{Script: `/* 1 **/1`, RunOutput: int64(1)},
   860  		{Script: `/* 1 ***/1`, RunOutput: int64(1)},
   861  		{Script: `/* 1 ****/1`, RunOutput: int64(1)},
   862  		{Script: `/** 1 ****/1`, RunOutput: int64(1)},
   863  		{Script: `/*** 1 ****/1`, RunOutput: int64(1)},
   864  		{Script: `/**** 1 ****/1`, RunOutput: int64(1)},
   865  
   866  		{Script: `1
   867  /* 1 */`, RunOutput: int64(1)},
   868  		{Script: `1
   869  /* * 1 */`, RunOutput: int64(1)},
   870  		{Script: `1
   871  /* 1 * */`, RunOutput: int64(1)},
   872  		{Script: `1
   873  /** 1 */`, RunOutput: int64(1)},
   874  		{Script: `1
   875  /*** 1 */`, RunOutput: int64(1)},
   876  		{Script: `1
   877  /**** 1 */`, RunOutput: int64(1)},
   878  		{Script: `1
   879  /* 1 **/`, RunOutput: int64(1)},
   880  		{Script: `1
   881  /* 1 ***/`, RunOutput: int64(1)},
   882  		{Script: `1
   883  /* 1 ****/`, RunOutput: int64(1)},
   884  		{Script: `1
   885  /** 1 ****/`, RunOutput: int64(1)},
   886  		{Script: `1
   887  /*** 1 ****/`, RunOutput: int64(1)},
   888  		{Script: `1
   889  /**** 1 ****/`, RunOutput: int64(1)},
   890  	}
   891  	runTests(t, tests, nil, &Options{Debug: true})
   892  }
   893  
   894  func TestCancelWithContext(t *testing.T) {
   895  	scripts := []string{
   896  		`
   897  b = 0
   898  close(waitChan)
   899  for {
   900  	b = 1
   901  }
   902  `,
   903  		`
   904  b = 0
   905  close(waitChan)
   906  for {
   907  	for {
   908  		b = 1
   909  	}
   910  }
   911  `,
   912  		`
   913  a = []
   914  for i = 0; i < 20000; i++ {
   915  	a += 1
   916  }
   917  b = 0
   918  close(waitChan)
   919  for {
   920  	for i in a {
   921  		b = i
   922  	}
   923  }
   924  `,
   925  		`
   926  a = []
   927  for i = 0; i < 20000; i++ {
   928  	a += 1
   929  }
   930  b = 0
   931  close(waitChan)
   932  for i in a {
   933  	for j in a {
   934  		b = j
   935  	}
   936  }
   937  `,
   938  		`
   939  close(waitChan)
   940  b = 0
   941  for i = 0; true; nil {
   942  }
   943  `,
   944  		`
   945  b = 0
   946  close(waitChan)
   947  for i = 0; true; nil {
   948  	for j = 0; true; nil {
   949  		b = 1
   950  	}
   951  }
   952  `,
   953  		`
   954  a = {}
   955  for i = 0; i < 20000; i++ {
   956  	a[toString(i)] = 1
   957  }
   958  b = 0
   959  close(waitChan)
   960  for {
   961  	for i in a {
   962  		b = 1
   963  	}
   964  }
   965  `,
   966  		`
   967  a = {}
   968  for i = 0; i < 20000; i++ {
   969  	a[toString(i)] = 1
   970  }
   971  b = 0
   972  close(waitChan)
   973  for i in a {
   974  	for j in a {
   975  		b = 1
   976  	}
   977  }
   978  `,
   979  		`
   980  close(waitChan)
   981  <- make(chan string)
   982  `,
   983  		`
   984  a = ""
   985  close(waitChan)
   986  a = <- make(chan string)
   987  `,
   988  		`
   989  for {
   990  	a = ""
   991  	close(waitChan)
   992  	a = <- make(chan string)
   993  }
   994  `,
   995  		`
   996  a = make(chan int)
   997  close(waitChan)
   998  a <- 1
   999  `,
  1000  		`
  1001  a = make(chan interface)
  1002  close(waitChan)
  1003  a <- nil
  1004  `,
  1005  		`
  1006  a = make(chan int64, 1)
  1007  close(waitChan)
  1008  for v in a { }
  1009  `,
  1010  		`
  1011  close(waitChan)
  1012  try {
  1013  	for { }
  1014  } catch { }
  1015  `,
  1016  	}
  1017  	for _, script := range scripts {
  1018  		runCancelTestWithContext(t, script)
  1019  	}
  1020  }
  1021  
  1022  func runCancelTestWithContext(t *testing.T, script string) {
  1023  	waitChan := make(chan struct{}, 1)
  1024  	toString := func(value interface{}) string {
  1025  		return fmt.Sprintf("%v", value)
  1026  	}
  1027  	e := env.NewEnv()
  1028  	err := e.Define("waitChan", waitChan)
  1029  	if err != nil {
  1030  		t.Errorf("Define error: %v", err)
  1031  	}
  1032  	err = e.Define("toString", toString)
  1033  	if err != nil {
  1034  		t.Errorf("Define error: %v", err)
  1035  	}
  1036  
  1037  	ctx, cancel := context.WithCancel(context.Background())
  1038  	go func() {
  1039  		<-waitChan
  1040  		time.Sleep(time.Millisecond)
  1041  		cancel()
  1042  	}()
  1043  
  1044  	_, err = ExecuteContext(ctx, e, nil, script)
  1045  	if err == nil || err.Error() != ErrInterrupt.Error() {
  1046  		t.Errorf("execute error - received %#v - expected: %#v - script: %v", err, ErrInterrupt, script)
  1047  	}
  1048  }
  1049  
  1050  func TestContextConcurrency(t *testing.T) {
  1051  	var waitGroup sync.WaitGroup
  1052  	e := env.NewEnv()
  1053  
  1054  	ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
  1055  	waitGroup.Add(100)
  1056  	for i := 0; i < 100; i++ {
  1057  		go func() {
  1058  			_, err := ExecuteContext(ctx, e, nil, "for { }")
  1059  			if err == nil || err.Error() != ErrInterrupt.Error() {
  1060  				t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt)
  1061  			}
  1062  			waitGroup.Done()
  1063  		}()
  1064  	}
  1065  	cancel()
  1066  	waitGroup.Wait()
  1067  	cancel()
  1068  
  1069  	_, err := ExecuteContext(ctx, e, nil, "for { }")
  1070  	if err == nil || err.Error() != ErrInterrupt.Error() {
  1071  		t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt)
  1072  	}
  1073  
  1074  	ctx, cancel = context.WithCancel(context.Background())
  1075  	_, err = ExecuteContext(ctx, e, nil, "for i = 0; i < 1000; i++ {}")
  1076  	if err != nil {
  1077  		t.Errorf("execute error - received: %v - expected: %v", err, nil)
  1078  	}
  1079  	waitGroup.Add(100)
  1080  	for i := 0; i < 100; i++ {
  1081  		go func() {
  1082  			_, err := ExecuteContext(ctx, e, nil, "for i = 0; i < 1000; i++ { }")
  1083  			if err != nil {
  1084  				t.Errorf("execute error - received: %v - expected: %v", err, nil)
  1085  			}
  1086  			waitGroup.Done()
  1087  		}()
  1088  	}
  1089  	waitGroup.Wait()
  1090  
  1091  	waitGroup.Add(100)
  1092  	for i := 0; i < 100; i++ {
  1093  		go func() {
  1094  			_, err := ExecuteContext(ctx, e, nil, "for { }")
  1095  			if err == nil || err.Error() != ErrInterrupt.Error() {
  1096  				t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt)
  1097  			}
  1098  			waitGroup.Done()
  1099  		}()
  1100  	}
  1101  	time.Sleep(time.Millisecond)
  1102  	cancel()
  1103  	waitGroup.Wait()
  1104  
  1105  	waitGroup.Add(100)
  1106  	for i := 0; i < 100; i++ {
  1107  		go func() {
  1108  			_, err := Execute(e, nil, "for i = 0; i < 1000; i++ { }")
  1109  			if err != nil {
  1110  				t.Errorf("execute error - received: %v - expected: %v", err, nil)
  1111  			}
  1112  			waitGroup.Done()
  1113  		}()
  1114  	}
  1115  	waitGroup.Wait()
  1116  }
  1117  
  1118  func TestContextFunction(t *testing.T) {
  1119  	t.Parallel()
  1120  
  1121  	e := env.NewEnv()
  1122  	script := `
  1123  		func myFunc(myVar) {
  1124  			myVar = 3
  1125  		}`
  1126  	envModule, err := e.NewModule("a")
  1127  	if err != nil {
  1128  		t.Fatal("NewModule error:", err)
  1129  	}
  1130  
  1131  	ctx, cancel := context.WithCancel(context.Background())
  1132  	_, err = ExecuteContext(ctx, envModule, nil, script)
  1133  	if err != nil {
  1134  		t.Errorf("execute error - received %#v - expected: %#v", err, nil)
  1135  	}
  1136  	cancel()
  1137  
  1138  	script = "a.myFunc(2)"
  1139  
  1140  	ctx, cancel = context.WithCancel(context.Background())
  1141  	_, err = ExecuteContext(ctx, e, nil, script)
  1142  	if err != nil {
  1143  		t.Errorf("execute error - received %#v - expected: %#v", err, nil)
  1144  	}
  1145  	cancel()
  1146  }
  1147  
  1148  func TestAssignToInterface(t *testing.T) {
  1149  	t.Parallel()
  1150  
  1151  	e := env.NewEnv()
  1152  	X := new(struct {
  1153  		Stdout io.Writer
  1154  	})
  1155  	err := e.Define("X", X)
  1156  	if err != nil {
  1157  		t.Errorf("Define error: %v", err)
  1158  	}
  1159  	err = e.Define("a", new(os.File))
  1160  	if err != nil {
  1161  		t.Errorf("Define error: %v", err)
  1162  	}
  1163  	_, err = Execute(e, nil, "X.Stdout = a")
  1164  	if err != nil {
  1165  		t.Errorf("execute error - received %#v - expected: %#v", err, ErrInterrupt)
  1166  	}
  1167  }
  1168  
  1169  // TestValueEqual do some basic ValueEqual tests for coverage
  1170  func TestValueEqual(t *testing.T) {
  1171  	t.Parallel()
  1172  
  1173  	result := valueEqual(true, true)
  1174  	if result != true {
  1175  		t.Fatal("ValueEqual")
  1176  	}
  1177  	result = valueEqual(true, false)
  1178  	if result != false {
  1179  		t.Fatal("ValueEqual")
  1180  	}
  1181  	result = valueEqual(false, true)
  1182  	if result != false {
  1183  		t.Fatal("ValueEqual")
  1184  	}
  1185  }
  1186  
  1187  // TestUnknownCases tests switch cases that are the unknown cases
  1188  func TestUnknownCases(t *testing.T) {
  1189  	t.Parallel()
  1190  
  1191  	oneLiteral := &ast.LiteralExpr{Literal: reflect.ValueOf(int64(1))}
  1192  	type (
  1193  		BadStmt struct {
  1194  			ast.StmtImpl
  1195  		}
  1196  		BadExpr struct {
  1197  			ast.ExprImpl
  1198  		}
  1199  		BadOperator struct {
  1200  			ast.OperatorImpl
  1201  		}
  1202  	)
  1203  
  1204  	stmts := []ast.Stmt{
  1205  		&BadStmt{},
  1206  		&ast.ExprStmt{Expr: &BadExpr{}},
  1207  		&ast.ExprStmt{Expr: &ast.OpExpr{Op: &BadOperator{}}},
  1208  		&ast.ExprStmt{Expr: &ast.UnaryExpr{Expr: oneLiteral}},
  1209  		&ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.BinaryOperator{LHS: oneLiteral}}},
  1210  		&ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.ComparisonOperator{LHS: oneLiteral, RHS: oneLiteral}}},
  1211  		&ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.AddOperator{LHS: oneLiteral, RHS: oneLiteral}}},
  1212  		&ast.ExprStmt{Expr: &ast.OpExpr{Op: &ast.MultiplyOperator{LHS: oneLiteral, RHS: oneLiteral}}},
  1213  	}
  1214  
  1215  	for _, stmt := range stmts {
  1216  		e := env.NewEnv()
  1217  		_, err := Run(e, nil, stmt)
  1218  		if err == nil {
  1219  			t.Errorf("no error - stmt: %#v", stmt)
  1220  		} else if len(err.Error()) < 9 || err.Error()[:8] != "unknown " {
  1221  			t.Errorf("err: %v - stmt: %#v", err, stmt)
  1222  		}
  1223  	}
  1224  }
  1225  
  1226  type Foo struct {
  1227  	Value int
  1228  }
  1229  type Bar struct {
  1230  	Foo
  1231  	Ref *int
  1232  }
  1233  
  1234  func (f Foo) ValueReceiver() int {
  1235  	return f.Value
  1236  }
  1237  func (b *Bar) PointerReceiver() (int, int) {
  1238  	b.Value = 0
  1239  	*b.Ref = 0
  1240  	return b.Value, *b.Ref
  1241  }
  1242  
  1243  func TestCallStructMethod(t *testing.T) {
  1244  	t.Parallel()
  1245  
  1246  	ref := 10
  1247  	ptr := &Bar{
  1248  		Foo: Foo{
  1249  			Value: 100,
  1250  		},
  1251  		Ref: &ref,
  1252  	}
  1253  	val := Bar{
  1254  		Foo: Foo{
  1255  			Value: 200,
  1256  		},
  1257  		Ref: &ref,
  1258  	}
  1259  
  1260  	// execution in native go
  1261  	v := ptr.ValueReceiver()
  1262  	if v != 100 {
  1263  		t.Fatal("ptr: call value receiver failed, v should equal to 100")
  1264  	}
  1265  	v, r := ptr.PointerReceiver()
  1266  	if v != 0 || r != 0 {
  1267  		t.Fatal("ptr: call pointer receiver failed, both should be 0")
  1268  	}
  1269  
  1270  	ref = 10
  1271  	v = val.ValueReceiver()
  1272  	if v != 200 {
  1273  		t.Fatal("val: call value receiver failed, v should equal to 200")
  1274  	}
  1275  	v, r = val.PointerReceiver()
  1276  	if v != 0 || r != 0 {
  1277  		t.Fatal("val: call pointer receiver failed, both should be 0")
  1278  	}
  1279  
  1280  	// reinitialize values before executing script in VM
  1281  	ptr.Value = 100
  1282  	val.Value = 200
  1283  
  1284  	// Define pointer 'ptr' to struct Bar in VM
  1285  	ref = 10
  1286  	tests := []Test{
  1287  		{Script: "ptr.ValueReceiver()", Input: map[string]interface{}{"ptr": ptr}, RunOutput: 100},
  1288  		{Script: "ptr.PointerReceiver()", Input: map[string]interface{}{"ptr": ptr}, RunOutput: []interface{}{0, 0}},
  1289  	}
  1290  	runTests(t, tests, nil, &Options{Debug: true})
  1291  
  1292  	// Define value 'val' to struct Bar in VM
  1293  	ref = 10
  1294  	tests = []Test{
  1295  		{Script: "val.ValueReceiver()", Input: map[string]interface{}{"val": val}, RunOutput: 200},
  1296  		{Script: "val.PointerReceiver()", Input: map[string]interface{}{"val": val}, RunOutput: []interface{}{0, 0}},
  1297  	}
  1298  	runTests(t, tests, nil, &Options{Debug: true})
  1299  }
  1300  
  1301  func fib(x int) int {
  1302  	if x < 2 {
  1303  		return x
  1304  	}
  1305  	return fib(x-1) + fib(x-2)
  1306  }
  1307  
  1308  func BenchmarkFibGo(b *testing.B) {
  1309  	for i := 0; i < b.N; i++ {
  1310  		fib(29)
  1311  	}
  1312  }
  1313  
  1314  func BenchmarkFibVM(b *testing.B) {
  1315  	b.StopTimer()
  1316  
  1317  	e := env.NewEnv()
  1318  	a, err := e.NewModule("a")
  1319  	if err != nil {
  1320  		b.Fatal("NewModule error:", err)
  1321  	}
  1322  
  1323  	script := `
  1324  fib = func(x) {
  1325  	if x < 2 {
  1326  		return x
  1327  	}
  1328  	return fib(x-1) + fib(x-2)
  1329  }`
  1330  
  1331  	_, err = Execute(a, nil, script)
  1332  	if err != nil {
  1333  		b.Fatal("Execute error:", err)
  1334  	}
  1335  
  1336  	b.ResetTimer()
  1337  	b.StartTimer()
  1338  
  1339  	for i := 0; i < b.N; i++ {
  1340  		_, err = Execute(e, nil, "a.fib(29)")
  1341  		if err != nil {
  1342  			b.Fatal("Execute error:", err)
  1343  		}
  1344  	}
  1345  }
  1346  
  1347  func TestLetsStatementPosition(t *testing.T) {
  1348  	src := `a, b = 1, 2
  1349  `
  1350  	stmts, err := parser.ParseSrc(src)
  1351  	if err != nil {
  1352  		t.Fatal(err)
  1353  	}
  1354  
  1355  	var stmtFound bool
  1356  	err = astutil.Walk(stmts, func(e interface{}) error {
  1357  		switch e := e.(type) {
  1358  		case *ast.LetsStmt:
  1359  			if len(e.LHSS) == 2 {
  1360  				if is, want := e.Position().Line, 1; is != want {
  1361  					t.Fatalf("%v != %v", is, want)
  1362  				}
  1363  				if is, want := e.Position().Column, 1; is != want {
  1364  					t.Fatalf("%v != %v", is, want)
  1365  				}
  1366  			}
  1367  			stmtFound = true
  1368  		}
  1369  
  1370  		return nil
  1371  	})
  1372  
  1373  	if err != nil {
  1374  		t.Fatal(err)
  1375  	}
  1376  
  1377  	if is, want := stmtFound, true; is != want {
  1378  		t.Fatalf("%v != %v", is, want)
  1379  	}
  1380  }