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

     1  package vm
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  )
     8  
     9  func TestBasicOperators(t *testing.T) {
    10  	t.Parallel()
    11  
    12  	tests := []Test{
    13  		{Script: `]`, ParseError: fmt.Errorf("syntax error")},
    14  
    15  		{Script: `2 + 1`, RunOutput: int64(3)},
    16  		{Script: `2 - 1`, RunOutput: int64(1)},
    17  		{Script: `2 * 1`, RunOutput: int64(2)},
    18  		{Script: `2 / 1`, RunOutput: float64(2)},
    19  		{Script: `2.1 + 1.1`, RunOutput: float64(3.2)},
    20  		{Script: `2.1 - 1.1`, RunOutput: float64(1)},
    21  		{Script: `2 + 1.1`, RunOutput: float64(3.1)},
    22  		{Script: `2.1 + 1`, RunOutput: float64(3.1)},
    23  		{Script: `3 - 1.5`, RunOutput: float64(1.5)},
    24  		{Script: `2.1 - 1`, RunOutput: float64(1.1)},
    25  		{Script: `2.1 * 2.0`, RunOutput: float64(4.2)},
    26  		{Script: `6.5 / 2.0`, RunOutput: float64(3.25)},
    27  
    28  		{Script: `2-1`, RunOutput: int64(1)},
    29  		{Script: `2 -1`, RunOutput: int64(1)},
    30  		{Script: `2- 1`, RunOutput: int64(1)},
    31  		{Script: `2 - -1`, RunOutput: int64(3)},
    32  		{Script: `2- -1`, RunOutput: int64(3)},
    33  		{Script: `2 - - 1`, RunOutput: int64(3)},
    34  		{Script: `2- - 1`, RunOutput: int64(3)},
    35  
    36  		{Script: `a + b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(3)},
    37  		{Script: `a - b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(1)},
    38  		{Script: `a * b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(2)},
    39  		{Script: `a / b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: float64(2)},
    40  		{Script: `a + b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(1.1)}, RunOutput: float64(3.2)},
    41  		{Script: `a - b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(1.1)}, RunOutput: float64(1)},
    42  		{Script: `a * b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(2)}, RunOutput: float64(4.2)},
    43  		{Script: `a / b`, Input: map[string]interface{}{"a": float64(6.5), "b": float64(2)}, RunOutput: float64(3.25)},
    44  
    45  		{Script: `a + b`, Input: map[string]interface{}{"a": "a", "b": "b"}, RunOutput: "ab"},
    46  		{Script: `a + b`, Input: map[string]interface{}{"a": "a", "b": int64(1)}, RunOutput: "a1"},
    47  		{Script: `a + b`, Input: map[string]interface{}{"a": "a", "b": float64(1.1)}, RunOutput: "a1.1"},
    48  		{Script: `a + b`, Input: map[string]interface{}{"a": int64(2), "b": "b"}, RunOutput: "2b"},
    49  		{Script: `a + b`, Input: map[string]interface{}{"a": float64(2.5), "b": "b"}, RunOutput: "2.5b"},
    50  
    51  		{Script: `a + z`, Input: map[string]interface{}{"a": "a"}, RunError: fmt.Errorf("undefined symbol 'z'"), RunOutput: nil},
    52  		{Script: `z + b`, Input: map[string]interface{}{"a": "a"}, RunError: fmt.Errorf("undefined symbol 'z'"), RunOutput: nil},
    53  
    54  		{Script: `c = a + b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(3), Output: map[string]interface{}{"c": int64(3)}},
    55  		{Script: `c = a - b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"c": int64(1)}},
    56  		{Script: `c = a * b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"c": int64(2)}},
    57  		{Script: `c = a / b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: float64(2), Output: map[string]interface{}{"c": float64(2)}},
    58  		{Script: `c = a + b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(1.1)}, RunOutput: float64(3.2), Output: map[string]interface{}{"c": float64(3.2)}},
    59  		{Script: `c = a - b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(1.1)}, RunOutput: float64(1), Output: map[string]interface{}{"c": float64(1)}},
    60  		{Script: `c = a * b`, Input: map[string]interface{}{"a": float64(2.1), "b": float64(2)}, RunOutput: float64(4.2), Output: map[string]interface{}{"c": float64(4.2)}},
    61  		{Script: `c = a / b`, Input: map[string]interface{}{"a": float64(6.5), "b": float64(2)}, RunOutput: float64(3.25), Output: map[string]interface{}{"c": float64(3.25)}},
    62  
    63  		{Script: `a = nil; a++`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    64  		{Script: `a = false; a++`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    65  		{Script: `a = true; a++`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
    66  		{Script: `a = 1; a++`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
    67  		{Script: `a = 1.5; a++`, RunOutput: float64(2.5), Output: map[string]interface{}{"a": float64(2.5)}},
    68  		{Script: `a = "1"; a++`, RunOutput: "11", Output: map[string]interface{}{"a": "11"}},
    69  		{Script: `a = "a"; a++`, RunOutput: "a1", Output: map[string]interface{}{"a": "a1"}},
    70  
    71  		{Script: `a = nil; a--`, RunOutput: int64(-1), Output: map[string]interface{}{"a": int64(-1)}},
    72  		{Script: `a = false; a--`, RunOutput: int64(-1), Output: map[string]interface{}{"a": int64(-1)}},
    73  		{Script: `a = true; a--`, RunOutput: int64(0), Output: map[string]interface{}{"a": int64(0)}},
    74  		{Script: `a = 2; a--`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    75  		{Script: `a = 2.5; a--`, RunOutput: float64(1.5), Output: map[string]interface{}{"a": float64(1.5)}},
    76  
    77  		{Script: `a++`, Input: map[string]interface{}{"a": nil}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    78  		{Script: `a++`, Input: map[string]interface{}{"a": false}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    79  		{Script: `a++`, Input: map[string]interface{}{"a": true}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
    80  		{Script: `a++`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
    81  		{Script: `a++`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
    82  		{Script: `a++`, Input: map[string]interface{}{"a": float32(3.5)}, RunOutput: float64(4.5), Output: map[string]interface{}{"a": float64(4.5)}},
    83  		{Script: `a++`, Input: map[string]interface{}{"a": float64(4.5)}, RunOutput: float64(5.5), Output: map[string]interface{}{"a": float64(5.5)}},
    84  		{Script: `a++`, Input: map[string]interface{}{"a": "2"}, RunOutput: "21", Output: map[string]interface{}{"a": "21"}},
    85  		{Script: `a++`, Input: map[string]interface{}{"a": "a"}, RunOutput: "a1", Output: map[string]interface{}{"a": "a1"}},
    86  
    87  		{Script: `a--`, Input: map[string]interface{}{"a": nil}, RunOutput: int64(-1), Output: map[string]interface{}{"a": int64(-1)}},
    88  		{Script: `a--`, Input: map[string]interface{}{"a": false}, RunOutput: int64(-1), Output: map[string]interface{}{"a": int64(-1)}},
    89  		{Script: `a--`, Input: map[string]interface{}{"a": true}, RunOutput: int64(0), Output: map[string]interface{}{"a": int64(0)}},
    90  		{Script: `a--`, Input: map[string]interface{}{"a": int32(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    91  		{Script: `a--`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    92  		{Script: `a--`, Input: map[string]interface{}{"a": float32(2.5)}, RunOutput: float64(1.5), Output: map[string]interface{}{"a": float64(1.5)}},
    93  		{Script: `a--`, Input: map[string]interface{}{"a": float64(2.5)}, RunOutput: float64(1.5), Output: map[string]interface{}{"a": float64(1.5)}},
    94  		{Script: `a--`, Input: map[string]interface{}{"a": "2"}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
    95  		{Script: `a--`, Input: map[string]interface{}{"a": "a"}, RunOutput: int64(-1), Output: map[string]interface{}{"a": int64(-1)}},
    96  
    97  		{Script: `1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
    98  		{Script: `1--`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
    99  		{Script: `z++`, RunError: fmt.Errorf("undefined symbol 'z'"), RunOutput: nil},
   100  		{Script: `z--`, RunError: fmt.Errorf("undefined symbol 'z'"), RunOutput: nil},
   101  		{Script: `!(1++)`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   102  		{Script: `1 + 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   103  		{Script: `1 - 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   104  		{Script: `1 * 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   105  		{Script: `1 / 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   106  		{Script: `1++ + 1`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   107  		{Script: `1++ - 1`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   108  		{Script: `1++ * 1`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   109  		{Script: `1++ / 1`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   110  
   111  		{Script: `a = 1; b = 2; a + b`, RunOutput: int64(3)},
   112  		{Script: `a = [1]; b = 2; a[0] + b`, RunOutput: int64(3)},
   113  		{Script: `a = 1; b = [2]; a + b[0]`, RunOutput: int64(3)},
   114  		{Script: `a = 2; b = 1; a - b`, RunOutput: int64(1)},
   115  		{Script: `a = [2]; b = 1; a[0] - b`, RunOutput: int64(1)},
   116  		{Script: `a = 2; b = [1]; a - b[0]`, RunOutput: int64(1)},
   117  		{Script: `a = 1; b = 2; a * b`, RunOutput: int64(2)},
   118  		{Script: `a = [1]; b = 2; a[0] * b`, RunOutput: int64(2)},
   119  		{Script: `a = 1; b = [2]; a * b[0]`, RunOutput: int64(2)},
   120  		{Script: `a = 4; b = 2; a / b`, RunOutput: float64(2)},
   121  		{Script: `a = [4]; b = 2; a[0] / b`, RunOutput: float64(2)},
   122  		{Script: `a = 4; b = [2]; a / b[0]`, RunOutput: float64(2)},
   123  
   124  		{Script: `a += 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   125  		{Script: `a -= 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   126  		{Script: `a *= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(4)}},
   127  		{Script: `a /= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: float64(1), Output: map[string]interface{}{"a": float64(1)}},
   128  		{Script: `a += 1`, Input: map[string]interface{}{"a": 2.1}, RunOutput: float64(3.1), Output: map[string]interface{}{"a": float64(3.1)}},
   129  		{Script: `a -= 1`, Input: map[string]interface{}{"a": 2.1}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}},
   130  		{Script: `a *= 2`, Input: map[string]interface{}{"a": 2.1}, RunOutput: float64(4.2), Output: map[string]interface{}{"a": float64(4.2)}},
   131  		{Script: `a /= 2`, Input: map[string]interface{}{"a": 6.5}, RunOutput: float64(3.25), Output: map[string]interface{}{"a": float64(3.25)}},
   132  
   133  		{Script: `a &= 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(0), Output: map[string]interface{}{"a": int64(0)}},
   134  		{Script: `a &= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   135  		{Script: `a &= 1`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(0), Output: map[string]interface{}{"a": int64(0)}},
   136  		{Script: `a &= 2`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   137  
   138  		{Script: `a |= 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   139  		{Script: `a |= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   140  		{Script: `a |= 1`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   141  		{Script: `a |= 2`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   142  
   143  		{Script: `a << 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(8), Output: map[string]interface{}{"a": int64(2)}},
   144  		{Script: `a >> 2`, Input: map[string]interface{}{"a": int64(8)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(8)}},
   145  		{Script: `a << 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: int64(8), Output: map[string]interface{}{"a": float64(2)}},
   146  		{Script: `a >> 2`, Input: map[string]interface{}{"a": float64(8)}, RunOutput: int64(2), Output: map[string]interface{}{"a": float64(8)}},
   147  
   148  		{Script: `a % 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(0), Output: map[string]interface{}{"a": int64(2)}},
   149  		{Script: `a % 3`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   150  		{Script: `a % 2`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(0), Output: map[string]interface{}{"a": float64(2.1)}},
   151  		{Script: `a % 3`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": float64(2.1)}},
   152  
   153  		{Script: `a * 4`, Input: map[string]interface{}{"a": "a"}, RunOutput: "aaaa", Output: map[string]interface{}{"a": "a"}},
   154  		{Script: `a * 4.0`, Input: map[string]interface{}{"a": "a"}, RunOutput: float64(0), Output: map[string]interface{}{"a": "a"}},
   155  
   156  		{Script: `-a`, Input: map[string]interface{}{"a": nil}, RunOutput: float64(-0), Output: map[string]interface{}{"a": nil}},
   157  		{Script: `-a`, Input: map[string]interface{}{"a": int32(1)}, RunOutput: int64(-1), Output: map[string]interface{}{"a": int32(1)}},
   158  		{Script: `-a`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(-2), Output: map[string]interface{}{"a": int64(2)}},
   159  		{Script: `-a`, Input: map[string]interface{}{"a": float32(3.5)}, RunOutput: float64(-3.5), Output: map[string]interface{}{"a": float32(3.5)}},
   160  		{Script: `-a`, Input: map[string]interface{}{"a": float64(4.5)}, RunOutput: float64(-4.5), Output: map[string]interface{}{"a": float64(4.5)}},
   161  		{Script: `-a`, Input: map[string]interface{}{"a": "a"}, RunOutput: float64(-0), Output: map[string]interface{}{"a": "a"}},
   162  		{Script: `-a`, Input: map[string]interface{}{"a": "1"}, RunOutput: float64(-1), Output: map[string]interface{}{"a": "1"}},
   163  
   164  		{Script: `^a`, Input: map[string]interface{}{"a": nil}, RunOutput: int64(-1), Output: map[string]interface{}{"a": nil}},
   165  		{Script: `^a`, Input: map[string]interface{}{"a": "a"}, RunOutput: int64(-1), Output: map[string]interface{}{"a": "a"}},
   166  		{Script: `^a`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(-3), Output: map[string]interface{}{"a": int64(2)}},
   167  		{Script: `^a`, Input: map[string]interface{}{"a": float64(2.1)}, RunOutput: int64(-3), Output: map[string]interface{}{"a": float64(2.1)}},
   168  
   169  		{Script: `!true`, RunOutput: false},
   170  		{Script: `!false`, RunOutput: true},
   171  		{Script: `!1`, RunOutput: false},
   172  	}
   173  	runTests(t, tests, nil, &Options{Debug: true})
   174  }
   175  
   176  func TestComparisonOperators(t *testing.T) {
   177  	t.Parallel()
   178  
   179  	tests := []Test{
   180  		{Script: `1++ == 2`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   181  		{Script: `2 == 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   182  		{Script: `1++ || true`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   183  		{Script: `false || 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   184  		{Script: `1++ && true`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   185  		{Script: `true && 1++`, RunError: fmt.Errorf("invalid operation"), RunOutput: nil},
   186  
   187  		{Script: `a == 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   188  		{Script: `a == 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   189  		{Script: `a != 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   190  		{Script: `a != 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   191  		{Script: `a == 1.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   192  		{Script: `a == 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   193  		{Script: `a != 1.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   194  		{Script: `a != 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   195  
   196  		{Script: `a == 1`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   197  		{Script: `a == 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   198  		{Script: `a != 1`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   199  		{Script: `a != 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   200  		{Script: `a == 1.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   201  		{Script: `a == 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   202  		{Script: `a != 1.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   203  		{Script: `a != 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   204  
   205  		{Script: `a == nil`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": nil}},
   206  		{Script: `a == nil`, Input: map[string]interface{}{"a": nil}, RunOutput: true, Output: map[string]interface{}{"a": nil}},
   207  		{Script: `a == nil`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   208  		{Script: `a == nil`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   209  		{Script: `a == 2`, Input: map[string]interface{}{"a": nil}, RunOutput: false, Output: map[string]interface{}{"a": nil}},
   210  		{Script: `a == 2.0`, Input: map[string]interface{}{"a": nil}, RunOutput: false, Output: map[string]interface{}{"a": nil}},
   211  
   212  		{Script: `1 == 1.0`, RunOutput: true},
   213  		{Script: `1 != 1.0`, RunOutput: false},
   214  		{Script: `"a" != "a"`, RunOutput: false},
   215  
   216  		{Script: `a > 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   217  		{Script: `a > 1`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   218  		{Script: `a < 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   219  		{Script: `a < 3`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   220  		{Script: `a > 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   221  		{Script: `a > 1.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   222  		{Script: `a < 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   223  		{Script: `a < 3.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   224  
   225  		{Script: `a > 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   226  		{Script: `a > 1`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   227  		{Script: `a < 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   228  		{Script: `a < 3`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   229  		{Script: `a > 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   230  		{Script: `a > 1.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   231  		{Script: `a < 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   232  		{Script: `a < 3.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   233  
   234  		{Script: `a >= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   235  		{Script: `a >= 3`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   236  		{Script: `a <= 2`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   237  		{Script: `a <= 3`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   238  		{Script: `a >= 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   239  		{Script: `a >= 3.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   240  		{Script: `a <= 2.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   241  		{Script: `a <= 3.0`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2)}},
   242  
   243  		{Script: `a >= 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   244  		{Script: `a >= 3`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   245  		{Script: `a <= 2`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   246  		{Script: `a <= 3`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   247  		{Script: `a >= 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   248  		{Script: `a >= 3.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2)}},
   249  		{Script: `a <= 2.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   250  		{Script: `a <= 3.0`, Input: map[string]interface{}{"a": float64(2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2)}},
   251  
   252  		{Script: `a = false; b = false; a && b`, RunOutput: false},
   253  		{Script: `a = false; b = true; a && b`, RunOutput: false},
   254  		{Script: `a = true; b = false; a && b`, RunOutput: false},
   255  		{Script: `a = true; b = true; a && b`, RunOutput: true},
   256  		{Script: `a = false; b = false; a || b`, RunOutput: false},
   257  		{Script: `a = false; b = true; a || b`, RunOutput: true},
   258  		{Script: `a = true; b = false; a || b`, RunOutput: true},
   259  		{Script: `a = true; b = true; a || b`, RunOutput: true},
   260  
   261  		{Script: `a = [false]; b = false; a[0] && b`, RunOutput: false},
   262  		{Script: `a = [false]; b = true; a[0] && b`, RunOutput: false},
   263  		{Script: `a = [true]; b = false; a[0] && b`, RunOutput: false},
   264  		{Script: `a = [true]; b = true; a[0] && b`, RunOutput: true},
   265  		{Script: `a = [false]; b = false; a[0] || b`, RunOutput: false},
   266  		{Script: `a = [false]; b = true; a[0] || b`, RunOutput: true},
   267  		{Script: `a = [true]; b = false; a[0] || b`, RunOutput: true},
   268  		{Script: `a = [true]; b = true; a[0] || b`, RunOutput: true},
   269  
   270  		{Script: `a = false; b = [false]; a && b[0]`, RunOutput: false},
   271  		{Script: `a = false; b = [true]; a && b[0]`, RunOutput: false},
   272  		{Script: `a = true; b = [false]; a && b[0]`, RunOutput: false},
   273  		{Script: `a = true; b = [true]; a && b[0]`, RunOutput: true},
   274  		{Script: `a = false; b = [false]; a || b[0]`, RunOutput: false},
   275  		{Script: `a = false; b = [true]; a || b[0]`, RunOutput: true},
   276  		{Script: `a = true; b = [false]; a || b[0]`, RunOutput: true},
   277  		{Script: `a = true; b = [true]; a || b[0]`, RunOutput: true},
   278  
   279  		{Script: `0 && 0`, RunOutput: false},
   280  		{Script: `0 && 1`, RunOutput: false},
   281  		{Script: `1 && 0`, RunOutput: false},
   282  		{Script: `1 && 1`, RunOutput: true},
   283  		{Script: `0 || 0`, RunOutput: false},
   284  		{Script: `0 || 1`, RunOutput: true},
   285  		{Script: `1 || 0`, RunOutput: true},
   286  		{Script: `1 || 1`, RunOutput: true},
   287  
   288  		{Script: `1 == 1 && 1 == 1`, RunOutput: true},
   289  		{Script: `1 == 1 && 1 == 2`, RunOutput: false},
   290  		{Script: `1 == 2 && 1 == 1`, RunOutput: false},
   291  		{Script: `1 == 2 && 1 == 2`, RunOutput: false},
   292  		{Script: `1 == 1 || 1 == 1`, RunOutput: true},
   293  		{Script: `1 == 1 || 1 == 2`, RunOutput: true},
   294  		{Script: `1 == 2 || 1 == 1`, RunOutput: true},
   295  		{Script: `1 == 2 || 1 == 2`, RunOutput: false},
   296  
   297  		{Script: `true == "1"`, RunOutput: true},
   298  		{Script: `true == "t"`, RunOutput: true},
   299  		{Script: `true == "T"`, RunOutput: true},
   300  		{Script: `true == "true"`, RunOutput: true},
   301  		{Script: `true == "TRUE"`, RunOutput: true},
   302  		{Script: `true == "True"`, RunOutput: true},
   303  		{Script: `true == "false"`, RunOutput: false},
   304  		{Script: `false == "0"`, RunOutput: true},
   305  		{Script: `false == "f"`, RunOutput: true},
   306  		{Script: `false == "F"`, RunOutput: true},
   307  		{Script: `false == "false"`, RunOutput: true},
   308  		{Script: `false == "false"`, RunOutput: true},
   309  		{Script: `false == "FALSE"`, RunOutput: true},
   310  		{Script: `false == "False"`, RunOutput: true},
   311  		{Script: `false == "true"`, RunOutput: false},
   312  		{Script: `false == "foo"`, RunOutput: false},
   313  		{Script: `true == "foo"`, RunOutput: true},
   314  
   315  		{Script: `0 == "0"`, RunOutput: true},
   316  		{Script: `"1.0" == 1`, RunOutput: true},
   317  		{Script: `1 == "1"`, RunOutput: true},
   318  		{Script: `0.0 == "0"`, RunOutput: true},
   319  		{Script: `0.0 == "0.0"`, RunOutput: true},
   320  		{Script: `1.0 == "1.0"`, RunOutput: true},
   321  		{Script: `1.2 == "1.2"`, RunOutput: true},
   322  		{Script: `"7" == 7.2`, RunOutput: false},
   323  		{Script: `1.2 == "1"`, RunOutput: false},
   324  		{Script: `"1.1" == 1`, RunOutput: false},
   325  		{Script: `0 == "1"`, RunOutput: false},
   326  
   327  		{Script: `a == b`, Input: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}, RunOutput: true, Output: map[string]interface{}{"a": reflect.Value{}, "b": reflect.Value{}}},
   328  		{Script: `a == b`, Input: map[string]interface{}{"a": reflect.Value{}, "b": true}, RunOutput: false, Output: map[string]interface{}{"a": reflect.Value{}, "b": true}},
   329  		{Script: `a == b`, Input: map[string]interface{}{"a": true, "b": reflect.Value{}}, RunOutput: false, Output: map[string]interface{}{"a": true, "b": reflect.Value{}}},
   330  
   331  		{Script: `a == b`, Input: map[string]interface{}{"a": nil, "b": nil}, RunOutput: true, Output: map[string]interface{}{"a": nil, "b": nil}},
   332  		{Script: `a == b`, Input: map[string]interface{}{"a": nil, "b": true}, RunOutput: false, Output: map[string]interface{}{"a": nil, "b": true}},
   333  		{Script: `a == b`, Input: map[string]interface{}{"a": true, "b": nil}, RunOutput: false, Output: map[string]interface{}{"a": true, "b": nil}},
   334  
   335  		{Script: `a == b`, Input: map[string]interface{}{"a": false, "b": false}, RunOutput: true, Output: map[string]interface{}{"a": false, "b": false}},
   336  		{Script: `a == b`, Input: map[string]interface{}{"a": false, "b": true}, RunOutput: false, Output: map[string]interface{}{"a": false, "b": true}},
   337  		{Script: `a == b`, Input: map[string]interface{}{"a": true, "b": false}, RunOutput: false, Output: map[string]interface{}{"a": true, "b": false}},
   338  		{Script: `a == b`, Input: map[string]interface{}{"a": true, "b": true}, RunOutput: true, Output: map[string]interface{}{"a": true, "b": true}},
   339  
   340  		{Script: `a == b`, Input: map[string]interface{}{"a": int32(1), "b": int32(1)}, RunOutput: true, Output: map[string]interface{}{"a": int32(1), "b": int32(1)}},
   341  		{Script: `a == b`, Input: map[string]interface{}{"a": int32(1), "b": int32(2)}, RunOutput: false, Output: map[string]interface{}{"a": int32(1), "b": int32(2)}},
   342  		{Script: `a == b`, Input: map[string]interface{}{"a": int32(2), "b": int32(1)}, RunOutput: false, Output: map[string]interface{}{"a": int32(2), "b": int32(1)}},
   343  		{Script: `a == b`, Input: map[string]interface{}{"a": int32(2), "b": int32(2)}, RunOutput: true, Output: map[string]interface{}{"a": int32(2), "b": int32(2)}},
   344  
   345  		{Script: `a == b`, Input: map[string]interface{}{"a": int64(1), "b": int64(1)}, RunOutput: true, Output: map[string]interface{}{"a": int64(1), "b": int64(1)}},
   346  		{Script: `a == b`, Input: map[string]interface{}{"a": int64(1), "b": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   347  		{Script: `a == b`, Input: map[string]interface{}{"a": int64(2), "b": int64(1)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2), "b": int64(1)}},
   348  		{Script: `a == b`, Input: map[string]interface{}{"a": int64(2), "b": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": int64(2), "b": int64(2)}},
   349  
   350  		{Script: `a == b`, Input: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}, RunOutput: true, Output: map[string]interface{}{"a": float32(1.1), "b": float32(1.1)}},
   351  		{Script: `a == b`, Input: map[string]interface{}{"a": float32(1.1), "b": float32(2.2)}, RunOutput: false, Output: map[string]interface{}{"a": float32(1.1), "b": float32(2.2)}},
   352  		{Script: `a == b`, Input: map[string]interface{}{"a": float32(2.2), "b": float32(1.1)}, RunOutput: false, Output: map[string]interface{}{"a": float32(2.2), "b": float32(1.1)}},
   353  		{Script: `a == b`, Input: map[string]interface{}{"a": float32(2.2), "b": float32(2.2)}, RunOutput: true, Output: map[string]interface{}{"a": float32(2.2), "b": float32(2.2)}},
   354  
   355  		{Script: `a == b`, Input: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}, RunOutput: true, Output: map[string]interface{}{"a": float64(1.1), "b": float64(1.1)}},
   356  		{Script: `a == b`, Input: map[string]interface{}{"a": float64(1.1), "b": float64(2.2)}, RunOutput: false, Output: map[string]interface{}{"a": float64(1.1), "b": float64(2.2)}},
   357  		{Script: `a == b`, Input: map[string]interface{}{"a": float64(2.2), "b": float64(1.1)}, RunOutput: false, Output: map[string]interface{}{"a": float64(2.2), "b": float64(1.1)}},
   358  		{Script: `a == b`, Input: map[string]interface{}{"a": float64(2.2), "b": float64(2.2)}, RunOutput: true, Output: map[string]interface{}{"a": float64(2.2), "b": float64(2.2)}},
   359  
   360  		{Script: `a == b`, Input: map[string]interface{}{"a": 'a', "b": 'a'}, RunOutput: true, Output: map[string]interface{}{"a": 'a', "b": 'a'}},
   361  		{Script: `a == b`, Input: map[string]interface{}{"a": 'a', "b": 'b'}, RunOutput: false, Output: map[string]interface{}{"a": 'a', "b": 'b'}},
   362  		{Script: `a == b`, Input: map[string]interface{}{"a": 'b', "b": 'a'}, RunOutput: false, Output: map[string]interface{}{"a": 'b', "b": 'a'}},
   363  		{Script: `a == b`, Input: map[string]interface{}{"a": 'b', "b": 'b'}, RunOutput: true, Output: map[string]interface{}{"a": 'b', "b": 'b'}},
   364  
   365  		{Script: `a == b`, Input: map[string]interface{}{"a": "a", "b": "a"}, RunOutput: true, Output: map[string]interface{}{"a": "a", "b": "a"}},
   366  		{Script: `a == b`, Input: map[string]interface{}{"a": "a", "b": "b"}, RunOutput: false, Output: map[string]interface{}{"a": "a", "b": "b"}},
   367  		{Script: `a == b`, Input: map[string]interface{}{"a": "b", "b": "a"}, RunOutput: false, Output: map[string]interface{}{"a": "b", "b": "a"}},
   368  		{Script: `a == b`, Input: map[string]interface{}{"a": "b", "b": "b"}, RunOutput: true, Output: map[string]interface{}{"a": "b", "b": "b"}},
   369  
   370  		{Script: `b = "\"a\""; a == b`, Input: map[string]interface{}{"a": `"a"`}, RunOutput: true, Output: map[string]interface{}{"a": `"a"`, "b": `"a"`}},
   371  
   372  		{Script: `a = "test"; a == "test"`, RunOutput: true},
   373  		{Script: `a = "test"; a[0:1] == "t"`, RunOutput: true},
   374  		{Script: `a = "test"; a[0:2] == "te"`, RunOutput: true},
   375  		{Script: `a = "test"; a[1:3] == "es"`, RunOutput: true},
   376  		{Script: `a = "test"; a[0:4] == "test"`, RunOutput: true},
   377  
   378  		{Script: `a = "a b"; a[1] == ' '`, RunOutput: true},
   379  		{Script: `a = "test"; a[0] == 't'`, RunOutput: true},
   380  		{Script: `a = "test"; a[1] == 'e'`, RunOutput: true},
   381  		{Script: `a = "test"; a[3] == 't'`, RunOutput: true},
   382  
   383  		{Script: `a = "a b"; a[1] != ' '`, RunOutput: false},
   384  		{Script: `a = "test"; a[0] != 't'`, RunOutput: false},
   385  		{Script: `a = "test"; a[1] != 'e'`, RunOutput: false},
   386  		{Script: `a = "test"; a[3] != 't'`, RunOutput: false},
   387  	}
   388  	runTests(t, tests, nil, &Options{Debug: true})
   389  }
   390  
   391  func TestThrows(t *testing.T) {
   392  	t.Parallel()
   393  
   394  	tests := []Test{
   395  		{Script: `throw(1++)`, RunError: fmt.Errorf("invalid operation")},
   396  		// {Script: `throw(a)`, Input: map[string]interface{}{"a": reflect.Value{}}, RunError: fmt.Errorf("invalid operation")},
   397  
   398  		{Script: `true && func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   399  		{Script: `false && func(){throw('abcde')}()`, RunOutput: false},
   400  		{Script: `true || func(){throw('abcde')}()`, RunOutput: true},
   401  		{Script: `false || func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   402  		{Script: `true && true && func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   403  		{Script: `true && false && func(){throw('abcde')}()`, RunOutput: false},
   404  		{Script: `true && func(){throw('abcde')}() && true`, RunError: fmt.Errorf("abcde")},
   405  		{Script: `false && func(){throw('abcde')}() && func(){throw('abcde')}() `, RunOutput: false},
   406  
   407  		{Script: `true && func(){throw('abcde')}() || false`, RunError: fmt.Errorf("abcde")},
   408  		{Script: `true && false || func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   409  		{Script: `true && true || func(){throw('abcde')}()`, RunOutput: true},
   410  
   411  		{Script: `true || func(){throw('abcde')}() || func(){throw('abcde')}()`, RunOutput: true},
   412  		{Script: `false || func(){throw('abcde')}() || true`, RunError: fmt.Errorf("abcde")},
   413  		{Script: `false || true || func(){throw('abcde')}()`, RunOutput: true},
   414  		{Script: `false || false || func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   415  
   416  		{Script: `false || false && func(){throw('abcde')}()`, RunOutput: false},
   417  		{Script: `false || true && func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   418  		{Script: `false || func(){throw('abcde')}() || true`, RunError: fmt.Errorf("abcde")},
   419  
   420  		{Script: `1 == 1 && func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   421  		{Script: `1 == 2 && func(){throw('abcde')}()`, RunOutput: false},
   422  		{Script: `1 == 1 || func(){throw('abcde')}()`, RunOutput: true},
   423  		{Script: `1 == 2 || func(){throw('abcde')}()`, RunError: fmt.Errorf("abcde")},
   424  
   425  		{Script: `(true || func(){throw('abcde')}()) && (true || func(){throw('hello')}())`, RunOutput: true},
   426  		{Script: `(true || func(){throw('abcde')}()) && (true && func(){throw('hello')}())`, RunError: fmt.Errorf("hello")},
   427  		{Script: `(true || func(){throw('abcde')}()) || (true && func(){throw('hello')}())`, RunOutput: true},
   428  		{Script: `(true && func(){throw('abcde')}()) && (true && func(){throw('hello')}())`, RunError: fmt.Errorf("abcde")},
   429  		{Script: `(true || func(){throw('abcde')}()) && (false || func(){throw('hello')}())`, RunError: fmt.Errorf("hello")},
   430  	}
   431  	runTests(t, tests, nil, &Options{Debug: true})
   432  }
   433  
   434  func TestTernaryOperator(t *testing.T) {
   435  	t.Parallel()
   436  
   437  	tests := []Test{
   438  		{Script: `a = a ? 1 : 2`, RunError: fmt.Errorf("undefined symbol 'a'")},
   439  		{Script: `a = z ? 1 : 2`, RunError: fmt.Errorf("undefined symbol 'z'")},
   440  		{Script: `a = 0; a = a ? 1 : z`, RunError: fmt.Errorf("undefined symbol 'z'")},
   441  		{Script: `a = 1; a = a ? z : 1`, RunError: fmt.Errorf("undefined symbol 'z'")},
   442  		{Script: `a = b[1] ? 2 : 1`, Input: map[string]interface{}{"b": []interface{}{}}, RunError: fmt.Errorf("index out of range")},
   443  		{Script: `a = b[1][2] ? 2 : 1`, Input: map[string]interface{}{"b": []interface{}{}}, RunError: fmt.Errorf("index out of range")},
   444  		{Script: `a = b["test"][1] ? 2 : 1`, Input: map[string]interface{}{"b": map[string]interface{}{"test": 2}}, RunError: fmt.Errorf("type int does not support index operation")},
   445  
   446  		{Script: `a = 1 ? 2 : z`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   447  		{Script: `a = -1 ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   448  		{Script: `a = true ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   449  		{Script: `a = false ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   450  		{Script: `a = "true" ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   451  		{Script: `a = "false" ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   452  		{Script: `a = "-1" ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   453  		{Script: `a = "0" ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   454  		{Script: `a = "0.0" ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   455  		{Script: `a = "2" ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   456  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": int64(0)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   457  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": int64(2)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   458  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": float64(0.0)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   459  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": float64(2.0)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   460  		{Script: `a = b ? 2 : 1.0`, Input: map[string]interface{}{"b": float64(0.0)}, RunOutput: float64(1.0), Output: map[string]interface{}{"a": float64(1.0)}},
   461  		{Script: `a = b ? 2 : 1.0`, Input: map[string]interface{}{"b": float64(0.1)}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   462  		{Script: `a = b ? 2 : 1.0`, Input: map[string]interface{}{"b": nil}, RunOutput: float64(1.0), Output: map[string]interface{}{"a": float64(1.0)}},
   463  		{Script: `a = nil ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   464  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": []interface{}{}}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   465  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": map[string]interface{}{}}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   466  		{Script: `a = [] ? 2 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   467  		{Script: `a = [2] ? 2 : 1`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   468  		{Script: `a = b ? 2 : 1`, Input: map[string]interface{}{"b": map[string]interface{}{"test": int64(2)}}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   469  		{Script: `a = b["test"] ? 2 : 1`, Input: map[string]interface{}{"b": map[string]interface{}{"test": int64(2)}}, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   470  		{Script: `b = "test"; a = b ? 2 : "empty"`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   471  		{Script: `b = "test"; a = b[1:3] ? 2 : "empty"`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(2)}},
   472  		{Script: `b = "test"; a = b[2:2] ? 2 : "empty"`, RunOutput: "empty", Output: map[string]interface{}{"a": "empty"}},
   473  		{Script: `b = "0.0"; a = false ? 2 : b ? 3 : 1`, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   474  		{Script: `b = "true"; a = false ? 2 : b ? 3 : 1`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   475  	}
   476  	runTests(t, tests, nil, &Options{Debug: true})
   477  }
   478  
   479  func TestNilCoalescingOperator(t *testing.T) {
   480  	t.Parallel()
   481  
   482  	tests := []Test{
   483  		{Script: `nil ?? nil`, RunOutput: nil},
   484  		{Script: `false ?? nil`, RunOutput: false},
   485  		{Script: `true ?? nil`, RunOutput: true},
   486  		{Script: `nil ?? false`, RunOutput: false},
   487  		{Script: `nil ?? true`, RunOutput: true},
   488  		{Script: `1 ?? nil`, RunOutput: int64(1)},
   489  		{Script: `1 ?? 2`, RunOutput: int64(1)},
   490  		{Script: `nil ?? 1`, RunOutput: int64(1)},
   491  
   492  		{Script: `a ?? 1`, RunOutput: int64(1)},
   493  		{Script: `a ?? b`, RunError: fmt.Errorf("undefined symbol 'b'")},
   494  
   495  		{Script: `a ?? 2`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   496  		{Script: `a ?? b`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   497  		{Script: `a ?? b`, Input: map[string]interface{}{"a": int64(1), "b": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1), "b": int64(2)}},
   498  		{Script: `a ?? b`, Input: map[string]interface{}{"a": nil, "b": int64(2)}, RunOutput: int64(2), Output: map[string]interface{}{"a": nil, "b": int64(2)}},
   499  
   500  		{Script: `[] ?? 1`, RunOutput: []interface{}{}},
   501  		{Script: `{} ?? 1`, RunOutput: map[interface{}]interface{}{}},
   502  
   503  		// test nil array and map
   504  		{Script: `a ?? 5`, Input: map[string]interface{}{"a": testSliceEmpty}, RunOutput: int64(5), Output: map[string]interface{}{"a": testSliceEmpty}},
   505  		{Script: `a ?? 6`, Input: map[string]interface{}{"a": testMapEmpty}, RunOutput: int64(6), Output: map[string]interface{}{"a": testMapEmpty}},
   506  	}
   507  	runTests(t, tests, nil, &Options{Debug: true})
   508  }
   509  
   510  func TestIf(t *testing.T) {
   511  	t.Parallel()
   512  
   513  	tests := []Test{
   514  		{Script: `if 1++ {}`, RunError: fmt.Errorf("invalid operation")},
   515  		{Script: `if false {} else if 1++ {}`, RunError: fmt.Errorf("invalid operation")},
   516  		{Script: `if false {} else if true { 1++ }`, RunError: fmt.Errorf("invalid operation")},
   517  
   518  		{Script: `if true {}`, Input: map[string]interface{}{"a": nil}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   519  		{Script: `if true {}`, Input: map[string]interface{}{"a": true}, RunOutput: nil, Output: map[string]interface{}{"a": true}},
   520  		{Script: `if true {}`, Input: map[string]interface{}{"a": int64(1)}, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   521  		{Script: `if true {}`, Input: map[string]interface{}{"a": float64(1.1)}, RunOutput: nil, Output: map[string]interface{}{"a": float64(1.1)}},
   522  		{Script: `if true {}`, Input: map[string]interface{}{"a": "a"}, RunOutput: nil, Output: map[string]interface{}{"a": "a"}},
   523  
   524  		{Script: `if true {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   525  		{Script: `if true {a = true}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: true, Output: map[string]interface{}{"a": true}},
   526  		{Script: `if true {a = 1}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   527  		{Script: `if true {a = 1.1}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: float64(1.1), Output: map[string]interface{}{"a": float64(1.1)}},
   528  		{Script: `if true {a = "a"}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: "a", Output: map[string]interface{}{"a": "a"}},
   529  
   530  		{Script: `if a == 1 {a = 1}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   531  		{Script: `if a == 2 {a = 1}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   532  		{Script: `if a == 1 {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   533  		{Script: `if a == 2 {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   534  
   535  		{Script: `if a == 1 {a = 1} else {a = 3}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   536  		{Script: `if a == 2 {a = 1} else {a = 3}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(1), Output: map[string]interface{}{"a": int64(1)}},
   537  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   538  		{Script: `if a == 1 {a = 1} else if a == 2 {a = 3}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   539  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else {a = 4}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(4)}},
   540  
   541  		{Script: `if a == 1 {a = 1} else {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   542  		{Script: `if a == 2 {a = nil} else {a = 3}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   543  		{Script: `if a == 1 {a = nil} else if a == 3 {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: false, Output: map[string]interface{}{"a": int64(2)}},
   544  		{Script: `if a == 1 {a = 1} else if a == 2 {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   545  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   546  
   547  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else if a == 4 {a = 4} else {a = 5}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(5)}},
   548  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else if a == 4 {a = 4} else {a = nil}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   549  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else if a == 2 {a = 4} else {a = 5}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: int64(4), Output: map[string]interface{}{"a": int64(4)}},
   550  		{Script: `if a == 1 {a = 1} else if a == 3 {a = 3} else if a == 2 {a = nil} else {a = 5}`, Input: map[string]interface{}{"a": int64(2)}, RunOutput: nil, Output: map[string]interface{}{"a": nil}},
   551  
   552  		// check scope
   553  		{Script: `a = 1; if a == 1 { b = 2 }; b`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": int64(1)}},
   554  		{Script: `a = 1; if a == 2 { b = 3 } else { b = 4 }; b`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": int64(1)}},
   555  		{Script: `a = 1; if a == 2 { b = 3 } else if a == 1 { b = 4 }; b`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": int64(1)}},
   556  		{Script: `a = 1; if a == 2 { b = 4 } else if a == 5 { b = 6 } else if a == 1 { c = b }`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": int64(1)}},
   557  		{Script: `a = 1; if a == 2 { b = 4 } else if a == 5 { b = 6 } else if a == 1 { b = 7 }; b`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": int64(1)}},
   558  	}
   559  	runTests(t, tests, nil, &Options{Debug: true})
   560  }
   561  
   562  func TestSwitch(t *testing.T) {
   563  	t.Parallel()
   564  
   565  	tests := []Test{
   566  		// test parse errors
   567  		{Script: `switch {}`, ParseError: fmt.Errorf("syntax error")},
   568  		{Script: `a = 1; switch a; {}`, ParseError: fmt.Errorf("syntax error")},
   569  		{Script: `a = 1; switch a = 2 {}`, ParseError: fmt.Errorf("syntax error")},
   570  		{Script: `a = 1; switch a {default: return 6; default: return 7}`, ParseError: fmt.Errorf("multiple default statement"), RunOutput: int64(7)},
   571  		{Script: `a = 1; switch a {case 1: return 5; default: return 6; default: return 7}`, ParseError: fmt.Errorf("multiple default statement"), RunOutput: int64(5)},
   572  
   573  		// test run errors
   574  		{Script: `a = 1; switch 1++ {}`, RunError: fmt.Errorf("invalid operation")},
   575  		{Script: `a = 1; switch a {case 1++: return 2}`, RunError: fmt.Errorf("invalid operation")},
   576  
   577  		// test no or empty cases
   578  		{Script: `a = 1; switch a {}`, Output: map[string]interface{}{"a": int64(1)}},
   579  		{Script: `a = 1; switch a {case: return 2}`, Output: map[string]interface{}{"a": int64(1)}},
   580  		{Script: `a = 1; switch a {case: return 2; case: return 3}`, Output: map[string]interface{}{"a": int64(1)}},
   581  
   582  		// test 1 case
   583  		{Script: `a = 1; switch a {case 1: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   584  		{Script: `a = 2; switch a {case 1: return 5}`, Output: map[string]interface{}{"a": int64(2)}},
   585  		{Script: `a = 1; switch a {case 1,2: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   586  		{Script: `a = 2; switch a {case 1,2: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(2)}},
   587  		{Script: `a = 3; switch a {case 1,2: return 5}`, Output: map[string]interface{}{"a": int64(3)}},
   588  		{Script: `a = 1; switch a {case 1,2,3: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   589  		{Script: `a = 2; switch a {case 1,2,3: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(2)}},
   590  		{Script: `a = 3; switch a {case 1,2,3: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(3)}},
   591  		{Script: `a = 4; switch a {case 1,2,3: return 5}`, Output: map[string]interface{}{"a": int64(4)}},
   592  		{Script: `a = func() { return 1 }; switch a() {case 1: return 5}`, RunOutput: int64(5)},
   593  		{Script: `a = func() { return 2 }; switch a() {case 1: return 5}`},
   594  		{Script: `a = func() { return 5 }; b = 1; switch b {case 1: return a() }`, RunOutput: int64(5), Output: map[string]interface{}{"b": int64(1)}},
   595  		{Script: `a = func() { return 6 }; b = 2; switch b {case 1: return a() }`, Output: map[string]interface{}{"b": int64(2)}},
   596  
   597  		// test 2 cases
   598  		{Script: `a = 1; switch a {case 1: return 5; case 2: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   599  		{Script: `a = 2; switch a {case 1: return 5; case 2: return 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(2)}},
   600  		{Script: `a = 3; switch a {case 1: return 5; case 2: return 6}`, Output: map[string]interface{}{"a": int64(3)}},
   601  		{Script: `a = 1; switch a {case 1: return 5; case 2,3: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   602  		{Script: `a = 2; switch a {case 1: return 5; case 2,3: return 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(2)}},
   603  		{Script: `a = 3; switch a {case 1: return 5; case 2,3: return 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(3)}},
   604  		{Script: `a = 4; switch a {case 1: return 5; case 2,3: return 6}`, Output: map[string]interface{}{"a": int64(4)}},
   605  
   606  		// test 3 cases
   607  		{Script: `a = 1; switch a {case 1,2: return 5; case 3: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   608  		{Script: `a = 2; switch a {case 1,2: return 5; case 3: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(2)}},
   609  		{Script: `a = 3; switch a {case 1,2: return 5; case 3: return 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(3)}},
   610  		{Script: `a = 4; switch a {case 1,2: return 5; case 3: return 6}`, Output: map[string]interface{}{"a": int64(4)}},
   611  		{Script: `a = 1; switch a {case 1,2: return 5; case 2,3: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   612  		{Script: `a = 2; switch a {case 1,2: return 5; case 2,3: return 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(2)}},
   613  		{Script: `a = 3; switch a {case 1,2: return 5; case 2,3: return 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(3)}},
   614  		{Script: `a = 4; switch a {case 1,2: return 5; case 2,3: return 6}`, Output: map[string]interface{}{"a": int64(4)}},
   615  
   616  		// test default
   617  		{Script: `a = 1; switch a {default: return 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   618  		{Script: `a = 1; switch a {case 1: return 5; case 2: return 6; default: return 7}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   619  		{Script: `a = 2; switch a {case 1: return 5; case 2: return 6; default: return 7}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(2)}},
   620  		{Script: `a = 3; switch a {case 1: return 5; case 2: return 6; default: return 7}`, RunOutput: int64(7), Output: map[string]interface{}{"a": int64(3)}},
   621  		{Script: `a = 1; switch a {case 1: return 5; case 2,3: return 6; default: return 7}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   622  		{Script: `a = 2; switch a {case 1: return 5; case 2,3: return 6; default: return 7}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(2)}},
   623  		{Script: `a = 3; switch a {case 1: return 5; case 2,3: return 6; default: return 7}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(3)}},
   624  		{Script: `a = 4; switch a {case 1: return 5; case 2,3: return 6; default: return 7}`, RunOutput: int64(7), Output: map[string]interface{}{"a": int64(4)}},
   625  		{Script: `a = 1; switch a {case 1,2: return 5; case 3: return 6; default: return 7}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   626  		{Script: `a = 2; switch a {case 1,2: return 5; case 3: return 6; default: return 7}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(2)}},
   627  		{Script: `a = 3; switch a {case 1,2: return 5; case 3: return 6; default: return 7}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(3)}},
   628  		{Script: `a = 4; switch a {case 1,2: return 5; case 3: return 6; default: return 7}`, RunOutput: int64(7), Output: map[string]interface{}{"a": int64(4)}},
   629  
   630  		// test scope
   631  		{Script: `a = 1; switch a {case 1: a = 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(5)}},
   632  		{Script: `a = 2; switch a {case 1: a = 5}`, Output: map[string]interface{}{"a": int64(2)}},
   633  		{Script: `a = 1; b = 5; switch a {case 1: b = 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(1), "b": int64(6)}},
   634  		{Script: `a = 2; b = 5; switch a {case 1: b = 6}`, Output: map[string]interface{}{"a": int64(2), "b": int64(5)}},
   635  		{Script: `a = 1; b = 5; switch a {case 1: b = 6; default: b = 7}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(1), "b": int64(6)}},
   636  		{Script: `a = 2; b = 5; switch a {case 1: b = 6; default: b = 7}`, RunOutput: int64(7), Output: map[string]interface{}{"a": int64(2), "b": int64(7)}},
   637  
   638  		// test scope without define b
   639  		{Script: `a = 1; switch a {case 1: b = 5}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   640  		{Script: `a = 2; switch a {case 1: b = 5}`, Output: map[string]interface{}{"a": int64(2)}},
   641  		{Script: `a = 1; switch a {case 1: b = 5}; b`, RunError: fmt.Errorf("undefined symbol 'b'"), RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   642  		{Script: `a = 2; switch a {case 1: b = 5}; b`, RunError: fmt.Errorf("undefined symbol 'b'"), RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   643  		{Script: `a = 1; switch a {case 1: b = 5; default: b = 6}`, RunOutput: int64(5), Output: map[string]interface{}{"a": int64(1)}},
   644  		{Script: `a = 2; switch a {case 1: b = 5; default: b = 6}`, RunOutput: int64(6), Output: map[string]interface{}{"a": int64(2)}},
   645  		{Script: `a = 1; switch a {case 1: b = 5; default: b = 6}; b`, RunError: fmt.Errorf("undefined symbol 'b'"), RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   646  		{Script: `a = 2; switch a {case 1: b = 5; default: b = 6}; b`, RunError: fmt.Errorf("undefined symbol 'b'"), RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   647  
   648  		// test new lines
   649  		{Script: `
   650  a = 1;
   651  switch a {
   652  	case 1:
   653  		return 1
   654  }`, RunOutput: int64(1)},
   655  	}
   656  	runTests(t, tests, nil, &Options{Debug: true})
   657  }
   658  
   659  func TestForLoop(t *testing.T) {
   660  	t.Parallel()
   661  
   662  	tests := []Test{
   663  		{Script: `for in [1] { }`, ParseError: fmt.Errorf("missing identifier")},
   664  		{Script: `for a, b, c in [1] { }`, ParseError: fmt.Errorf("too many identifiers")},
   665  
   666  		{Script: `break`, RunError: fmt.Errorf("unexpected break statement")},
   667  		{Script: `continue`, RunError: fmt.Errorf("unexpected continue statement")},
   668  		{Script: `for 1++ { }`, RunError: fmt.Errorf("invalid operation")},
   669  		{Script: `for { 1++ }`, RunError: fmt.Errorf("invalid operation")},
   670  		{Script: `for a in 1++ { }`, RunError: fmt.Errorf("invalid operation")},
   671  
   672  		{Script: `for { break }`, RunOutput: nil},
   673  		{Script: `for {a = 1; if a == 1 { break } }`, RunOutput: nil},
   674  		{Script: `a = 1; for { if a == 1 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   675  		{Script: `a = 1; for { if a == 1 { break }; a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   676  		{Script: `a = 1; for { if a == 3 { break }; a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   677  
   678  		{Script: `a = 1; for { if a == 1 { return }; a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   679  		{Script: `a = 1; for { if a == 3 { return }; a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   680  		{Script: `a = 1; for { if a == 1 { return 2 }; a++ }`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(1)}},
   681  		{Script: `a = 1; for { if a == 3 { return 2 }; a++ }`, RunOutput: int64(2), Output: map[string]interface{}{"a": int64(3)}},
   682  
   683  		{Script: `a = 1; for { if a == 3 { return 3 }; a++ }; return 2`, RunOutput: int64(3), Output: map[string]interface{}{"a": int64(3)}},
   684  
   685  		{Script: `a = 1; for { a++; if a == 2 { continue } else { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   686  		{Script: `a = 1; for { a++; if a == 2 { continue }; if a == 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   687  
   688  		{Script: `for a in [1] { if a == 1 { break } }`, RunOutput: nil},
   689  		{Script: `for a in [1, 2] { if a == 2 { break } }`, RunOutput: nil},
   690  		{Script: `for a in [1, 2, 3] { if a == 3 { break } }`, RunOutput: nil},
   691  
   692  		{Script: `for a in [1, 2, 3] { if a == 2 { return 2 } }; return 3`, RunOutput: int64(2)},
   693  
   694  		{Script: `a = [1]; for b in a { if b == 1 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1)}}},
   695  		{Script: `a = [1, 2]; for b in a { if b == 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1), int64(2)}}},
   696  		{Script: `a = [1, 2, 3]; for b in a { if b == 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1), int64(2), int64(3)}}},
   697  
   698  		{Script: `a = [1]; b = 0; for c in a { b = c }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1)}, "b": int64(1)}},
   699  		{Script: `a = [1, 2]; b = 0; for c in a { b = c }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1), int64(2)}, "b": int64(2)}},
   700  		{Script: `a = [1, 2, 3]; b = 0; for c in a { b = c }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1), int64(2), int64(3)}, "b": int64(3)}},
   701  
   702  		{Script: `a = 1; for a < 2 { a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   703  		{Script: `a = 1; for a < 3 { a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   704  
   705  		{Script: `a = 1; for nil { a++; if a > 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   706  		{Script: `a = 1; for nil { a++; if a > 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   707  		{Script: `a = 1; for true { a++; if a > 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   708  		{Script: `a = 1; for true { a++; if a > 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(4)}},
   709  
   710  		{Script: `func x() { return [1] }; for b in x() { if b == 1 { break } }`, RunOutput: nil},
   711  		{Script: `func x() { return [1, 2] }; for b in x() { if b == 2 { break } }`, RunOutput: nil},
   712  		{Script: `func x() { return [1, 2, 3] }; for b in x() { if b == 3 { break } }`, RunOutput: nil},
   713  
   714  		{Script: `func x() { a = 1; for { if a == 1 { return } } }; x()`, RunOutput: nil},
   715  		{Script: `func x() { a = 1; for { if a == 1 { return nil } } }; x()`, RunOutput: nil},
   716  		{Script: `func x() { a = 1; for { if a == 1 { return true } } }; x()`, RunOutput: true},
   717  		{Script: `func x() { a = 1; for { if a == 1 { return 1 } } }; x()`, RunOutput: int64(1)},
   718  		{Script: `func x() { a = 1; for { if a == 1 { return 1.1 } } }; x()`, RunOutput: float64(1.1)},
   719  		{Script: `func x() { a = 1; for { if a == 1 { return "a" } } }; x()`, RunOutput: "a"},
   720  
   721  		{Script: `func x() { for a in [1, 2, 3] { if a == 3 { return } } }; x()`, RunOutput: nil},
   722  		{Script: `func x() { for a in [1, 2, 3] { if a == 3 { return 3 } }; return 2 }; x()`, RunOutput: int64(3)},
   723  		{Script: `func x() { for a in [1, 2, 3] { if a == 1 { continue } } }; x()`, RunOutput: nil},
   724  		{Script: `func x() { for a in [1, 2, 3] { if a == 1 { continue };  if a == 3 { return } } }; x()`, RunOutput: nil},
   725  
   726  		{Script: `func x() { return [1, 2] }; a = 1; for i in x() { a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   727  		{Script: `func x() { return [1, 2, 3] }; a = 1; for i in x() { a++ }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(4)}},
   728  
   729  		{Script: `for a = 1; nil; nil { return }`},
   730  		// TOFIX:
   731  		// {Script: `for a, b = 1; nil; nil { return }`},
   732  		// {Script: `for a, b = 1, 2; nil; nil { return }`},
   733  
   734  		{Script: `var a = 1; for ; ; { return a }`, RunOutput: int64(1)},
   735  		{Script: `var a = 1; for ; ; a++ { return a }`, RunOutput: int64(1)},
   736  		{Script: `var a = 1; for ; a > 0 ; { return a }`, RunOutput: int64(1)},
   737  		{Script: `var a = 1; for ; a > 0 ; a++ { return a }`, RunOutput: int64(1)},
   738  		{Script: `for var a = 1 ; ; { return a }`, RunOutput: int64(1)},
   739  		{Script: `for var a = 1 ; ; a++ { return a }`, RunOutput: int64(1)},
   740  		{Script: `for var a = 1 ; a > 0 ; { return a }`, RunOutput: int64(1)},
   741  		{Script: `for var a = 1 ; a > 0 ; a++ { return a }`, RunOutput: int64(1)},
   742  
   743  		{Script: `for var a = 1; nil; nil { return }`},
   744  		{Script: `for var a = 1, 2; nil; nil { return }`},
   745  		{Script: `for var a, b = 1; nil; nil { return }`},
   746  		{Script: `for var a, b = 1, 2; nil; nil { return }`},
   747  
   748  		{Script: `for a.b = 1; nil; nil { return }`, RunError: fmt.Errorf("undefined symbol 'a'")},
   749  
   750  		{Script: `for a = 1; nil; nil { if a == 1 { break } }`, RunOutput: nil},
   751  		{Script: `for a = 1; nil; nil { if a == 2 { break }; a++ }`, RunOutput: nil},
   752  		{Script: `for a = 1; nil; nil { a++; if a == 3 { break } }`, RunOutput: nil},
   753  
   754  		{Script: `for a = 1; a < 1; nil { }`, RunOutput: nil},
   755  		{Script: `for a = 1; a > 1; nil { }`, RunOutput: nil},
   756  		{Script: `for a = 1; a == 1; nil { break }`, RunOutput: nil},
   757  
   758  		{Script: `for a = 1; a == 1; a++ { }`, RunOutput: nil},
   759  		{Script: `for a = 1; a < 2; a++ { }`, RunOutput: nil},
   760  		{Script: `for a = 1; a < 3; a++ { }`, RunOutput: nil},
   761  
   762  		{Script: `for a = 1; a < 5; a++ { if a == 3 { return 3 } }; return 2`, RunOutput: int64(3)},
   763  
   764  		{Script: `a = 1; for b = 1; a < 1; a++ { }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   765  		{Script: `a = 1; for b = 1; a < 2; a++ { }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   766  		{Script: `a = 1; for b = 1; a < 3; a++ { }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   767  
   768  		{Script: `a = 1; for b = 1; a < 1; a++ {  if a == 1 { continue } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   769  		{Script: `a = 1; for b = 1; a < 2; a++ {  if a == 1 { continue } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   770  		{Script: `a = 1; for b = 1; a < 3; a++ {  if a == 1 { continue } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   771  
   772  		{Script: `a = 1; for b = 1; a < 1; a++ {  if a == 1 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   773  		{Script: `a = 1; for b = 1; a < 2; a++ {  if a == 1 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   774  		{Script: `a = 1; for b = 1; a < 3; a++ {  if a == 1 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   775  		{Script: `a = 1; for b = 1; a < 1; a++ {  if a == 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   776  		{Script: `a = 1; for b = 1; a < 2; a++ {  if a == 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   777  		{Script: `a = 1; for b = 1; a < 3; a++ {  if a == 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   778  		{Script: `a = 1; for b = 1; a < 1; a++ {  if a == 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(1)}},
   779  		{Script: `a = 1; for b = 1; a < 2; a++ {  if a == 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(2)}},
   780  		{Script: `a = 1; for b = 1; a < 3; a++ {  if a == 3 { break } }`, RunOutput: nil, Output: map[string]interface{}{"a": int64(3)}},
   781  
   782  		{Script: `a = ["123", "456", "789"]; b = ""; for i = 0; i < len(a); i++ { b += a[i][len(a[i]) - 2:]; b += a[i][:len(a[i]) - 2] }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{"123", "456", "789"}, "b": "231564897"}},
   783  		{Script: `a = [[["123"], ["456"]], [["789"]]]; b = ""; for i = 0; i < len(a); i++ { for j = 0; j < len(a[i]); j++ {  for k = 0; k < len(a[i][j]); k++ { for l = 0; l < len(a[i][j][k]); l++ { b += a[i][j][k][l] + "-" } } } }`,
   784  			RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{[]interface{}{[]interface{}{"123"}, []interface{}{"456"}}, []interface{}{[]interface{}{"789"}}}, "b": "1-2-3-4-5-6-7-8-9-"}},
   785  
   786  		{Script: `func x() { for a = 1; a < 3; a++ { if a == 1 { return a } } }; x()`, RunOutput: int64(1)},
   787  		{Script: `func x() { for a = 1; a < 3; a++ { if a == 2 { return a } } }; x()`, RunOutput: int64(2)},
   788  		{Script: `func x() { for a = 1; a < 3; a++ { if a == 3 { return a } } }; x()`, RunOutput: nil},
   789  		{Script: `func x() { for a = 1; a < 3; a++ { if a == 4 { return a } } }; x()`, RunOutput: nil},
   790  
   791  		{Script: `func x() { a = 1; for b = 1; a < 3; a++ { if a == 1 { continue } }; return a }; x()`, RunOutput: int64(3)},
   792  		{Script: `func x() { a = 1; for b = 1; a < 3; a++ { if a == 2 { continue } }; return a }; x()`, RunOutput: int64(3)},
   793  		{Script: `func x() { a = 1; for b = 1; a < 3; a++ { if a == 3 { continue } }; return a }; x()`, RunOutput: int64(3)},
   794  		{Script: `func x() { a = 1; for b = 1; a < 3; a++ { if a == 4 { continue } }; return a }; x()`, RunOutput: int64(3)},
   795  
   796  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{reflect.Value{}}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{reflect.Value{}}, "b": reflect.Value{}}},
   797  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{nil}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{nil}, "b": nil}},
   798  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{true}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{true}, "b": true}},
   799  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{int32(1)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int32(1)}, "b": int32(1)}},
   800  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{int64(1)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{int64(1)}, "b": int64(1)}},
   801  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{float32(1.1)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{float32(1.1)}, "b": float32(1.1)}},
   802  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{float64(1.1)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{float64(1.1)}, "b": float64(1.1)}},
   803  
   804  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(reflect.Value{})}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(reflect.Value{})}, "b": interface{}(reflect.Value{})}},
   805  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(nil)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(nil)}, "b": interface{}(nil)}},
   806  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(true)}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(true)}, "b": interface{}(true)}},
   807  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(int32(1))}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(int32(1))}, "b": interface{}(int32(1))}},
   808  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(int64(1))}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(int64(1))}, "b": interface{}(int64(1))}},
   809  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(float32(1.1))}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(float32(1.1))}, "b": interface{}(float32(1.1))}},
   810  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": []interface{}{interface{}(float64(1.1))}}, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{interface{}(float64(1.1))}, "b": interface{}(float64(1.1))}},
   811  
   812  		{Script: `b = 0; for i in a { b = i }`, Input: map[string]interface{}{"a": interface{}([]interface{}{nil})}, RunOutput: nil, Output: map[string]interface{}{"a": interface{}([]interface{}{nil}), "b": nil}},
   813  
   814  		{Script: `for i in nil { }`, RunError: fmt.Errorf("for cannot loop over type interface")},
   815  		{Script: `for i in true { }`, RunError: fmt.Errorf("for cannot loop over type bool")},
   816  		{Script: `for i in a { }`, Input: map[string]interface{}{"a": reflect.Value{}}, RunError: fmt.Errorf("for cannot loop over type struct"), Output: map[string]interface{}{"a": reflect.Value{}}},
   817  		{Script: `for i in a { }`, Input: map[string]interface{}{"a": interface{}(nil)}, RunError: fmt.Errorf("for cannot loop over type interface"), Output: map[string]interface{}{"a": interface{}(nil)}},
   818  		{Script: `for i in a { }`, Input: map[string]interface{}{"a": interface{}(true)}, RunError: fmt.Errorf("for cannot loop over type bool"), Output: map[string]interface{}{"a": interface{}(true)}},
   819  		{Script: `for i in [1, 2, 3] { b++ }`, RunError: fmt.Errorf("undefined symbol 'b'")},
   820  		{Script: `for a = 1; a < 3; a++ { b++ }`, RunError: fmt.Errorf("undefined symbol 'b'")},
   821  		{Script: `for a = b; a < 3; a++ { }`, RunError: fmt.Errorf("undefined symbol 'b'")},
   822  		{Script: `for a = 1; b < 3; a++ { }`, RunError: fmt.Errorf("undefined symbol 'b'")},
   823  		{Script: `for a = 1; a < 3; b++ { }`, RunError: fmt.Errorf("undefined symbol 'b'")},
   824  
   825  		{Script: `a = 1; b = [{"c": "c"}]; for i in b { a = i }`, RunOutput: nil, Output: map[string]interface{}{"a": map[interface{}]interface{}{"c": "c"}, "b": []interface{}{map[interface{}]interface{}{"c": "c"}}}},
   826  		{Script: `a = 1; b = {"x": [{"y": "y"}]};  for i in b.x { a = i }`, RunOutput: nil, Output: map[string]interface{}{"a": map[interface{}]interface{}{"y": "y"}, "b": map[interface{}]interface{}{"x": []interface{}{map[interface{}]interface{}{"y": "y"}}}}},
   827  
   828  		{Script: `a = {}; b = 1; for i in a { b = i }; b`, RunOutput: int64(1), Output: map[string]interface{}{"a": map[interface{}]interface{}{}, "b": int64(1)}},
   829  		{Script: `a = {"x": 2}; b = 1; for i in a { b = i }; b`, RunOutput: "x", Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2)}, "b": "x"}},
   830  		{Script: `a = {"x": 2, "y": 3}; b = 0; for i in a { b++ }; b`, RunOutput: int64(2), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}, "b": int64(2)}},
   831  		{Script: `a = {"x": 2, "y": 3}; for i in a { b++ }`, RunError: fmt.Errorf("undefined symbol 'b'"), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}}},
   832  
   833  		{Script: `a = {"x": 2, "y": 3}; b = 0; for i in a { if i ==  "x" { continue }; b = i }; b`, RunOutput: "y", Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}, "b": "y"}},
   834  		{Script: `a = {"x": 2, "y": 3}; b = 0; for i in a { if i ==  "y" { continue }; b = i }; b`, RunOutput: "x", Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}, "b": "x"}},
   835  		{Script: `a = {"x": 2, "y": 3}; for i in a { if i ==  "x" { return 1 } }`, RunOutput: int64(1), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}}},
   836  		{Script: `a = {"x": 2, "y": 3}; for i in a { if i ==  "y" { return 2 } }`, RunOutput: int64(2), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}}},
   837  		{Script: `a = {"x": 2, "y": 3}; b = 0; for i in a { if i ==  "x" { break }; b++ }; if b > 1 { return false } else { return true }`, RunOutput: true, Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}}},
   838  		{Script: `a = {"x": 2, "y": 3}; b = 0; for i in a { if i ==  "y" { break }; b++ }; if b > 1 { return false } else { return true }`, RunOutput: true, Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}}},
   839  		{Script: `a = {"x": 2, "y": 3}; b = 1; for i in a { if (i ==  "x" || i ==  "y") { break }; b++ }; b`, RunOutput: int64(1), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2), "y": int64(3)}, "b": int64(1)}},
   840  
   841  		{Script: `a = ["123", "456", "789"]; b = ""; for v in a { b += v[len(v) - 2:]; b += v[:len(v) - 2] }`, RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{"123", "456", "789"}, "b": "231564897"}},
   842  		{Script: `a = [[["123"], ["456"]], [["789"]]]; b = ""; for x in a { for y in x  {  for z in y { for i = 0; i < len(z); i++ { b += z[i] + "-" } } } }`,
   843  			RunOutput: nil, Output: map[string]interface{}{"a": []interface{}{[]interface{}{[]interface{}{"123"}, []interface{}{"456"}}, []interface{}{[]interface{}{"789"}}}, "b": "1-2-3-4-5-6-7-8-9-"}},
   844  
   845  		{Script: `a = {"x": 2}; b = 0; for k, v in a { b = k }; b`, RunOutput: "x", Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2)}, "b": "x"}},
   846  		{Script: `a = {"x": 2}; b = 0; for k, v in a { b = v }; b`, RunOutput: int64(2), Output: map[string]interface{}{"a": map[interface{}]interface{}{"x": int64(2)}, "b": int64(2)}},
   847  
   848  		{Script: `a = make(chan int64, 2); a <- 1; v = 0; for val in a { v = val; break; }; v`, RunOutput: int64(1), Output: map[string]interface{}{"v": int64(1)}},
   849  		{Script: `a = make(chan int64, 4); a <- 1; a <- 2; a <- 3; for i in a { if i == 2 { return 2 } }; return 4`, RunOutput: int64(2)},
   850  		{Script: `a = make(chan int64, 2); a <- 1; for i in a { if i < 4 { a <- i + 1; continue }; return 4 }; return 6`, RunOutput: int64(4)},
   851  
   852  		// test non-buffer and go func
   853  		{Script: `a = make(chan int64); go func() { a <- 1; a <- 2; a <- 3 }(); b = []; for i in a { b += i; if i > 2 { break } }`, RunOutput: nil, Output: map[string]interface{}{"b": []interface{}{int64(1), int64(2), int64(3)}}},
   854  		{Script: `a = make(chan int64); go func() { a <- 1; a <- 2; a <- 3; close(a) }(); b = []; for i in a { b += i }`, RunOutput: nil, Output: map[string]interface{}{"b": []interface{}{int64(1), int64(2), int64(3)}}},
   855  	}
   856  	runTests(t, tests, nil, &Options{Debug: true})
   857  }
   858  
   859  func TestItemInList(t *testing.T) {
   860  	t.Parallel()
   861  
   862  	tests := []Test{
   863  		{Script: `"a" in ["a"]`, RunOutput: true},
   864  		{Script: `"a" in ["b"]`, RunOutput: false},
   865  		{Script: `"a" in ["c", "b", "a"]`, RunOutput: true},
   866  		{Script: `"a" in ["a", "b", 1]`, RunOutput: true},
   867  		{Script: `"a" in l`, Input: map[string]interface{}{"l": []interface{}{"a"}}, RunOutput: true},
   868  		{Script: `"a" in l`, Input: map[string]interface{}{"l": []interface{}{"b"}}, RunOutput: false},
   869  		{Script: `"a" in l`, Input: map[string]interface{}{"l": []interface{}{"c", "b", "a"}}, RunOutput: true},
   870  		{Script: `"a" in l`, Input: map[string]interface{}{"l": []interface{}{"a", "b", 1}}, RunOutput: true},
   871  
   872  		{Script: `1 in [1]`, RunOutput: true},
   873  		{Script: `1 in [2]`, RunOutput: false},
   874  		{Script: `1 in [3, 2, 1]`, RunOutput: true},
   875  		{Script: `1 in ["1"]`, RunOutput: true},
   876  		{Script: `1 in l`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   877  		{Script: `"1" in l`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   878  		{Script: `1 in l`, Input: map[string]interface{}{"l": []interface{}{2}}, RunOutput: false},
   879  		{Script: `1 in l`, Input: map[string]interface{}{"l": []interface{}{3, 2, 1}}, RunOutput: true},
   880  		{Script: `1 in l`, Input: map[string]interface{}{"l": []interface{}{"1"}}, RunOutput: true},
   881  
   882  		{Script: `0.9 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   883  		{Script: `1.0 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   884  		{Script: `1.1 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   885  		{Script: `1 in [0.9]`, Input: map[string]interface{}{"l": []interface{}{0.9}}, RunOutput: false},
   886  		{Script: `1 in [1.0]`, Input: map[string]interface{}{"l": []interface{}{1.0}}, RunOutput: true},
   887  		{Script: `1 in [1.1]`, Input: map[string]interface{}{"l": []interface{}{1.1}}, RunOutput: false},
   888  		{Script: `0.9 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   889  		{Script: `1.0 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   890  		{Script: `1.1 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   891  		{Script: `1 in [0.9]`, Input: map[string]interface{}{"l": []interface{}{0.9}}, RunOutput: false},
   892  		{Script: `1 in [1.0]`, Input: map[string]interface{}{"l": []interface{}{1.0}}, RunOutput: true},
   893  		{Script: `1 in [1.1]`, Input: map[string]interface{}{"l": []interface{}{1.1}}, RunOutput: false},
   894  
   895  		{Script: `true in ["true"]`, RunOutput: true},
   896  		{Script: `true in [true]`, RunOutput: true},
   897  		{Script: `true in [true, false]`, RunOutput: true},
   898  		{Script: `false in [false, true]`, RunOutput: true},
   899  		{Script: `true in l`, Input: map[string]interface{}{"l": []interface{}{"true"}}, RunOutput: true},
   900  		{Script: `true in l`, Input: map[string]interface{}{"l": []interface{}{true}}, RunOutput: true},
   901  		{Script: `true in l`, Input: map[string]interface{}{"l": []interface{}{true, false}}, RunOutput: true},
   902  		{Script: `false in l`, Input: map[string]interface{}{"l": []interface{}{false, true}}, RunOutput: true},
   903  
   904  		{Script: `"a" in ["b", "a", "c"][1:]`, RunOutput: true},
   905  		{Script: `"a" in ["b", "a", "c"][:1]`, RunOutput: false},
   906  		{Script: `"a" in ["b", "a", "c"][1:2]`, RunOutput: true},
   907  		{Script: `l = ["b", "a", "c"];"a" in l[1:]`, RunOutput: true},
   908  		{Script: `l = ["b", "a", "c"];"a" in l[:1]`, RunOutput: false},
   909  		{Script: `l = ["b", "a", "c"];"a" in l[1:2]`, RunOutput: true},
   910  		{Script: `"a" in l[1:]`, Input: map[string]interface{}{"l": []interface{}{"b", "a", "c"}}, RunOutput: true},
   911  		{Script: `"a" in l[:1]`, Input: map[string]interface{}{"l": []interface{}{"b", "a", "c"}}, RunOutput: false},
   912  		{Script: `"a" in l[1:2]`, Input: map[string]interface{}{"l": []interface{}{"b", "a", "c"}}, RunOutput: true},
   913  
   914  		// for i in list && item in list
   915  		{Script: `list_of_list = [["a"]];for l in list_of_list { return "a" in l }`, RunOutput: true},
   916  		{Script: `for l in list_of_list { return "a" in l }`, Input: map[string]interface{}{"list_of_list": []interface{}{[]interface{}{"a"}}}, RunOutput: true},
   917  
   918  		// not slice or array
   919  		// todo: support `"a" in "aaa"` ?
   920  		{Script: `"a" in "aaa"`, RunError: fmt.Errorf("second argument must be slice or array; but have string")},
   921  		{Script: `1 in 12345`, RunError: fmt.Errorf("second argument must be slice or array; but have int64")},
   922  
   923  		// a in item in list
   924  		{Script: `"a" in 5 in [1, 2, 3]`, RunError: fmt.Errorf("second argument must be slice or array; but have bool")},
   925  
   926  		// applying a in b in several part of expresstion/statement
   927  		{Script: `switch 1 in [1] {case true: return true;default: return false}`, RunOutput: true},
   928  		{Script: `switch 1 in [2,3] {case true: return true;default: return false}`, RunOutput: false},
   929  		{Script: `switch true {case 1 in [1]: return true;default: return false}`, RunOutput: true},
   930  		{Script: `switch false {case 1 in [1]: return true;default: return false}`, RunOutput: false},
   931  		{Script: `if 1 in [1] {return true} else {return false}`, RunOutput: true},
   932  		{Script: `if 1 in [2,3] {return true} else {return false}`, RunOutput: false},
   933  		{Script: `for i in [1,2,3] { i++ }`},
   934  		{Script: `a=1; a=a in [1]`, RunOutput: true},
   935  		{Script: `a=1; a=a in [2,3]`, RunOutput: false},
   936  		{Script: `1 in [1] && true`, RunOutput: true},
   937  		{Script: `1 in [1] && false`, RunOutput: false},
   938  		{Script: `1 in [1] || true`, RunOutput: true},
   939  		{Script: `1 in [1] || false`, RunOutput: true},
   940  		{Script: `1 in [2,3] && true`, RunOutput: false},
   941  		{Script: `1 in [2,3] && false`, RunOutput: false},
   942  		{Script: `1 in [2,3] || true`, RunOutput: true},
   943  		{Script: `1 in [2,3] || false`, RunOutput: false},
   944  		{Script: `1++ in [1, 2, 3]`, RunError: fmt.Errorf("invalid operation")},
   945  		{Script: `3++ in [1, 2, 3]`, RunError: fmt.Errorf("invalid operation")},
   946  		{Script: `1 in 1++`, RunError: fmt.Errorf("invalid operation")},
   947  		{Script: `a=1;a++ in [1, 2, 3]`, RunOutput: true},
   948  		{Script: `a=3;a++ in [1, 2, 3]`, RunOutput: false},
   949  		{Script: `switch 1 in l {case true: return true;default: return false}`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   950  		{Script: `switch 1 in l {case true: return true;default: return false}`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   951  		{Script: `switch true {case 1 in l: return true;default: return false}`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   952  		{Script: `switch false {case 1 in l: return true;default: return false}`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   953  		{Script: `if 1 in l {return true} else {return false}`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   954  		{Script: `if 1 in l {return true} else {return false}`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   955  		{Script: `for i in l { i++ }`, Input: map[string]interface{}{"l": []interface{}{1, 2, 3}}},
   956  		{Script: `a=1; a=a in l`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   957  		{Script: `a=1; a=a in l`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   958  		{Script: `1 in l && true`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   959  		{Script: `1 in l && false`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   960  		{Script: `1 in l || true`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   961  		{Script: `1 in l || false`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   962  		{Script: `1 in l && true`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   963  		{Script: `1 in l && false`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   964  		{Script: `1 in l || true`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: true},
   965  		{Script: `1 in l || false`, Input: map[string]interface{}{"l": []interface{}{2, 3}}, RunOutput: false},
   966  		{Script: `1++ in l`, Input: map[string]interface{}{"l": []interface{}{1, 2, 3}}, RunError: fmt.Errorf("invalid operation")},
   967  		{Script: `3++ in l`, Input: map[string]interface{}{"l": []interface{}{1, 2, 3}}, RunError: fmt.Errorf("invalid operation")},
   968  		{Script: `a=1;a++ in l`, Input: map[string]interface{}{"l": []interface{}{1, 2, 3}}, RunOutput: true},
   969  		{Script: `a=3;a++ in l`, Input: map[string]interface{}{"l": []interface{}{1, 2, 3}}, RunOutput: false},
   970  
   971  		// multidimensional slice
   972  		{Script: `1 in [1]`, RunOutput: true},
   973  		{Script: `1 in [[1]]`, RunOutput: false},
   974  		{Script: `1 in [[[1]]]`, RunOutput: false},
   975  		{Script: `1 in [[1],[[1]],1]`, RunOutput: true},
   976  		{Script: `[1] in [1]`, RunOutput: false},
   977  		{Script: `[1] in [[1]]`, RunOutput: true},
   978  		{Script: `[1] in [[[1]]]`, RunOutput: false},
   979  		{Script: `[[1]] in [1]`, RunOutput: false},
   980  		{Script: `[[1]] in [[1]]`, RunOutput: false},
   981  		{Script: `[[1]] in [[[1]]]`, RunOutput: true},
   982  		{Script: `1 in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: true},
   983  		{Script: `1 in [[1]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{1}}}, RunOutput: false},
   984  		{Script: `1 in [[[1]]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{[]interface{}{1}}}}, RunOutput: false},
   985  		{Script: `1 in [[1],[[1]],1]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{1}, []interface{}{[]interface{}{1}}, 1}}, RunOutput: true},
   986  		{Script: `[1] in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   987  		{Script: `[1] in [[1]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{1}}}, RunOutput: true},
   988  		{Script: `[1] in [[[1]]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{[]interface{}{1}}}}, RunOutput: false},
   989  		{Script: `[[1]] in [1]`, Input: map[string]interface{}{"l": []interface{}{1}}, RunOutput: false},
   990  		{Script: `[[1]] in [[1]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{1}}}, RunOutput: false},
   991  		{Script: `[[1]] in [[[1]]]`, Input: map[string]interface{}{"l": []interface{}{[]interface{}{[]interface{}{1}}}}, RunOutput: true},
   992  	}
   993  	runTests(t, tests, nil, &Options{Debug: true})
   994  }
   995  
   996  func TestOperatorPrecedence(t *testing.T) {
   997  	t.Parallel()
   998  
   999  	tests := []Test{
  1000  		// test && > ||
  1001  		{Script: `true || true && false`, RunOutput: true},
  1002  		{Script: `(true || true) && false`, RunOutput: false},
  1003  		{Script: `false && true || true`, RunOutput: true},
  1004  		{Script: `false && (true || true)`, RunOutput: false},
  1005  
  1006  		// test == > ||
  1007  		{Script: `0 == 1 || 1 == 1`, RunOutput: true},
  1008  		{Script: `0 == (1 || 1) == 1`, RunOutput: false},
  1009  
  1010  		// test + > ==
  1011  		{Script: `1 + 2 == 2 + 1`, RunOutput: true},
  1012  		{Script: `1 + (2 == 2) + 1`, RunOutput: int64(3)},
  1013  
  1014  		// test * > +
  1015  		{Script: `2 * 3 + 4 * 5`, RunOutput: int64(26)},
  1016  		{Script: `2 * (3 + 4) * 5`, RunOutput: int64(70)},
  1017  
  1018  		// test * > &&
  1019  		{Script: `2 * 0 && 3 * 4`, RunOutput: false},
  1020  		{Script: `2 * (0 && 3) * 4`, RunOutput: int64(0)},
  1021  
  1022  		// test ++ > *
  1023  		{Script: `a = 1; b = 2; a++ * b++`, RunOutput: int64(6)},
  1024  
  1025  		// test ++ > *
  1026  		{Script: `a = 1; b = 2; a++ * b++`, RunOutput: int64(6)},
  1027  
  1028  		// test unary - > +
  1029  		{Script: `a = 1; b = 2; -a + b`, RunOutput: int64(1)},
  1030  		{Script: `a = 1; b = 2; -(a + b)`, RunOutput: int64(-3)},
  1031  		{Script: `a = 1; b = 2; a + -b`, RunOutput: int64(-1)},
  1032  
  1033  		// test ! > ||
  1034  		{Script: `!true || true`, RunOutput: true},
  1035  		{Script: `!(true || true)`, RunOutput: false},
  1036  	}
  1037  	runTests(t, tests, nil, &Options{Debug: true})
  1038  }
  1039  
  1040  func TestTry(t *testing.T) {
  1041  	t.Parallel()
  1042  
  1043  	tests := []Test{
  1044  		{Script: `try { 1++ } catch { 1++ }`, RunError: fmt.Errorf("invalid operation")},
  1045  		{Script: `try { 1++ } catch a { return a }`, RunOutput: fmt.Errorf("invalid operation")},
  1046  		{Script: `try { 1++ } catch a { a = 2 }; return a`, RunError: fmt.Errorf("undefined symbol 'a'")},
  1047  
  1048  		// test finally
  1049  		{Script: `try { 1++ } catch { 1++ } finally { return 1 }`, RunError: fmt.Errorf("invalid operation")},
  1050  		{Script: `try { } catch { } finally { 1++ }`, RunError: fmt.Errorf("invalid operation")},
  1051  		{Script: `try { } catch { 1 } finally { 1++ }`, RunError: fmt.Errorf("invalid operation")},
  1052  		{Script: `try { 1++ } catch { } finally { 1++ }`, RunError: fmt.Errorf("invalid operation")},
  1053  		{Script: `try { 1++ } catch a { } finally { return a }`, RunOutput: fmt.Errorf("invalid operation")},
  1054  		{Script: `try { 1++ } catch a { } finally { a = 2 }; return a`, RunError: fmt.Errorf("undefined symbol 'a'")},
  1055  
  1056  		{Script: `try { } catch { }`, RunOutput: nil},
  1057  		{Script: `try { 1++ } catch { }`, RunOutput: nil},
  1058  		{Script: `try { } catch { 1++ }`, RunOutput: nil},
  1059  		{Script: `try { return 1 } catch { }`, RunOutput: int64(1)},
  1060  		{Script: `try { return 1 } catch { return 2 }`, RunOutput: int64(2)},
  1061  		{Script: `try { 1++ } catch { return 1 }`, RunOutput: int64(1)},
  1062  
  1063  		// test finally
  1064  		{Script: `try { } catch { } finally { return 1 }`, RunOutput: int64(1)},
  1065  		{Script: `try { 1++ } catch { } finally { return 1 }`, RunOutput: int64(1)},
  1066  		{Script: `try { 1++ } catch { return 1 } finally { 1++ }`, RunOutput: int64(1)},
  1067  
  1068  		// test variable scope
  1069  		{Script: `try { 1++ } catch a { if a.Error() == "invalid operation" { return 1 } else { return 2 } }`, RunOutput: int64(1)},
  1070  		{Script: `try { 1++ } catch a { } finally { if a.Error() == "invalid operation" { return 1 } else { return 2 } }`, RunOutput: int64(1)},
  1071  	}
  1072  	runTests(t, tests, nil, &Options{Debug: true})
  1073  }