summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/d5/tengo
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/d5/tengo')
-rw-r--r--vendor/github.com/d5/tengo/.travis.yml17
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/array_lit.go35
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go40
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/ast.go5
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/bad_expr.go25
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go25
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/binary_expr.go30
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/block_stmt.go35
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/bool_lit.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go38
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/call_expr.go36
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/char_lit.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/cond_expr.go30
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/error_expr.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/export_stmt.go27
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/expr.go7
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go24
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/float_lit.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go32
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/for_stmt.go43
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/func_lit.go25
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/func_type.go25
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/ident.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/if_stmt.go40
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/import_expr.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/index_expr.go32
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/int_lit.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go27
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/map_lit.go35
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/node.go13
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/paren_expr.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/return_stmt.go35
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/selector_expr.go25
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/slice_expr.go36
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/stmt.go7
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/string_lit.go26
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/unary_expr.go29
-rw-r--r--vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go24
-rw-r--r--vendor/github.com/d5/tengo/compiler/bytecode.go90
-rw-r--r--vendor/github.com/d5/tengo/compiler/bytecode_decode.go97
-rw-r--r--vendor/github.com/d5/tengo/compiler/bytecode_optimize.go129
-rw-r--r--vendor/github.com/d5/tengo/compiler/compilation_scope.go11
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler.go846
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_assign.go133
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_for.go181
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_logical.go30
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_loops.go31
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_module.go79
-rw-r--r--vendor/github.com/d5/tengo/compiler/compiler_scopes.go43
-rw-r--r--vendor/github.com/d5/tengo/compiler/emitted_instruction.go8
-rw-r--r--vendor/github.com/d5/tengo/compiler/error.go20
-rw-r--r--vendor/github.com/d5/tengo/compiler/instructions.go72
-rw-r--r--vendor/github.com/d5/tengo/compiler/loop.go8
-rw-r--r--vendor/github.com/d5/tengo/compiler/module_loader.go4
-rw-r--r--vendor/github.com/d5/tengo/compiler/parser/error.go21
-rw-r--r--vendor/github.com/d5/tengo/compiler/parser/error_list.go68
-rw-r--r--vendor/github.com/d5/tengo/compiler/parser/parse_source.go17
-rw-r--r--vendor/github.com/d5/tengo/compiler/parser/sync.go12
-rw-r--r--vendor/github.com/d5/tengo/compiler/scanner/error_handler.go6
-rw-r--r--vendor/github.com/d5/tengo/compiler/scanner/mode.go10
-rw-r--r--vendor/github.com/d5/tengo/compiler/source/file.go110
-rw-r--r--vendor/github.com/d5/tengo/compiler/source/file_pos.go47
-rw-r--r--vendor/github.com/d5/tengo/compiler/source/file_set.go96
-rw-r--r--vendor/github.com/d5/tengo/compiler/symbol.go9
-rw-r--r--vendor/github.com/d5/tengo/compiler/symbol_scopes.go12
-rw-r--r--vendor/github.com/d5/tengo/compiler/token/keywords.go19
-rw-r--r--vendor/github.com/d5/tengo/go.mod3
-rw-r--r--vendor/github.com/d5/tengo/objects/array.go130
-rw-r--r--vendor/github.com/d5/tengo/objects/array_iterator.go57
-rw-r--r--vendor/github.com/d5/tengo/objects/bool.go64
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_append.go21
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_convert.go169
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_copy.go9
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_format.go27
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_function.go47
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_len.go29
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_module.go23
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_type.go9
-rw-r--r--vendor/github.com/d5/tengo/objects/builtin_type_checks.go195
-rw-r--r--vendor/github.com/d5/tengo/objects/builtins.go118
-rw-r--r--vendor/github.com/d5/tengo/objects/bytes.go89
-rw-r--r--vendor/github.com/d5/tengo/objects/bytes_iterator.go57
-rw-r--r--vendor/github.com/d5/tengo/objects/callable.go9
-rw-r--r--vendor/github.com/d5/tengo/objects/callable_func.go4
-rw-r--r--vendor/github.com/d5/tengo/objects/char.go119
-rw-r--r--vendor/github.com/d5/tengo/objects/closure.go45
-rw-r--r--vendor/github.com/d5/tengo/objects/compiled_function.go62
-rw-r--r--vendor/github.com/d5/tengo/objects/count_objects.go31
-rw-r--r--vendor/github.com/d5/tengo/objects/error.go47
-rw-r--r--vendor/github.com/d5/tengo/objects/errors.go38
-rw-r--r--vendor/github.com/d5/tengo/objects/float.go146
-rw-r--r--vendor/github.com/d5/tengo/objects/immutable_array.go109
-rw-r--r--vendor/github.com/d5/tengo/objects/immutable_map.go105
-rw-r--r--vendor/github.com/d5/tengo/objects/importable.go7
-rw-r--r--vendor/github.com/d5/tengo/objects/index_assignable.go9
-rw-r--r--vendor/github.com/d5/tengo/objects/indexable.go9
-rw-r--r--vendor/github.com/d5/tengo/objects/int.go198
-rw-r--r--vendor/github.com/d5/tengo/objects/iterable.go7
-rw-r--r--vendor/github.com/d5/tengo/objects/iterator.go15
-rw-r--r--vendor/github.com/d5/tengo/objects/map.go118
-rw-r--r--vendor/github.com/d5/tengo/objects/map_iterator.go62
-rw-r--r--vendor/github.com/d5/tengo/objects/object.go30
-rw-r--r--vendor/github.com/d5/tengo/objects/object_ptr.go41
-rw-r--r--vendor/github.com/d5/tengo/objects/objects.go12
-rw-r--r--vendor/github.com/d5/tengo/objects/source_module.go11
-rw-r--r--vendor/github.com/d5/tengo/objects/string.go103
-rw-r--r--vendor/github.com/d5/tengo/objects/string_iterator.go57
-rw-r--r--vendor/github.com/d5/tengo/objects/time.go89
-rw-r--r--vendor/github.com/d5/tengo/objects/undefined.go62
-rw-r--r--vendor/github.com/d5/tengo/objects/user_function.go48
-rw-r--r--vendor/github.com/d5/tengo/runtime/errors.go11
-rw-r--r--vendor/github.com/d5/tengo/runtime/frame.go13
-rw-r--r--vendor/github.com/d5/tengo/script/compiled.go159
-rw-r--r--vendor/github.com/d5/tengo/script/script.go185
-rw-r--r--vendor/github.com/d5/tengo/stdlib/base64.go20
-rw-r--r--vendor/github.com/d5/tengo/stdlib/builtin_modules.go16
-rw-r--r--vendor/github.com/d5/tengo/stdlib/errors.go11
-rw-r--r--vendor/github.com/d5/tengo/stdlib/fmt.go110
-rw-r--r--vendor/github.com/d5/tengo/stdlib/func_typedefs.go1178
-rw-r--r--vendor/github.com/d5/tengo/stdlib/hex.go11
-rw-r--r--vendor/github.com/d5/tengo/stdlib/json.go126
-rw-r--r--vendor/github.com/d5/tengo/stdlib/math.go74
-rw-r--r--vendor/github.com/d5/tengo/stdlib/os.go492
-rw-r--r--vendor/github.com/d5/tengo/stdlib/os_exec.go113
-rw-r--r--vendor/github.com/d5/tengo/stdlib/os_file.go96
-rw-r--r--vendor/github.com/d5/tengo/stdlib/os_process.go62
-rw-r--r--vendor/github.com/d5/tengo/stdlib/rand.go102
-rw-r--r--vendor/github.com/d5/tengo/stdlib/text.go930
-rw-r--r--vendor/github.com/d5/tengo/stdlib/times.go989
-rw-r--r--vendor/github.com/d5/tengo/tengo.go11
-rw-r--r--vendor/github.com/d5/tengo/v2/.gitignore (renamed from vendor/github.com/d5/tengo/.gitignore)0
-rw-r--r--vendor/github.com/d5/tengo/v2/.goreleaser.yml (renamed from vendor/github.com/d5/tengo/.goreleaser.yml)9
-rw-r--r--vendor/github.com/d5/tengo/v2/LICENSE (renamed from vendor/github.com/d5/tengo/LICENSE)0
-rw-r--r--vendor/github.com/d5/tengo/v2/Makefile (renamed from vendor/github.com/d5/tengo/Makefile)5
-rw-r--r--vendor/github.com/d5/tengo/v2/README.md (renamed from vendor/github.com/d5/tengo/README.md)86
-rw-r--r--vendor/github.com/d5/tengo/v2/builtins.go502
-rw-r--r--vendor/github.com/d5/tengo/v2/bytecode.go292
-rw-r--r--vendor/github.com/d5/tengo/v2/compiler.go1312
-rw-r--r--vendor/github.com/d5/tengo/v2/doc.go3
-rw-r--r--vendor/github.com/d5/tengo/v2/errors.go64
-rw-r--r--vendor/github.com/d5/tengo/v2/formatter.go (renamed from vendor/github.com/d5/tengo/objects/formatter.go)147
-rw-r--r--vendor/github.com/d5/tengo/v2/go.mod3
-rw-r--r--vendor/github.com/d5/tengo/v2/go.sum (renamed from vendor/github.com/d5/tengo/go.sum)0
-rw-r--r--vendor/github.com/d5/tengo/v2/instructions.go61
-rw-r--r--vendor/github.com/d5/tengo/v2/iterator.go209
-rw-r--r--vendor/github.com/d5/tengo/v2/modules.go (renamed from vendor/github.com/d5/tengo/objects/module_map.go)34
-rw-r--r--vendor/github.com/d5/tengo/v2/objects.go1581
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/ast.go (renamed from vendor/github.com/d5/tengo/compiler/ast/ident_list.go)34
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/expr.go597
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/file.go (renamed from vendor/github.com/d5/tengo/compiler/ast/file.go)15
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/opcodes.go (renamed from vendor/github.com/d5/tengo/compiler/opcodes.go)11
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/parser.go (renamed from vendor/github.com/d5/tengo/compiler/parser/parser.go)516
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/pos.go (renamed from vendor/github.com/d5/tengo/compiler/source/pos.go)2
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/scanner.go (renamed from vendor/github.com/d5/tengo/compiler/scanner/scanner.go)139
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/source_file.go231
-rw-r--r--vendor/github.com/d5/tengo/v2/parser/stmt.go349
-rw-r--r--vendor/github.com/d5/tengo/v2/script.go313
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/base64.go34
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/builtin_modules.go18
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/errors.go12
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/fmt.go101
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/func_typedefs.go1049
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/hex.go12
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/json.go146
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/json/decode.go (renamed from vendor/github.com/d5/tengo/stdlib/json/decode.go)54
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/json/encode.go (renamed from vendor/github.com/d5/tengo/stdlib/json/encode.go)29
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/json/scanner.go (renamed from vendor/github.com/d5/tengo/stdlib/json/scanner.go)7
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/math.go233
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/os.go564
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/os_exec.go119
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/os_file.go117
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/os_process.go76
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/rand.go138
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/source_modules.go (renamed from vendor/github.com/d5/tengo/stdlib/source_modules.go)0
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/srcmod_enum.tengo (renamed from vendor/github.com/d5/tengo/stdlib/srcmod_enum.tengo)0
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/stdlib.go (renamed from vendor/github.com/d5/tengo/stdlib/stdlib.go)10
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/text.go1072
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/text_regexp.go (renamed from vendor/github.com/d5/tengo/stdlib/text_regexp.go)141
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/times.go1135
-rw-r--r--vendor/github.com/d5/tengo/v2/symbol_table.go (renamed from vendor/github.com/d5/tengo/compiler/symbol_table.go)46
-rw-r--r--vendor/github.com/d5/tengo/v2/tengo.go (renamed from vendor/github.com/d5/tengo/objects/conversion.go)80
-rw-r--r--vendor/github.com/d5/tengo/v2/token/token.go (renamed from vendor/github.com/d5/tengo/compiler/token/tokens.go)17
-rw-r--r--vendor/github.com/d5/tengo/v2/variable.go (renamed from vendor/github.com/d5/tengo/script/variable.go)89
-rw-r--r--vendor/github.com/d5/tengo/v2/vm.go (renamed from vendor/github.com/d5/tengo/runtime/vm.go)695
187 files changed, 11390 insertions, 11809 deletions
diff --git a/vendor/github.com/d5/tengo/.travis.yml b/vendor/github.com/d5/tengo/.travis.yml
deleted file mode 100644
index 57986ae9..00000000
--- a/vendor/github.com/d5/tengo/.travis.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-language: go
-
-go:
- - "1.12"
-
-install:
- - env GO111MODULE=on go get -u golang.org/x/lint/golint
-
-script:
- - env GO111MODULE=on make test
-
-deploy:
- - provider: script
- skip_cleanup: true
- script: curl -sL https://git.io/goreleaser | bash
- on:
- tags: true \ No newline at end of file
diff --git a/vendor/github.com/d5/tengo/compiler/ast/array_lit.go b/vendor/github.com/d5/tengo/compiler/ast/array_lit.go
deleted file mode 100644
index 9fb4ed67..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/array_lit.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package ast
-
-import (
- "strings"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// ArrayLit represents an array literal.
-type ArrayLit struct {
- Elements []Expr
- LBrack source.Pos
- RBrack source.Pos
-}
-
-func (e *ArrayLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *ArrayLit) Pos() source.Pos {
- return e.LBrack
-}
-
-// End returns the position of first character immediately after the node.
-func (e *ArrayLit) End() source.Pos {
- return e.RBrack + 1
-}
-
-func (e *ArrayLit) String() string {
- var elements []string
- for _, m := range e.Elements {
- elements = append(elements, m.String())
- }
-
- return "[" + strings.Join(elements, ", ") + "]"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go
deleted file mode 100644
index e129114e..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package ast
-
-import (
- "strings"
-
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// AssignStmt represents an assignment statement.
-type AssignStmt struct {
- LHS []Expr
- RHS []Expr
- Token token.Token
- TokenPos source.Pos
-}
-
-func (s *AssignStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *AssignStmt) Pos() source.Pos {
- return s.LHS[0].Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (s *AssignStmt) End() source.Pos {
- return s.RHS[len(s.RHS)-1].End()
-}
-
-func (s *AssignStmt) String() string {
- var lhs, rhs []string
- for _, e := range s.LHS {
- lhs = append(lhs, e.String())
- }
- for _, e := range s.RHS {
- rhs = append(rhs, e.String())
- }
-
- return strings.Join(lhs, ", ") + " " + s.Token.String() + " " + strings.Join(rhs, ", ")
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/ast.go b/vendor/github.com/d5/tengo/compiler/ast/ast.go
deleted file mode 100644
index 9fd06728..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/ast.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package ast
-
-const (
- nullRep = "<null>"
-)
diff --git a/vendor/github.com/d5/tengo/compiler/ast/bad_expr.go b/vendor/github.com/d5/tengo/compiler/ast/bad_expr.go
deleted file mode 100644
index 771f26fd..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/bad_expr.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// BadExpr represents a bad expression.
-type BadExpr struct {
- From source.Pos
- To source.Pos
-}
-
-func (e *BadExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *BadExpr) Pos() source.Pos {
- return e.From
-}
-
-// End returns the position of first character immediately after the node.
-func (e *BadExpr) End() source.Pos {
- return e.To
-}
-
-func (e *BadExpr) String() string {
- return "<bad expression>"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go
deleted file mode 100644
index c2d0ae9a..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// BadStmt represents a bad statement.
-type BadStmt struct {
- From source.Pos
- To source.Pos
-}
-
-func (s *BadStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *BadStmt) Pos() source.Pos {
- return s.From
-}
-
-// End returns the position of first character immediately after the node.
-func (s *BadStmt) End() source.Pos {
- return s.To
-}
-
-func (s *BadStmt) String() string {
- return "<bad statement>"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/binary_expr.go b/vendor/github.com/d5/tengo/compiler/ast/binary_expr.go
deleted file mode 100644
index 0cc5bba8..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/binary_expr.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// BinaryExpr represents a binary operator expression.
-type BinaryExpr struct {
- LHS Expr
- RHS Expr
- Token token.Token
- TokenPos source.Pos
-}
-
-func (e *BinaryExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *BinaryExpr) Pos() source.Pos {
- return e.LHS.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *BinaryExpr) End() source.Pos {
- return e.RHS.End()
-}
-
-func (e *BinaryExpr) String() string {
- return "(" + e.LHS.String() + " " + e.Token.String() + " " + e.RHS.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/block_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/block_stmt.go
deleted file mode 100644
index 9bde9fa3..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/block_stmt.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package ast
-
-import (
- "strings"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// BlockStmt represents a block statement.
-type BlockStmt struct {
- Stmts []Stmt
- LBrace source.Pos
- RBrace source.Pos
-}
-
-func (s *BlockStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *BlockStmt) Pos() source.Pos {
- return s.LBrace
-}
-
-// End returns the position of first character immediately after the node.
-func (s *BlockStmt) End() source.Pos {
- return s.RBrace + 1
-}
-
-func (s *BlockStmt) String() string {
- var list []string
- for _, e := range s.Stmts {
- list = append(list, e.String())
- }
-
- return "{" + strings.Join(list, "; ") + "}"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/bool_lit.go b/vendor/github.com/d5/tengo/compiler/ast/bool_lit.go
deleted file mode 100644
index e667a5c8..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/bool_lit.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// BoolLit represents a boolean literal.
-type BoolLit struct {
- Value bool
- ValuePos source.Pos
- Literal string
-}
-
-func (e *BoolLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *BoolLit) Pos() source.Pos {
- return e.ValuePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *BoolLit) End() source.Pos {
- return source.Pos(int(e.ValuePos) + len(e.Literal))
-}
-
-func (e *BoolLit) String() string {
- return e.Literal
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go
deleted file mode 100644
index f6c7fdea..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// BranchStmt represents a branch statement.
-type BranchStmt struct {
- Token token.Token
- TokenPos source.Pos
- Label *Ident
-}
-
-func (s *BranchStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *BranchStmt) Pos() source.Pos {
- return s.TokenPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *BranchStmt) End() source.Pos {
- if s.Label != nil {
- return s.Label.End()
- }
-
- return source.Pos(int(s.TokenPos) + len(s.Token.String()))
-}
-
-func (s *BranchStmt) String() string {
- var label string
- if s.Label != nil {
- label = " " + s.Label.Name
- }
-
- return s.Token.String() + label
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/call_expr.go b/vendor/github.com/d5/tengo/compiler/ast/call_expr.go
deleted file mode 100644
index 0219d7c9..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/call_expr.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ast
-
-import (
- "strings"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// CallExpr represents a function call expression.
-type CallExpr struct {
- Func Expr
- LParen source.Pos
- Args []Expr
- RParen source.Pos
-}
-
-func (e *CallExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *CallExpr) Pos() source.Pos {
- return e.Func.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *CallExpr) End() source.Pos {
- return e.RParen + 1
-}
-
-func (e *CallExpr) String() string {
- var args []string
- for _, e := range e.Args {
- args = append(args, e.String())
- }
-
- return e.Func.String() + "(" + strings.Join(args, ", ") + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/char_lit.go b/vendor/github.com/d5/tengo/compiler/ast/char_lit.go
deleted file mode 100644
index 592f8744..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/char_lit.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// CharLit represents a character literal.
-type CharLit struct {
- Value rune
- ValuePos source.Pos
- Literal string
-}
-
-func (e *CharLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *CharLit) Pos() source.Pos {
- return e.ValuePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *CharLit) End() source.Pos {
- return source.Pos(int(e.ValuePos) + len(e.Literal))
-}
-
-func (e *CharLit) String() string {
- return e.Literal
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/cond_expr.go b/vendor/github.com/d5/tengo/compiler/ast/cond_expr.go
deleted file mode 100644
index bb1db849..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/cond_expr.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
-)
-
-// CondExpr represents a ternary conditional expression.
-type CondExpr struct {
- Cond Expr
- True Expr
- False Expr
- QuestionPos source.Pos
- ColonPos source.Pos
-}
-
-func (e *CondExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *CondExpr) Pos() source.Pos {
- return e.Cond.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *CondExpr) End() source.Pos {
- return e.False.End()
-}
-
-func (e *CondExpr) String() string {
- return "(" + e.Cond.String() + " ? " + e.True.String() + " : " + e.False.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go
deleted file mode 100644
index a2ac6ffe..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// EmptyStmt represents an empty statement.
-type EmptyStmt struct {
- Semicolon source.Pos
- Implicit bool
-}
-
-func (s *EmptyStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *EmptyStmt) Pos() source.Pos {
- return s.Semicolon
-}
-
-// End returns the position of first character immediately after the node.
-func (s *EmptyStmt) End() source.Pos {
- if s.Implicit {
- return s.Semicolon
- }
-
- return s.Semicolon + 1
-}
-
-func (s *EmptyStmt) String() string {
- return ";"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/error_expr.go b/vendor/github.com/d5/tengo/compiler/ast/error_expr.go
deleted file mode 100644
index 7ce5667e..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/error_expr.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
-)
-
-// ErrorExpr represents an error expression
-type ErrorExpr struct {
- Expr Expr
- ErrorPos source.Pos
- LParen source.Pos
- RParen source.Pos
-}
-
-func (e *ErrorExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *ErrorExpr) Pos() source.Pos {
- return e.ErrorPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *ErrorExpr) End() source.Pos {
- return e.RParen
-}
-
-func (e *ErrorExpr) String() string {
- return "error(" + e.Expr.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/export_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/export_stmt.go
deleted file mode 100644
index 64eb7606..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/export_stmt.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
-)
-
-// ExportStmt represents an export statement.
-type ExportStmt struct {
- ExportPos source.Pos
- Result Expr
-}
-
-func (s *ExportStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *ExportStmt) Pos() source.Pos {
- return s.ExportPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *ExportStmt) End() source.Pos {
- return s.Result.End()
-}
-
-func (s *ExportStmt) String() string {
- return "export " + s.Result.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/expr.go b/vendor/github.com/d5/tengo/compiler/ast/expr.go
deleted file mode 100644
index 764bacec..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/expr.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package ast
-
-// Expr represents an expression node in the AST.
-type Expr interface {
- Node
- exprNode()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go
deleted file mode 100644
index 095a3ad5..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// ExprStmt represents an expression statement.
-type ExprStmt struct {
- Expr Expr
-}
-
-func (s *ExprStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *ExprStmt) Pos() source.Pos {
- return s.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (s *ExprStmt) End() source.Pos {
- return s.Expr.End()
-}
-
-func (s *ExprStmt) String() string {
- return s.Expr.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/float_lit.go b/vendor/github.com/d5/tengo/compiler/ast/float_lit.go
deleted file mode 100644
index 670f744b..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/float_lit.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// FloatLit represents a floating point literal.
-type FloatLit struct {
- Value float64
- ValuePos source.Pos
- Literal string
-}
-
-func (e *FloatLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *FloatLit) Pos() source.Pos {
- return e.ValuePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *FloatLit) End() source.Pos {
- return source.Pos(int(e.ValuePos) + len(e.Literal))
-}
-
-func (e *FloatLit) String() string {
- return e.Literal
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go
deleted file mode 100644
index 18020b56..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// ForInStmt represents a for-in statement.
-type ForInStmt struct {
- ForPos source.Pos
- Key *Ident
- Value *Ident
- Iterable Expr
- Body *BlockStmt
-}
-
-func (s *ForInStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *ForInStmt) Pos() source.Pos {
- return s.ForPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *ForInStmt) End() source.Pos {
- return s.Body.End()
-}
-
-func (s *ForInStmt) String() string {
- if s.Value != nil {
- return "for " + s.Key.String() + ", " + s.Value.String() + " in " + s.Iterable.String() + " " + s.Body.String()
- }
-
- return "for " + s.Key.String() + " in " + s.Iterable.String() + " " + s.Body.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/for_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/for_stmt.go
deleted file mode 100644
index 4b5a0a17..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/for_stmt.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// ForStmt represents a for statement.
-type ForStmt struct {
- ForPos source.Pos
- Init Stmt
- Cond Expr
- Post Stmt
- Body *BlockStmt
-}
-
-func (s *ForStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *ForStmt) Pos() source.Pos {
- return s.ForPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *ForStmt) End() source.Pos {
- return s.Body.End()
-}
-
-func (s *ForStmt) String() string {
- var init, cond, post string
- if s.Init != nil {
- init = s.Init.String()
- }
- if s.Cond != nil {
- cond = s.Cond.String() + " "
- }
- if s.Post != nil {
- post = s.Post.String()
- }
-
- if init != "" || post != "" {
- return "for " + init + " ; " + cond + " ; " + post + s.Body.String()
- }
-
- return "for " + cond + s.Body.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/func_lit.go b/vendor/github.com/d5/tengo/compiler/ast/func_lit.go
deleted file mode 100644
index 2e90ed2b..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/func_lit.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// FuncLit represents a function literal.
-type FuncLit struct {
- Type *FuncType
- Body *BlockStmt
-}
-
-func (e *FuncLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *FuncLit) Pos() source.Pos {
- return e.Type.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *FuncLit) End() source.Pos {
- return e.Body.End()
-}
-
-func (e *FuncLit) String() string {
- return "func" + e.Type.Params.String() + " " + e.Body.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/func_type.go b/vendor/github.com/d5/tengo/compiler/ast/func_type.go
deleted file mode 100644
index 2afaabb1..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/func_type.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// FuncType represents a function type definition.
-type FuncType struct {
- FuncPos source.Pos
- Params *IdentList
-}
-
-func (e *FuncType) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *FuncType) Pos() source.Pos {
- return e.FuncPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *FuncType) End() source.Pos {
- return e.Params.End()
-}
-
-func (e *FuncType) String() string {
- return "func" + e.Params.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/ident.go b/vendor/github.com/d5/tengo/compiler/ast/ident.go
deleted file mode 100644
index 33b7ff76..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/ident.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// Ident represents an identifier.
-type Ident struct {
- Name string
- NamePos source.Pos
-}
-
-func (e *Ident) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *Ident) Pos() source.Pos {
- return e.NamePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *Ident) End() source.Pos {
- return source.Pos(int(e.NamePos) + len(e.Name))
-}
-
-func (e *Ident) String() string {
- if e != nil {
- return e.Name
- }
-
- return nullRep
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/if_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/if_stmt.go
deleted file mode 100644
index b3d65606..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/if_stmt.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// IfStmt represents an if statement.
-type IfStmt struct {
- IfPos source.Pos
- Init Stmt
- Cond Expr
- Body *BlockStmt
- Else Stmt // else branch; or nil
-}
-
-func (s *IfStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *IfStmt) Pos() source.Pos {
- return s.IfPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *IfStmt) End() source.Pos {
- if s.Else != nil {
- return s.Else.End()
- }
-
- return s.Body.End()
-}
-
-func (s *IfStmt) String() string {
- var initStmt, elseStmt string
- if s.Init != nil {
- initStmt = s.Init.String() + "; "
- }
- if s.Else != nil {
- elseStmt = " else " + s.Else.String()
- }
-
- return "if " + initStmt + s.Cond.String() + " " + s.Body.String() + elseStmt
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go b/vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go
deleted file mode 100644
index f9843b50..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
-)
-
-// ImmutableExpr represents an immutable expression
-type ImmutableExpr struct {
- Expr Expr
- ErrorPos source.Pos
- LParen source.Pos
- RParen source.Pos
-}
-
-func (e *ImmutableExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *ImmutableExpr) Pos() source.Pos {
- return e.ErrorPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *ImmutableExpr) End() source.Pos {
- return e.RParen
-}
-
-func (e *ImmutableExpr) String() string {
- return "immutable(" + e.Expr.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/import_expr.go b/vendor/github.com/d5/tengo/compiler/ast/import_expr.go
deleted file mode 100644
index 6eff74a9..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/import_expr.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// ImportExpr represents an import expression
-type ImportExpr struct {
- ModuleName string
- Token token.Token
- TokenPos source.Pos
-}
-
-func (e *ImportExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *ImportExpr) Pos() source.Pos {
- return e.TokenPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *ImportExpr) End() source.Pos {
- return source.Pos(int(e.TokenPos) + 10 + len(e.ModuleName)) // import("moduleName")
-}
-
-func (e *ImportExpr) String() string {
- return `import("` + e.ModuleName + `")"`
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go
deleted file mode 100644
index e4e7f92c..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// IncDecStmt represents increment or decrement statement.
-type IncDecStmt struct {
- Expr Expr
- Token token.Token
- TokenPos source.Pos
-}
-
-func (s *IncDecStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *IncDecStmt) Pos() source.Pos {
- return s.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (s *IncDecStmt) End() source.Pos {
- return source.Pos(int(s.TokenPos) + 2)
-}
-
-func (s *IncDecStmt) String() string {
- return s.Expr.String() + s.Token.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/index_expr.go b/vendor/github.com/d5/tengo/compiler/ast/index_expr.go
deleted file mode 100644
index bc0992a3..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/index_expr.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// IndexExpr represents an index expression.
-type IndexExpr struct {
- Expr Expr
- LBrack source.Pos
- Index Expr
- RBrack source.Pos
-}
-
-func (e *IndexExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *IndexExpr) Pos() source.Pos {
- return e.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *IndexExpr) End() source.Pos {
- return e.RBrack + 1
-}
-
-func (e *IndexExpr) String() string {
- var index string
- if e.Index != nil {
- index = e.Index.String()
- }
-
- return e.Expr.String() + "[" + index + "]"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/int_lit.go b/vendor/github.com/d5/tengo/compiler/ast/int_lit.go
deleted file mode 100644
index 3e1fd98b..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/int_lit.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// IntLit represents an integer literal.
-type IntLit struct {
- Value int64
- ValuePos source.Pos
- Literal string
-}
-
-func (e *IntLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *IntLit) Pos() source.Pos {
- return e.ValuePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *IntLit) End() source.Pos {
- return source.Pos(int(e.ValuePos) + len(e.Literal))
-}
-
-func (e *IntLit) String() string {
- return e.Literal
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go b/vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go
deleted file mode 100644
index 3d7fca9e..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// MapElementLit represents a map element.
-type MapElementLit struct {
- Key string
- KeyPos source.Pos
- ColonPos source.Pos
- Value Expr
-}
-
-func (e *MapElementLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *MapElementLit) Pos() source.Pos {
- return e.KeyPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *MapElementLit) End() source.Pos {
- return e.Value.End()
-}
-
-func (e *MapElementLit) String() string {
- return e.Key + ": " + e.Value.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/map_lit.go b/vendor/github.com/d5/tengo/compiler/ast/map_lit.go
deleted file mode 100644
index a228224d..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/map_lit.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package ast
-
-import (
- "strings"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// MapLit represents a map literal.
-type MapLit struct {
- LBrace source.Pos
- Elements []*MapElementLit
- RBrace source.Pos
-}
-
-func (e *MapLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *MapLit) Pos() source.Pos {
- return e.LBrace
-}
-
-// End returns the position of first character immediately after the node.
-func (e *MapLit) End() source.Pos {
- return e.RBrace + 1
-}
-
-func (e *MapLit) String() string {
- var elements []string
- for _, m := range e.Elements {
- elements = append(elements, m.String())
- }
-
- return "{" + strings.Join(elements, ", ") + "}"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/node.go b/vendor/github.com/d5/tengo/compiler/ast/node.go
deleted file mode 100644
index 44677b47..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/node.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// Node represents a node in the AST.
-type Node interface {
- // Pos returns the position of first character belonging to the node.
- Pos() source.Pos
- // End returns the position of first character immediately after the node.
- End() source.Pos
- // String returns a string representation of the node.
- String() string
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/paren_expr.go b/vendor/github.com/d5/tengo/compiler/ast/paren_expr.go
deleted file mode 100644
index 8db4ac02..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/paren_expr.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// ParenExpr represents a parenthesis wrapped expression.
-type ParenExpr struct {
- Expr Expr
- LParen source.Pos
- RParen source.Pos
-}
-
-func (e *ParenExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *ParenExpr) Pos() source.Pos {
- return e.LParen
-}
-
-// End returns the position of first character immediately after the node.
-func (e *ParenExpr) End() source.Pos {
- return e.RParen + 1
-}
-
-func (e *ParenExpr) String() string {
- return "(" + e.Expr.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/return_stmt.go b/vendor/github.com/d5/tengo/compiler/ast/return_stmt.go
deleted file mode 100644
index 592d45b8..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/return_stmt.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
-)
-
-// ReturnStmt represents a return statement.
-type ReturnStmt struct {
- ReturnPos source.Pos
- Result Expr
-}
-
-func (s *ReturnStmt) stmtNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (s *ReturnStmt) Pos() source.Pos {
- return s.ReturnPos
-}
-
-// End returns the position of first character immediately after the node.
-func (s *ReturnStmt) End() source.Pos {
- if s.Result != nil {
- return s.Result.End()
- }
-
- return s.ReturnPos + 6
-}
-
-func (s *ReturnStmt) String() string {
- if s.Result != nil {
- return "return " + s.Result.String()
- }
-
- return "return"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/selector_expr.go b/vendor/github.com/d5/tengo/compiler/ast/selector_expr.go
deleted file mode 100644
index 31d2e6d1..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/selector_expr.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// SelectorExpr represents a selector expression.
-type SelectorExpr struct {
- Expr Expr
- Sel Expr
-}
-
-func (e *SelectorExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *SelectorExpr) Pos() source.Pos {
- return e.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *SelectorExpr) End() source.Pos {
- return e.Sel.End()
-}
-
-func (e *SelectorExpr) String() string {
- return e.Expr.String() + "." + e.Sel.String()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/slice_expr.go b/vendor/github.com/d5/tengo/compiler/ast/slice_expr.go
deleted file mode 100644
index e7e2e05b..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/slice_expr.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// SliceExpr represents a slice expression.
-type SliceExpr struct {
- Expr Expr
- LBrack source.Pos
- Low Expr
- High Expr
- RBrack source.Pos
-}
-
-func (e *SliceExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *SliceExpr) Pos() source.Pos {
- return e.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *SliceExpr) End() source.Pos {
- return e.RBrack + 1
-}
-
-func (e *SliceExpr) String() string {
- var low, high string
- if e.Low != nil {
- low = e.Low.String()
- }
- if e.High != nil {
- high = e.High.String()
- }
-
- return e.Expr.String() + "[" + low + ":" + high + "]"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/stmt.go b/vendor/github.com/d5/tengo/compiler/ast/stmt.go
deleted file mode 100644
index 6b26ba88..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/stmt.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package ast
-
-// Stmt represents a statement in the AST.
-type Stmt interface {
- Node
- stmtNode()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/string_lit.go b/vendor/github.com/d5/tengo/compiler/ast/string_lit.go
deleted file mode 100644
index 2119d34b..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/string_lit.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// StringLit represents a string literal.
-type StringLit struct {
- Value string
- ValuePos source.Pos
- Literal string
-}
-
-func (e *StringLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *StringLit) Pos() source.Pos {
- return e.ValuePos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *StringLit) End() source.Pos {
- return source.Pos(int(e.ValuePos) + len(e.Literal))
-}
-
-func (e *StringLit) String() string {
- return e.Literal
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/unary_expr.go b/vendor/github.com/d5/tengo/compiler/ast/unary_expr.go
deleted file mode 100644
index 53236146..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/unary_expr.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package ast
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// UnaryExpr represents an unary operator expression.
-type UnaryExpr struct {
- Expr Expr
- Token token.Token
- TokenPos source.Pos
-}
-
-func (e *UnaryExpr) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *UnaryExpr) Pos() source.Pos {
- return e.Expr.Pos()
-}
-
-// End returns the position of first character immediately after the node.
-func (e *UnaryExpr) End() source.Pos {
- return e.Expr.End()
-}
-
-func (e *UnaryExpr) String() string {
- return "(" + e.Token.String() + e.Expr.String() + ")"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go b/vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go
deleted file mode 100644
index 8e51b113..00000000
--- a/vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package ast
-
-import "github.com/d5/tengo/compiler/source"
-
-// UndefinedLit represents an undefined literal.
-type UndefinedLit struct {
- TokenPos source.Pos
-}
-
-func (e *UndefinedLit) exprNode() {}
-
-// Pos returns the position of first character belonging to the node.
-func (e *UndefinedLit) Pos() source.Pos {
- return e.TokenPos
-}
-
-// End returns the position of first character immediately after the node.
-func (e *UndefinedLit) End() source.Pos {
- return e.TokenPos + 9 // len(undefined) == 9
-}
-
-func (e *UndefinedLit) String() string {
- return "undefined"
-}
diff --git a/vendor/github.com/d5/tengo/compiler/bytecode.go b/vendor/github.com/d5/tengo/compiler/bytecode.go
deleted file mode 100644
index 35f36c0a..00000000
--- a/vendor/github.com/d5/tengo/compiler/bytecode.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package compiler
-
-import (
- "encoding/gob"
- "fmt"
- "io"
- "reflect"
-
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/objects"
-)
-
-// Bytecode is a compiled instructions and constants.
-type Bytecode struct {
- FileSet *source.FileSet
- MainFunction *objects.CompiledFunction
- Constants []objects.Object
-}
-
-// Encode writes Bytecode data to the writer.
-func (b *Bytecode) Encode(w io.Writer) error {
- enc := gob.NewEncoder(w)
-
- if err := enc.Encode(b.FileSet); err != nil {
- return err
- }
-
- if err := enc.Encode(b.MainFunction); err != nil {
- return err
- }
-
- // constants
- return enc.Encode(b.Constants)
-}
-
-// CountObjects returns the number of objects found in Constants.
-func (b *Bytecode) CountObjects() int {
- n := 0
-
- for _, c := range b.Constants {
- n += objects.CountObjects(c)
- }
-
- return n
-}
-
-// FormatInstructions returns human readable string representations of
-// compiled instructions.
-func (b *Bytecode) FormatInstructions() []string {
- return FormatInstructions(b.MainFunction.Instructions, 0)
-}
-
-// FormatConstants returns human readable string representations of
-// compiled constants.
-func (b *Bytecode) FormatConstants() (output []string) {
- for cidx, cn := range b.Constants {
- switch cn := cn.(type) {
- case *objects.CompiledFunction:
- output = append(output, fmt.Sprintf("[% 3d] (Compiled Function|%p)", cidx, &cn))
- for _, l := range FormatInstructions(cn.Instructions, 0) {
- output = append(output, fmt.Sprintf(" %s", l))
- }
- default:
- output = append(output, fmt.Sprintf("[% 3d] %s (%s|%p)", cidx, cn, reflect.TypeOf(cn).Elem().Name(), &cn))
- }
- }
-
- return
-}
-
-func init() {
- gob.Register(&source.FileSet{})
- gob.Register(&source.File{})
- gob.Register(&objects.Array{})
- gob.Register(&objects.Bool{})
- gob.Register(&objects.Bytes{})
- gob.Register(&objects.Char{})
- gob.Register(&objects.Closure{})
- gob.Register(&objects.CompiledFunction{})
- gob.Register(&objects.Error{})
- gob.Register(&objects.Float{})
- gob.Register(&objects.ImmutableArray{})
- gob.Register(&objects.ImmutableMap{})
- gob.Register(&objects.Int{})
- gob.Register(&objects.Map{})
- gob.Register(&objects.String{})
- gob.Register(&objects.Time{})
- gob.Register(&objects.Undefined{})
- gob.Register(&objects.UserFunction{})
-}
diff --git a/vendor/github.com/d5/tengo/compiler/bytecode_decode.go b/vendor/github.com/d5/tengo/compiler/bytecode_decode.go
deleted file mode 100644
index b3b32a64..00000000
--- a/vendor/github.com/d5/tengo/compiler/bytecode_decode.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package compiler
-
-import (
- "encoding/gob"
- "fmt"
- "io"
-
- "github.com/d5/tengo/objects"
-)
-
-// Decode reads Bytecode data from the reader.
-func (b *Bytecode) Decode(r io.Reader, modules *objects.ModuleMap) error {
- if modules == nil {
- modules = objects.NewModuleMap()
- }
-
- dec := gob.NewDecoder(r)
-
- if err := dec.Decode(&b.FileSet); err != nil {
- return err
- }
- // TODO: files in b.FileSet.File does not have their 'set' field properly set to b.FileSet
- // as it's private field and not serialized by gob encoder/decoder.
-
- if err := dec.Decode(&b.MainFunction); err != nil {
- return err
- }
-
- if err := dec.Decode(&b.Constants); err != nil {
- return err
- }
- for i, v := range b.Constants {
- fv, err := fixDecoded(v, modules)
- if err != nil {
- return err
- }
- b.Constants[i] = fv
- }
-
- return nil
-}
-
-func fixDecoded(o objects.Object, modules *objects.ModuleMap) (objects.Object, error) {
- switch o := o.(type) {
- case *objects.Bool:
- if o.IsFalsy() {
- return objects.FalseValue, nil
- }
- return objects.TrueValue, nil
- case *objects.Undefined:
- return objects.UndefinedValue, nil
- case *objects.Array:
- for i, v := range o.Value {
- fv, err := fixDecoded(v, modules)
- if err != nil {
- return nil, err
- }
- o.Value[i] = fv
- }
- case *objects.ImmutableArray:
- for i, v := range o.Value {
- fv, err := fixDecoded(v, modules)
- if err != nil {
- return nil, err
- }
- o.Value[i] = fv
- }
- case *objects.Map:
- for k, v := range o.Value {
- fv, err := fixDecoded(v, modules)
- if err != nil {
- return nil, err
- }
- o.Value[k] = fv
- }
- case *objects.ImmutableMap:
- modName := moduleName(o)
- if mod := modules.GetBuiltinModule(modName); mod != nil {
- return mod.AsImmutableMap(modName), nil
- }
-
- for k, v := range o.Value {
- // encoding of user function not supported
- if _, isUserFunction := v.(*objects.UserFunction); isUserFunction {
- return nil, fmt.Errorf("user function not decodable")
- }
-
- fv, err := fixDecoded(v, modules)
- if err != nil {
- return nil, err
- }
- o.Value[k] = fv
- }
- }
-
- return o, nil
-}
diff --git a/vendor/github.com/d5/tengo/compiler/bytecode_optimize.go b/vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
deleted file mode 100644
index 9526de2e..00000000
--- a/vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package compiler
-
-import (
- "fmt"
-
- "github.com/d5/tengo/objects"
-)
-
-// RemoveDuplicates finds and remove the duplicate values in Constants.
-// Note this function mutates Bytecode.
-func (b *Bytecode) RemoveDuplicates() {
- var deduped []objects.Object
-
- indexMap := make(map[int]int) // mapping from old constant index to new index
- ints := make(map[int64]int)
- strings := make(map[string]int)
- floats := make(map[float64]int)
- chars := make(map[rune]int)
- immutableMaps := make(map[string]int) // for modules
-
- for curIdx, c := range b.Constants {
- switch c := c.(type) {
- case *objects.CompiledFunction:
- // add to deduped list
- indexMap[curIdx] = len(deduped)
- deduped = append(deduped, c)
- case *objects.ImmutableMap:
- modName := moduleName(c)
- newIdx, ok := immutableMaps[modName]
- if modName != "" && ok {
- indexMap[curIdx] = newIdx
- } else {
- newIdx = len(deduped)
- immutableMaps[modName] = newIdx
- indexMap[curIdx] = newIdx
- deduped = append(deduped, c)
- }
- case *objects.Int:
- if newIdx, ok := ints[c.Value]; ok {
- indexMap[curIdx] = newIdx
- } else {
- newIdx = len(deduped)
- ints[c.Value] = newIdx
- indexMap[curIdx] = newIdx
- deduped = append(deduped, c)
- }
- case *objects.String:
- if newIdx, ok := strings[c.Value]; ok {
- indexMap[curIdx] = newIdx
- } else {
- newIdx = len(deduped)
- strings[c.Value] = newIdx
- indexMap[curIdx] = newIdx
- deduped = append(deduped, c)
- }
- case *objects.Float:
- if newIdx, ok := floats[c.Value]; ok {
- indexMap[curIdx] = newIdx
- } else {
- newIdx = len(deduped)
- floats[c.Value] = newIdx
- indexMap[curIdx] = newIdx
- deduped = append(deduped, c)
- }
- case *objects.Char:
- if newIdx, ok := chars[c.Value]; ok {
- indexMap[curIdx] = newIdx
- } else {
- newIdx = len(deduped)
- chars[c.Value] = newIdx
- indexMap[curIdx] = newIdx
- deduped = append(deduped, c)
- }
- default:
- panic(fmt.Errorf("unsupported top-level constant type: %s", c.TypeName()))
- }
- }
-
- // replace with de-duplicated constants
- b.Constants = deduped
-
- // update CONST instructions with new indexes
- // main function
- updateConstIndexes(b.MainFunction.Instructions, indexMap)
- // other compiled functions in constants
- for _, c := range b.Constants {
- switch c := c.(type) {
- case *objects.CompiledFunction:
- updateConstIndexes(c.Instructions, indexMap)
- }
- }
-}
-
-func updateConstIndexes(insts []byte, indexMap map[int]int) {
- i := 0
- for i < len(insts) {
- op := insts[i]
- numOperands := OpcodeOperands[op]
- _, read := ReadOperands(numOperands, insts[i+1:])
-
- switch op {
- case OpConstant:
- curIdx := int(insts[i+2]) | int(insts[i+1])<<8
- newIdx, ok := indexMap[curIdx]
- if !ok {
- panic(fmt.Errorf("constant index not found: %d", curIdx))
- }
- copy(insts[i:], MakeInstruction(op, newIdx))
- case OpClosure:
- curIdx := int(insts[i+2]) | int(insts[i+1])<<8
- numFree := int(insts[i+3])
- newIdx, ok := indexMap[curIdx]
- if !ok {
- panic(fmt.Errorf("constant index not found: %d", curIdx))
- }
- copy(insts[i:], MakeInstruction(op, newIdx, numFree))
- }
-
- i += 1 + read
- }
-}
-
-func moduleName(mod *objects.ImmutableMap) string {
- if modName, ok := mod.Value["__module_name__"].(*objects.String); ok {
- return modName.Value
- }
-
- return ""
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compilation_scope.go b/vendor/github.com/d5/tengo/compiler/compilation_scope.go
deleted file mode 100644
index 41e7876b..00000000
--- a/vendor/github.com/d5/tengo/compiler/compilation_scope.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package compiler
-
-import "github.com/d5/tengo/compiler/source"
-
-// CompilationScope represents a compiled instructions
-// and the last two instructions that were emitted.
-type CompilationScope struct {
- instructions []byte
- symbolInit map[string]bool
- sourceMap map[int]source.Pos
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler.go b/vendor/github.com/d5/tengo/compiler/compiler.go
deleted file mode 100644
index 8bde5dc9..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler.go
+++ /dev/null
@@ -1,846 +0,0 @@
-package compiler
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "path/filepath"
- "reflect"
- "strings"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
- "github.com/d5/tengo/objects"
-)
-
-// Compiler compiles the AST into a bytecode.
-type Compiler struct {
- file *source.File
- parent *Compiler
- modulePath string
- constants []objects.Object
- symbolTable *SymbolTable
- scopes []CompilationScope
- scopeIndex int
- modules *objects.ModuleMap
- compiledModules map[string]*objects.CompiledFunction
- allowFileImport bool
- loops []*Loop
- loopIndex int
- trace io.Writer
- indent int
-}
-
-// NewCompiler creates a Compiler.
-func NewCompiler(file *source.File, symbolTable *SymbolTable, constants []objects.Object, modules *objects.ModuleMap, trace io.Writer) *Compiler {
- mainScope := CompilationScope{
- symbolInit: make(map[string]bool),
- sourceMap: make(map[int]source.Pos),
- }
-
- // symbol table
- if symbolTable == nil {
- symbolTable = NewSymbolTable()
- }
-
- // add builtin functions to the symbol table
- for idx, fn := range objects.Builtins {
- symbolTable.DefineBuiltin(idx, fn.Name)
- }
-
- // builtin modules
- if modules == nil {
- modules = objects.NewModuleMap()
- }
-
- return &Compiler{
- file: file,
- symbolTable: symbolTable,
- constants: constants,
- scopes: []CompilationScope{mainScope},
- scopeIndex: 0,
- loopIndex: -1,
- trace: trace,
- modules: modules,
- compiledModules: make(map[string]*objects.CompiledFunction),
- }
-}
-
-// Compile compiles the AST node.
-func (c *Compiler) Compile(node ast.Node) error {
- if c.trace != nil {
- if node != nil {
- defer un(trace(c, fmt.Sprintf("%s (%s)", node.String(), reflect.TypeOf(node).Elem().Name())))
- } else {
- defer un(trace(c, "<nil>"))
- }
- }
-
- switch node := node.(type) {
- case *ast.File:
- for _, stmt := range node.Stmts {
- if err := c.Compile(stmt); err != nil {
- return err
- }
- }
-
- case *ast.ExprStmt:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
- c.emit(node, OpPop)
-
- case *ast.IncDecStmt:
- op := token.AddAssign
- if node.Token == token.Dec {
- op = token.SubAssign
- }
-
- return c.compileAssign(node, []ast.Expr{node.Expr}, []ast.Expr{&ast.IntLit{Value: 1}}, op)
-
- case *ast.ParenExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- case *ast.BinaryExpr:
- if node.Token == token.LAnd || node.Token == token.LOr {
- return c.compileLogical(node)
- }
-
- if node.Token == token.Less {
- if err := c.Compile(node.RHS); err != nil {
- return err
- }
-
- if err := c.Compile(node.LHS); err != nil {
- return err
- }
-
- c.emit(node, OpBinaryOp, int(token.Greater))
-
- return nil
- } else if node.Token == token.LessEq {
- if err := c.Compile(node.RHS); err != nil {
- return err
- }
- if err := c.Compile(node.LHS); err != nil {
- return err
- }
-
- c.emit(node, OpBinaryOp, int(token.GreaterEq))
-
- return nil
- }
-
- if err := c.Compile(node.LHS); err != nil {
- return err
- }
- if err := c.Compile(node.RHS); err != nil {
- return err
- }
-
- switch node.Token {
- case token.Add:
- c.emit(node, OpBinaryOp, int(token.Add))
- case token.Sub:
- c.emit(node, OpBinaryOp, int(token.Sub))
- case token.Mul:
- c.emit(node, OpBinaryOp, int(token.Mul))
- case token.Quo:
- c.emit(node, OpBinaryOp, int(token.Quo))
- case token.Rem:
- c.emit(node, OpBinaryOp, int(token.Rem))
- case token.Greater:
- c.emit(node, OpBinaryOp, int(token.Greater))
- case token.GreaterEq:
- c.emit(node, OpBinaryOp, int(token.GreaterEq))
- case token.Equal:
- c.emit(node, OpEqual)
- case token.NotEqual:
- c.emit(node, OpNotEqual)
- case token.And:
- c.emit(node, OpBinaryOp, int(token.And))
- case token.Or:
- c.emit(node, OpBinaryOp, int(token.Or))
- case token.Xor:
- c.emit(node, OpBinaryOp, int(token.Xor))
- case token.AndNot:
- c.emit(node, OpBinaryOp, int(token.AndNot))
- case token.Shl:
- c.emit(node, OpBinaryOp, int(token.Shl))
- case token.Shr:
- c.emit(node, OpBinaryOp, int(token.Shr))
- default:
- return c.errorf(node, "invalid binary operator: %s", node.Token.String())
- }
-
- case *ast.IntLit:
- c.emit(node, OpConstant, c.addConstant(&objects.Int{Value: node.Value}))
-
- case *ast.FloatLit:
- c.emit(node, OpConstant, c.addConstant(&objects.Float{Value: node.Value}))
-
- case *ast.BoolLit:
- if node.Value {
- c.emit(node, OpTrue)
- } else {
- c.emit(node, OpFalse)
- }
-
- case *ast.StringLit:
- if len(node.Value) > tengo.MaxStringLen {
- return c.error(node, objects.ErrStringLimit)
- }
-
- c.emit(node, OpConstant, c.addConstant(&objects.String{Value: node.Value}))
-
- case *ast.CharLit:
- c.emit(node, OpConstant, c.addConstant(&objects.Char{Value: node.Value}))
-
- case *ast.UndefinedLit:
- c.emit(node, OpNull)
-
- case *ast.UnaryExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- switch node.Token {
- case token.Not:
- c.emit(node, OpLNot)
- case token.Sub:
- c.emit(node, OpMinus)
- case token.Xor:
- c.emit(node, OpBComplement)
- case token.Add:
- // do nothing?
- default:
- return c.errorf(node, "invalid unary operator: %s", node.Token.String())
- }
-
- case *ast.IfStmt:
- // open new symbol table for the statement
- c.symbolTable = c.symbolTable.Fork(true)
- defer func() {
- c.symbolTable = c.symbolTable.Parent(false)
- }()
-
- if node.Init != nil {
- if err := c.Compile(node.Init); err != nil {
- return err
- }
- }
-
- if err := c.Compile(node.Cond); err != nil {
- return err
- }
-
- // first jump placeholder
- jumpPos1 := c.emit(node, OpJumpFalsy, 0)
-
- if err := c.Compile(node.Body); err != nil {
- return err
- }
-
- if node.Else != nil {
- // second jump placeholder
- jumpPos2 := c.emit(node, OpJump, 0)
-
- // update first jump offset
- curPos := len(c.currentInstructions())
- c.changeOperand(jumpPos1, curPos)
-
- if err := c.Compile(node.Else); err != nil {
- return err
- }
-
- // update second jump offset
- curPos = len(c.currentInstructions())
- c.changeOperand(jumpPos2, curPos)
- } else {
- // update first jump offset
- curPos := len(c.currentInstructions())
- c.changeOperand(jumpPos1, curPos)
- }
-
- case *ast.ForStmt:
- return c.compileForStmt(node)
-
- case *ast.ForInStmt:
- return c.compileForInStmt(node)
-
- case *ast.BranchStmt:
- if node.Token == token.Break {
- curLoop := c.currentLoop()
- if curLoop == nil {
- return c.errorf(node, "break not allowed outside loop")
- }
- pos := c.emit(node, OpJump, 0)
- curLoop.Breaks = append(curLoop.Breaks, pos)
- } else if node.Token == token.Continue {
- curLoop := c.currentLoop()
- if curLoop == nil {
- return c.errorf(node, "continue not allowed outside loop")
- }
- pos := c.emit(node, OpJump, 0)
- curLoop.Continues = append(curLoop.Continues, pos)
- } else {
- panic(fmt.Errorf("invalid branch statement: %s", node.Token.String()))
- }
-
- case *ast.BlockStmt:
- if len(node.Stmts) == 0 {
- return nil
- }
-
- c.symbolTable = c.symbolTable.Fork(true)
- defer func() {
- c.symbolTable = c.symbolTable.Parent(false)
- }()
-
- for _, stmt := range node.Stmts {
- if err := c.Compile(stmt); err != nil {
- return err
- }
- }
-
- case *ast.AssignStmt:
- if err := c.compileAssign(node, node.LHS, node.RHS, node.Token); err != nil {
- return err
- }
-
- case *ast.Ident:
- symbol, _, ok := c.symbolTable.Resolve(node.Name)
- if !ok {
- return c.errorf(node, "unresolved reference '%s'", node.Name)
- }
-
- switch symbol.Scope {
- case ScopeGlobal:
- c.emit(node, OpGetGlobal, symbol.Index)
- case ScopeLocal:
- c.emit(node, OpGetLocal, symbol.Index)
- case ScopeBuiltin:
- c.emit(node, OpGetBuiltin, symbol.Index)
- case ScopeFree:
- c.emit(node, OpGetFree, symbol.Index)
- }
-
- case *ast.ArrayLit:
- for _, elem := range node.Elements {
- if err := c.Compile(elem); err != nil {
- return err
- }
- }
-
- c.emit(node, OpArray, len(node.Elements))
-
- case *ast.MapLit:
- for _, elt := range node.Elements {
- // key
- if len(elt.Key) > tengo.MaxStringLen {
- return c.error(node, objects.ErrStringLimit)
- }
- c.emit(node, OpConstant, c.addConstant(&objects.String{Value: elt.Key}))
-
- // value
- if err := c.Compile(elt.Value); err != nil {
- return err
- }
- }
-
- c.emit(node, OpMap, len(node.Elements)*2)
-
- case *ast.SelectorExpr: // selector on RHS side
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- if err := c.Compile(node.Sel); err != nil {
- return err
- }
-
- c.emit(node, OpIndex)
-
- case *ast.IndexExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- if err := c.Compile(node.Index); err != nil {
- return err
- }
-
- c.emit(node, OpIndex)
-
- case *ast.SliceExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- if node.Low != nil {
- if err := c.Compile(node.Low); err != nil {
- return err
- }
- } else {
- c.emit(node, OpNull)
- }
-
- if node.High != nil {
- if err := c.Compile(node.High); err != nil {
- return err
- }
- } else {
- c.emit(node, OpNull)
- }
-
- c.emit(node, OpSliceIndex)
-
- case *ast.FuncLit:
- c.enterScope()
-
- for _, p := range node.Type.Params.List {
- s := c.symbolTable.Define(p.Name)
-
- // function arguments is not assigned directly.
- s.LocalAssigned = true
- }
-
- if err := c.Compile(node.Body); err != nil {
- return err
- }
-
- // code optimization
- c.optimizeFunc(node)
-
- freeSymbols := c.symbolTable.FreeSymbols()
- numLocals := c.symbolTable.MaxSymbols()
- instructions, sourceMap := c.leaveScope()
-
- for _, s := range freeSymbols {
- switch s.Scope {
- case ScopeLocal:
- if !s.LocalAssigned {
- // Here, the closure is capturing a local variable that's not yet assigned its value.
- // One example is a local recursive function:
- //
- // func() {
- // foo := func(x) {
- // // ..
- // return foo(x-1)
- // }
- // }
- //
- // which translate into
- //
- // 0000 GETL 0
- // 0002 CLOSURE ? 1
- // 0006 DEFL 0
- //
- // . So the local variable (0) is being captured before it's assigned the value.
- //
- // Solution is to transform the code into something like this:
- //
- // func() {
- // foo := undefined
- // foo = func(x) {
- // // ..
- // return foo(x-1)
- // }
- // }
- //
- // that is equivalent to
- //
- // 0000 NULL
- // 0001 DEFL 0
- // 0003 GETL 0
- // 0005 CLOSURE ? 1
- // 0009 SETL 0
- //
-
- c.emit(node, OpNull)
- c.emit(node, OpDefineLocal, s.Index)
-
- s.LocalAssigned = true
- }
-
- c.emit(node, OpGetLocalPtr, s.Index)
- case ScopeFree:
- c.emit(node, OpGetFreePtr, s.Index)
- }
- }
-
- compiledFunction := &objects.CompiledFunction{
- Instructions: instructions,
- NumLocals: numLocals,
- NumParameters: len(node.Type.Params.List),
- VarArgs: node.Type.Params.VarArgs,
- SourceMap: sourceMap,
- }
-
- if len(freeSymbols) > 0 {
- c.emit(node, OpClosure, c.addConstant(compiledFunction), len(freeSymbols))
- } else {
- c.emit(node, OpConstant, c.addConstant(compiledFunction))
- }
-
- case *ast.ReturnStmt:
- if c.symbolTable.Parent(true) == nil {
- // outside the function
- return c.errorf(node, "return not allowed outside function")
- }
-
- if node.Result == nil {
- c.emit(node, OpReturn, 0)
- } else {
- if err := c.Compile(node.Result); err != nil {
- return err
- }
-
- c.emit(node, OpReturn, 1)
- }
-
- case *ast.CallExpr:
- if err := c.Compile(node.Func); err != nil {
- return err
- }
-
- for _, arg := range node.Args {
- if err := c.Compile(arg); err != nil {
- return err
- }
- }
-
- c.emit(node, OpCall, len(node.Args))
-
- case *ast.ImportExpr:
- if node.ModuleName == "" {
- return c.errorf(node, "empty module name")
- }
-
- if mod := c.modules.Get(node.ModuleName); mod != nil {
- v, err := mod.Import(node.ModuleName)
- if err != nil {
- return err
- }
-
- switch v := v.(type) {
- case []byte: // module written in Tengo
- compiled, err := c.compileModule(node, node.ModuleName, node.ModuleName, v)
- if err != nil {
- return err
- }
- c.emit(node, OpConstant, c.addConstant(compiled))
- c.emit(node, OpCall, 0)
- case objects.Object: // builtin module
- c.emit(node, OpConstant, c.addConstant(v))
- default:
- panic(fmt.Errorf("invalid import value type: %T", v))
- }
- } else if c.allowFileImport {
- moduleName := node.ModuleName
- if !strings.HasSuffix(moduleName, ".tengo") {
- moduleName += ".tengo"
- }
-
- modulePath, err := filepath.Abs(moduleName)
- if err != nil {
- return c.errorf(node, "module file path error: %s", err.Error())
- }
-
- if err := c.checkCyclicImports(node, modulePath); err != nil {
- return err
- }
-
- moduleSrc, err := ioutil.ReadFile(moduleName)
- if err != nil {
- return c.errorf(node, "module file read error: %s", err.Error())
- }
-
- compiled, err := c.compileModule(node, moduleName, modulePath, moduleSrc)
- if err != nil {
- return err
- }
- c.emit(node, OpConstant, c.addConstant(compiled))
- c.emit(node, OpCall, 0)
- } else {
- return c.errorf(node, "module '%s' not found", node.ModuleName)
- }
-
- case *ast.ExportStmt:
- // export statement must be in top-level scope
- if c.scopeIndex != 0 {
- return c.errorf(node, "export not allowed inside function")
- }
-
- // export statement is simply ignore when compiling non-module code
- if c.parent == nil {
- break
- }
-
- if err := c.Compile(node.Result); err != nil {
- return err
- }
-
- c.emit(node, OpImmutable)
- c.emit(node, OpReturn, 1)
-
- case *ast.ErrorExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- c.emit(node, OpError)
-
- case *ast.ImmutableExpr:
- if err := c.Compile(node.Expr); err != nil {
- return err
- }
-
- c.emit(node, OpImmutable)
-
- case *ast.CondExpr:
- if err := c.Compile(node.Cond); err != nil {
- return err
- }
-
- // first jump placeholder
- jumpPos1 := c.emit(node, OpJumpFalsy, 0)
-
- if err := c.Compile(node.True); err != nil {
- return err
- }
-
- // second jump placeholder
- jumpPos2 := c.emit(node, OpJump, 0)
-
- // update first jump offset
- curPos := len(c.currentInstructions())
- c.changeOperand(jumpPos1, curPos)
-
- if err := c.Compile(node.False); err != nil {
- return err
- }
-
- // update second jump offset
- curPos = len(c.currentInstructions())
- c.changeOperand(jumpPos2, curPos)
- }
-
- return nil
-}
-
-// Bytecode returns a compiled bytecode.
-func (c *Compiler) Bytecode() *Bytecode {
- return &Bytecode{
- FileSet: c.file.Set(),
- MainFunction: &objects.CompiledFunction{
- Instructions: c.currentInstructions(),
- SourceMap: c.currentSourceMap(),
- },
- Constants: c.constants,
- }
-}
-
-// EnableFileImport enables or disables module loading from local files.
-// Local file modules are disabled by default.
-func (c *Compiler) EnableFileImport(enable bool) {
- c.allowFileImport = enable
-}
-
-func (c *Compiler) fork(file *source.File, modulePath string, symbolTable *SymbolTable) *Compiler {
- child := NewCompiler(file, symbolTable, nil, c.modules, c.trace)
- child.modulePath = modulePath // module file path
- child.parent = c // parent to set to current compiler
-
- return child
-}
-
-func (c *Compiler) error(node ast.Node, err error) error {
- return &Error{
- fileSet: c.file.Set(),
- node: node,
- error: err,
- }
-}
-
-func (c *Compiler) errorf(node ast.Node, format string, args ...interface{}) error {
- return &Error{
- fileSet: c.file.Set(),
- node: node,
- error: fmt.Errorf(format, args...),
- }
-}
-
-func (c *Compiler) addConstant(o objects.Object) int {
- if c.parent != nil {
- // module compilers will use their parent's constants array
- return c.parent.addConstant(o)
- }
-
- c.constants = append(c.constants, o)
-
- if c.trace != nil {
- c.printTrace(fmt.Sprintf("CONST %04d %s", len(c.constants)-1, o))
- }
-
- return len(c.constants) - 1
-}
-
-func (c *Compiler) addInstruction(b []byte) int {
- posNewIns := len(c.currentInstructions())
-
- c.scopes[c.scopeIndex].instructions = append(c.currentInstructions(), b...)
-
- return posNewIns
-}
-
-func (c *Compiler) replaceInstruction(pos int, inst []byte) {
- copy(c.currentInstructions()[pos:], inst)
-
- if c.trace != nil {
- c.printTrace(fmt.Sprintf("REPLC %s",
- FormatInstructions(c.scopes[c.scopeIndex].instructions[pos:], pos)[0]))
- }
-}
-
-func (c *Compiler) changeOperand(opPos int, operand ...int) {
- op := Opcode(c.currentInstructions()[opPos])
- inst := MakeInstruction(op, operand...)
-
- c.replaceInstruction(opPos, inst)
-}
-
-// optimizeFunc performs some code-level optimization for the current function instructions
-// it removes unreachable (dead code) instructions and adds "returns" instruction if needed.
-func (c *Compiler) optimizeFunc(node ast.Node) {
- // any instructions between RETURN and the function end
- // or instructions between RETURN and jump target position
- // are considered as unreachable.
-
- // pass 1. identify all jump destinations
- dsts := make(map[int]bool)
- iterateInstructions(c.scopes[c.scopeIndex].instructions, func(pos int, opcode Opcode, operands []int) bool {
- switch opcode {
- case OpJump, OpJumpFalsy, OpAndJump, OpOrJump:
- dsts[operands[0]] = true
- }
-
- return true
- })
-
- var newInsts []byte
-
- // pass 2. eliminate dead code
- posMap := make(map[int]int) // old position to new position
- var dstIdx int
- var deadCode bool
- iterateInstructions(c.scopes[c.scopeIndex].instructions, func(pos int, opcode Opcode, operands []int) bool {
- switch {
- case opcode == OpReturn:
- if deadCode {
- return true
- }
- deadCode = true
- case dsts[pos]:
- dstIdx++
- deadCode = false
- case deadCode:
- return true
- }
-
- posMap[pos] = len(newInsts)
- newInsts = append(newInsts, MakeInstruction(opcode, operands...)...)
- return true
- })
-
- // pass 3. update jump positions
- var lastOp Opcode
- var appendReturn bool
- endPos := len(c.scopes[c.scopeIndex].instructions)
- iterateInstructions(newInsts, func(pos int, opcode Opcode, operands []int) bool {
- switch opcode {
- case OpJump, OpJumpFalsy, OpAndJump, OpOrJump:
- newDst, ok := posMap[operands[0]]
- if ok {
- copy(newInsts[pos:], MakeInstruction(opcode, newDst))
- } else if endPos == operands[0] {
- // there's a jump instruction that jumps to the end of function
- // compiler should append "return".
- appendReturn = true
- } else {
- panic(fmt.Errorf("invalid jump position: %d", newDst))
- }
- }
- lastOp = opcode
- return true
- })
- if lastOp != OpReturn {
- appendReturn = true
- }
-
- // pass 4. update source map
- newSourceMap := make(map[int]source.Pos)
- for pos, srcPos := range c.scopes[c.scopeIndex].sourceMap {
- newPos, ok := posMap[pos]
- if ok {
- newSourceMap[newPos] = srcPos
- }
- }
-
- c.scopes[c.scopeIndex].instructions = newInsts
- c.scopes[c.scopeIndex].sourceMap = newSourceMap
-
- // append "return"
- if appendReturn {
- c.emit(node, OpReturn, 0)
- }
-}
-
-func (c *Compiler) emit(node ast.Node, opcode Opcode, operands ...int) int {
- filePos := source.NoPos
- if node != nil {
- filePos = node.Pos()
- }
-
- inst := MakeInstruction(opcode, operands...)
- pos := c.addInstruction(inst)
- c.scopes[c.scopeIndex].sourceMap[pos] = filePos
-
- if c.trace != nil {
- c.printTrace(fmt.Sprintf("EMIT %s",
- FormatInstructions(c.scopes[c.scopeIndex].instructions[pos:], pos)[0]))
- }
-
- return pos
-}
-
-func (c *Compiler) printTrace(a ...interface{}) {
- const (
- dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
- n = len(dots)
- )
-
- i := 2 * c.indent
- for i > n {
- _, _ = fmt.Fprint(c.trace, dots)
- i -= n
- }
- _, _ = fmt.Fprint(c.trace, dots[0:i])
- _, _ = fmt.Fprintln(c.trace, a...)
-}
-
-func trace(c *Compiler, msg string) *Compiler {
- c.printTrace(msg, "{")
- c.indent++
-
- return c
-}
-
-func un(c *Compiler) {
- c.indent--
- c.printTrace("}")
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_assign.go b/vendor/github.com/d5/tengo/compiler/compiler_assign.go
deleted file mode 100644
index 59296f6f..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_assign.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package compiler
-
-import (
- "fmt"
-
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/token"
-)
-
-func (c *Compiler) compileAssign(node ast.Node, lhs, rhs []ast.Expr, op token.Token) error {
- numLHS, numRHS := len(lhs), len(rhs)
- if numLHS > 1 || numRHS > 1 {
- return c.errorf(node, "tuple assignment not allowed")
- }
-
- // resolve and compile left-hand side
- ident, selectors := resolveAssignLHS(lhs[0])
- numSel := len(selectors)
-
- if op == token.Define && numSel > 0 {
- // using selector on new variable does not make sense
- return c.errorf(node, "operator ':=' not allowed with selector")
- }
-
- symbol, depth, exists := c.symbolTable.Resolve(ident)
- if op == token.Define {
- if depth == 0 && exists {
- return c.errorf(node, "'%s' redeclared in this block", ident)
- }
-
- symbol = c.symbolTable.Define(ident)
- } else {
- if !exists {
- return c.errorf(node, "unresolved reference '%s'", ident)
- }
- }
-
- // +=, -=, *=, /=
- if op != token.Assign && op != token.Define {
- if err := c.Compile(lhs[0]); err != nil {
- return err
- }
- }
-
- // compile RHSs
- for _, expr := range rhs {
- if err := c.Compile(expr); err != nil {
- return err
- }
- }
-
- switch op {
- case token.AddAssign:
- c.emit(node, OpBinaryOp, int(token.Add))
- case token.SubAssign:
- c.emit(node, OpBinaryOp, int(token.Sub))
- case token.MulAssign:
- c.emit(node, OpBinaryOp, int(token.Mul))
- case token.QuoAssign:
- c.emit(node, OpBinaryOp, int(token.Quo))
- case token.RemAssign:
- c.emit(node, OpBinaryOp, int(token.Rem))
- case token.AndAssign:
- c.emit(node, OpBinaryOp, int(token.And))
- case token.OrAssign:
- c.emit(node, OpBinaryOp, int(token.Or))
- case token.AndNotAssign:
- c.emit(node, OpBinaryOp, int(token.AndNot))
- case token.XorAssign:
- c.emit(node, OpBinaryOp, int(token.Xor))
- case token.ShlAssign:
- c.emit(node, OpBinaryOp, int(token.Shl))
- case token.ShrAssign:
- c.emit(node, OpBinaryOp, int(token.Shr))
- }
-
- // compile selector expressions (right to left)
- for i := numSel - 1; i >= 0; i-- {
- if err := c.Compile(selectors[i]); err != nil {
- return err
- }
- }
-
- switch symbol.Scope {
- case ScopeGlobal:
- if numSel > 0 {
- c.emit(node, OpSetSelGlobal, symbol.Index, numSel)
- } else {
- c.emit(node, OpSetGlobal, symbol.Index)
- }
- case ScopeLocal:
- if numSel > 0 {
- c.emit(node, OpSetSelLocal, symbol.Index, numSel)
- } else {
- if op == token.Define && !symbol.LocalAssigned {
- c.emit(node, OpDefineLocal, symbol.Index)
- } else {
- c.emit(node, OpSetLocal, symbol.Index)
- }
- }
-
- // mark the symbol as local-assigned
- symbol.LocalAssigned = true
- case ScopeFree:
- if numSel > 0 {
- c.emit(node, OpSetSelFree, symbol.Index, numSel)
- } else {
- c.emit(node, OpSetFree, symbol.Index)
- }
- default:
- panic(fmt.Errorf("invalid assignment variable scope: %s", symbol.Scope))
- }
-
- return nil
-}
-
-func resolveAssignLHS(expr ast.Expr) (name string, selectors []ast.Expr) {
- switch term := expr.(type) {
- case *ast.SelectorExpr:
- name, selectors = resolveAssignLHS(term.Expr)
- selectors = append(selectors, term.Sel)
- return
-
- case *ast.IndexExpr:
- name, selectors = resolveAssignLHS(term.Expr)
- selectors = append(selectors, term.Index)
-
- case *ast.Ident:
- name = term.Name
- }
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_for.go b/vendor/github.com/d5/tengo/compiler/compiler_for.go
deleted file mode 100644
index e7b7b5f1..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_for.go
+++ /dev/null
@@ -1,181 +0,0 @@
-package compiler
-
-import (
- "github.com/d5/tengo/compiler/ast"
-)
-
-func (c *Compiler) compileForStmt(stmt *ast.ForStmt) error {
- c.symbolTable = c.symbolTable.Fork(true)
- defer func() {
- c.symbolTable = c.symbolTable.Parent(false)
- }()
-
- // init statement
- if stmt.Init != nil {
- if err := c.Compile(stmt.Init); err != nil {
- return err
- }
- }
-
- // pre-condition position
- preCondPos := len(c.currentInstructions())
-
- // condition expression
- postCondPos := -1
- if stmt.Cond != nil {
- if err := c.Compile(stmt.Cond); err != nil {
- return err
- }
- // condition jump position
- postCondPos = c.emit(stmt, OpJumpFalsy, 0)
- }
-
- // enter loop
- loop := c.enterLoop()
-
- // body statement
- if err := c.Compile(stmt.Body); err != nil {
- c.leaveLoop()
- return err
- }
-
- c.leaveLoop()
-
- // post-body position
- postBodyPos := len(c.currentInstructions())
-
- // post statement
- if stmt.Post != nil {
- if err := c.Compile(stmt.Post); err != nil {
- return err
- }
- }
-
- // back to condition
- c.emit(stmt, OpJump, preCondPos)
-
- // post-statement position
- postStmtPos := len(c.currentInstructions())
- if postCondPos >= 0 {
- c.changeOperand(postCondPos, postStmtPos)
- }
-
- // update all break/continue jump positions
- for _, pos := range loop.Breaks {
- c.changeOperand(pos, postStmtPos)
- }
- for _, pos := range loop.Continues {
- c.changeOperand(pos, postBodyPos)
- }
-
- return nil
-}
-
-func (c *Compiler) compileForInStmt(stmt *ast.ForInStmt) error {
- c.symbolTable = c.symbolTable.Fork(true)
- defer func() {
- c.symbolTable = c.symbolTable.Parent(false)
- }()
-
- // for-in statement is compiled like following:
- //
- // for :it := iterator(iterable); :it.next(); {
- // k, v := :it.get() // DEFINE operator
- //
- // ... body ...
- // }
- //
- // ":it" is a local variable but will be conflict with other user variables
- // because character ":" is not allowed.
-
- // init
- // :it = iterator(iterable)
- itSymbol := c.symbolTable.Define(":it")
- if err := c.Compile(stmt.Iterable); err != nil {
- return err
- }
- c.emit(stmt, OpIteratorInit)
- if itSymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpSetGlobal, itSymbol.Index)
- } else {
- c.emit(stmt, OpDefineLocal, itSymbol.Index)
- }
-
- // pre-condition position
- preCondPos := len(c.currentInstructions())
-
- // condition
- // :it.HasMore()
- if itSymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpGetGlobal, itSymbol.Index)
- } else {
- c.emit(stmt, OpGetLocal, itSymbol.Index)
- }
- c.emit(stmt, OpIteratorNext)
-
- // condition jump position
- postCondPos := c.emit(stmt, OpJumpFalsy, 0)
-
- // enter loop
- loop := c.enterLoop()
-
- // assign key variable
- if stmt.Key.Name != "_" {
- keySymbol := c.symbolTable.Define(stmt.Key.Name)
- if itSymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpGetGlobal, itSymbol.Index)
- } else {
- c.emit(stmt, OpGetLocal, itSymbol.Index)
- }
- c.emit(stmt, OpIteratorKey)
- if keySymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpSetGlobal, keySymbol.Index)
- } else {
- c.emit(stmt, OpDefineLocal, keySymbol.Index)
- }
- }
-
- // assign value variable
- if stmt.Value.Name != "_" {
- valueSymbol := c.symbolTable.Define(stmt.Value.Name)
- if itSymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpGetGlobal, itSymbol.Index)
- } else {
- c.emit(stmt, OpGetLocal, itSymbol.Index)
- }
- c.emit(stmt, OpIteratorValue)
- if valueSymbol.Scope == ScopeGlobal {
- c.emit(stmt, OpSetGlobal, valueSymbol.Index)
- } else {
- c.emit(stmt, OpDefineLocal, valueSymbol.Index)
- }
- }
-
- // body statement
- if err := c.Compile(stmt.Body); err != nil {
- c.leaveLoop()
- return err
- }
-
- c.leaveLoop()
-
- // post-body position
- postBodyPos := len(c.currentInstructions())
-
- // back to condition
- c.emit(stmt, OpJump, preCondPos)
-
- // post-statement position
- postStmtPos := len(c.currentInstructions())
- c.changeOperand(postCondPos, postStmtPos)
-
- // update all break/continue jump positions
- for _, pos := range loop.Breaks {
- c.changeOperand(pos, postStmtPos)
- }
- for _, pos := range loop.Continues {
- c.changeOperand(pos, postBodyPos)
- }
-
- return nil
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_logical.go b/vendor/github.com/d5/tengo/compiler/compiler_logical.go
deleted file mode 100644
index 68c96759..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_logical.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package compiler
-
-import (
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/token"
-)
-
-func (c *Compiler) compileLogical(node *ast.BinaryExpr) error {
- // left side term
- if err := c.Compile(node.LHS); err != nil {
- return err
- }
-
- // jump position
- var jumpPos int
- if node.Token == token.LAnd {
- jumpPos = c.emit(node, OpAndJump, 0)
- } else {
- jumpPos = c.emit(node, OpOrJump, 0)
- }
-
- // right side term
- if err := c.Compile(node.RHS); err != nil {
- return err
- }
-
- c.changeOperand(jumpPos, len(c.currentInstructions()))
-
- return nil
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_loops.go b/vendor/github.com/d5/tengo/compiler/compiler_loops.go
deleted file mode 100644
index 0659ce73..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_loops.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package compiler
-
-func (c *Compiler) enterLoop() *Loop {
- loop := &Loop{}
-
- c.loops = append(c.loops, loop)
- c.loopIndex++
-
- if c.trace != nil {
- c.printTrace("LOOPE", c.loopIndex)
- }
-
- return loop
-}
-
-func (c *Compiler) leaveLoop() {
- if c.trace != nil {
- c.printTrace("LOOPL", c.loopIndex)
- }
-
- c.loops = c.loops[:len(c.loops)-1]
- c.loopIndex--
-}
-
-func (c *Compiler) currentLoop() *Loop {
- if c.loopIndex >= 0 {
- return c.loops[c.loopIndex]
- }
-
- return nil
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_module.go b/vendor/github.com/d5/tengo/compiler/compiler_module.go
deleted file mode 100644
index 8a3671ce..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_module.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package compiler
-
-import (
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/parser"
- "github.com/d5/tengo/objects"
-)
-
-func (c *Compiler) checkCyclicImports(node ast.Node, modulePath string) error {
- if c.modulePath == modulePath {
- return c.errorf(node, "cyclic module import: %s", modulePath)
- } else if c.parent != nil {
- return c.parent.checkCyclicImports(node, modulePath)
- }
-
- return nil
-}
-
-func (c *Compiler) compileModule(node ast.Node, moduleName, modulePath string, src []byte) (*objects.CompiledFunction, error) {
- if err := c.checkCyclicImports(node, modulePath); err != nil {
- return nil, err
- }
-
- compiledModule, exists := c.loadCompiledModule(modulePath)
- if exists {
- return compiledModule, nil
- }
-
- modFile := c.file.Set().AddFile(moduleName, -1, len(src))
- p := parser.NewParser(modFile, src, nil)
- file, err := p.ParseFile()
- if err != nil {
- return nil, err
- }
-
- symbolTable := NewSymbolTable()
-
- // inherit builtin functions
- for _, sym := range c.symbolTable.BuiltinSymbols() {
- symbolTable.DefineBuiltin(sym.Index, sym.Name)
- }
-
- // no global scope for the module
- symbolTable = symbolTable.Fork(false)
-
- // compile module
- moduleCompiler := c.fork(modFile, modulePath, symbolTable)
- if err := moduleCompiler.Compile(file); err != nil {
- return nil, err
- }
-
- // code optimization
- moduleCompiler.optimizeFunc(node)
-
- compiledFunc := moduleCompiler.Bytecode().MainFunction
- compiledFunc.NumLocals = symbolTable.MaxSymbols()
-
- c.storeCompiledModule(modulePath, compiledFunc)
-
- return compiledFunc, nil
-}
-
-func (c *Compiler) loadCompiledModule(modulePath string) (mod *objects.CompiledFunction, ok bool) {
- if c.parent != nil {
- return c.parent.loadCompiledModule(modulePath)
- }
-
- mod, ok = c.compiledModules[modulePath]
-
- return
-}
-
-func (c *Compiler) storeCompiledModule(modulePath string, module *objects.CompiledFunction) {
- if c.parent != nil {
- c.parent.storeCompiledModule(modulePath, module)
- }
-
- c.compiledModules[modulePath] = module
-}
diff --git a/vendor/github.com/d5/tengo/compiler/compiler_scopes.go b/vendor/github.com/d5/tengo/compiler/compiler_scopes.go
deleted file mode 100644
index b63f915a..00000000
--- a/vendor/github.com/d5/tengo/compiler/compiler_scopes.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package compiler
-
-import "github.com/d5/tengo/compiler/source"
-
-func (c *Compiler) currentInstructions() []byte {
- return c.scopes[c.scopeIndex].instructions
-}
-
-func (c *Compiler) currentSourceMap() map[int]source.Pos {
- return c.scopes[c.scopeIndex].sourceMap
-}
-
-func (c *Compiler) enterScope() {
- scope := CompilationScope{
- symbolInit: make(map[string]bool),
- sourceMap: make(map[int]source.Pos),
- }
-
- c.scopes = append(c.scopes, scope)
- c.scopeIndex++
-
- c.symbolTable = c.symbolTable.Fork(false)
-
- if c.trace != nil {
- c.printTrace("SCOPE", c.scopeIndex)
- }
-}
-
-func (c *Compiler) leaveScope() (instructions []byte, sourceMap map[int]source.Pos) {
- instructions = c.currentInstructions()
- sourceMap = c.currentSourceMap()
-
- c.scopes = c.scopes[:len(c.scopes)-1]
- c.scopeIndex--
-
- c.symbolTable = c.symbolTable.Parent(true)
-
- if c.trace != nil {
- c.printTrace("SCOPL", c.scopeIndex)
- }
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/compiler/emitted_instruction.go b/vendor/github.com/d5/tengo/compiler/emitted_instruction.go
deleted file mode 100644
index 8572fb0a..00000000
--- a/vendor/github.com/d5/tengo/compiler/emitted_instruction.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package compiler
-
-// EmittedInstruction represents an opcode
-// with its emitted position.
-type EmittedInstruction struct {
- Opcode Opcode
- Position int
-}
diff --git a/vendor/github.com/d5/tengo/compiler/error.go b/vendor/github.com/d5/tengo/compiler/error.go
deleted file mode 100644
index 6ac33d42..00000000
--- a/vendor/github.com/d5/tengo/compiler/error.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package compiler
-
-import (
- "fmt"
-
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/source"
-)
-
-// Error represents a compiler error.
-type Error struct {
- fileSet *source.FileSet
- node ast.Node
- error error
-}
-
-func (e *Error) Error() string {
- filePos := e.fileSet.Position(e.node.Pos())
- return fmt.Sprintf("Compile Error: %s\n\tat %s", e.error.Error(), filePos)
-}
diff --git a/vendor/github.com/d5/tengo/compiler/instructions.go b/vendor/github.com/d5/tengo/compiler/instructions.go
deleted file mode 100644
index 14dde1d8..00000000
--- a/vendor/github.com/d5/tengo/compiler/instructions.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package compiler
-
-import (
- "fmt"
-)
-
-// MakeInstruction returns a bytecode for an opcode and the operands.
-func MakeInstruction(opcode Opcode, operands ...int) []byte {
- numOperands := OpcodeOperands[opcode]
-
- totalLen := 1
- for _, w := range numOperands {
- totalLen += w
- }
-
- instruction := make([]byte, totalLen)
- instruction[0] = byte(opcode)
-
- offset := 1
- for i, o := range operands {
- width := numOperands[i]
- switch width {
- case 1:
- instruction[offset] = byte(o)
- case 2:
- n := uint16(o)
- instruction[offset] = byte(n >> 8)
- instruction[offset+1] = byte(n)
- }
- offset += width
- }
-
- return instruction
-}
-
-// FormatInstructions returns string representation of
-// bytecode instructions.
-func FormatInstructions(b []byte, posOffset int) []string {
- var out []string
-
- i := 0
- for i < len(b) {
- numOperands := OpcodeOperands[Opcode(b[i])]
- operands, read := ReadOperands(numOperands, b[i+1:])
-
- switch len(numOperands) {
- case 0:
- out = append(out, fmt.Sprintf("%04d %-7s", posOffset+i, OpcodeNames[Opcode(b[i])]))
- case 1:
- out = append(out, fmt.Sprintf("%04d %-7s %-5d", posOffset+i, OpcodeNames[Opcode(b[i])], operands[0]))
- case 2:
- out = append(out, fmt.Sprintf("%04d %-7s %-5d %-5d", posOffset+i, OpcodeNames[Opcode(b[i])], operands[0], operands[1]))
- }
-
- i += 1 + read
- }
-
- return out
-}
-
-func iterateInstructions(b []byte, fn func(pos int, opcode Opcode, operands []int) bool) {
- for i := 0; i < len(b); i++ {
- numOperands := OpcodeOperands[Opcode(b[i])]
- operands, read := ReadOperands(numOperands, b[i+1:])
-
- if !fn(i, b[i], operands) {
- break
- }
-
- i += read
- }
-}
diff --git a/vendor/github.com/d5/tengo/compiler/loop.go b/vendor/github.com/d5/tengo/compiler/loop.go
deleted file mode 100644
index e27cb096..00000000
--- a/vendor/github.com/d5/tengo/compiler/loop.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package compiler
-
-// Loop represents a loop construct that
-// the compiler uses to track the current loop.
-type Loop struct {
- Continues []int
- Breaks []int
-}
diff --git a/vendor/github.com/d5/tengo/compiler/module_loader.go b/vendor/github.com/d5/tengo/compiler/module_loader.go
deleted file mode 100644
index b050474d..00000000
--- a/vendor/github.com/d5/tengo/compiler/module_loader.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package compiler
-
-// ModuleLoader should take a module name and return the module data.
-type ModuleLoader func(moduleName string) ([]byte, error)
diff --git a/vendor/github.com/d5/tengo/compiler/parser/error.go b/vendor/github.com/d5/tengo/compiler/parser/error.go
deleted file mode 100644
index 80544fbd..00000000
--- a/vendor/github.com/d5/tengo/compiler/parser/error.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package parser
-
-import (
- "fmt"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// Error represents a parser error.
-type Error struct {
- Pos source.FilePos
- Msg string
-}
-
-func (e Error) Error() string {
- if e.Pos.Filename != "" || e.Pos.IsValid() {
- return fmt.Sprintf("Parse Error: %s\n\tat %s", e.Msg, e.Pos)
- }
-
- return fmt.Sprintf("Parse Error: %s", e.Msg)
-}
diff --git a/vendor/github.com/d5/tengo/compiler/parser/error_list.go b/vendor/github.com/d5/tengo/compiler/parser/error_list.go
deleted file mode 100644
index 599eaf7d..00000000
--- a/vendor/github.com/d5/tengo/compiler/parser/error_list.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package parser
-
-import (
- "fmt"
- "sort"
-
- "github.com/d5/tengo/compiler/source"
-)
-
-// ErrorList is a collection of parser errors.
-type ErrorList []*Error
-
-// Add adds a new parser error to the collection.
-func (p *ErrorList) Add(pos source.FilePos, msg string) {
- *p = append(*p, &Error{pos, msg})
-}
-
-// Len returns the number of elements in the collection.
-func (p ErrorList) Len() int {
- return len(p)
-}
-
-func (p ErrorList) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p ErrorList) Less(i, j int) bool {
- e := &p[i].Pos
- f := &p[j].Pos
-
- if e.Filename != f.Filename {
- return e.Filename < f.Filename
- }
-
- if e.Line != f.Line {
- return e.Line < f.Line
- }
-
- if e.Column != f.Column {
- return e.Column < f.Column
- }
-
- return p[i].Msg < p[j].Msg
-}
-
-// Sort sorts the collection.
-func (p ErrorList) Sort() {
- sort.Sort(p)
-}
-
-func (p ErrorList) Error() string {
- switch len(p) {
- case 0:
- return "no errors"
- case 1:
- return p[0].Error()
- }
- return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
-}
-
-// Err returns an error.
-func (p ErrorList) Err() error {
- if len(p) == 0 {
- return nil
- }
-
- return p
-}
diff --git a/vendor/github.com/d5/tengo/compiler/parser/parse_source.go b/vendor/github.com/d5/tengo/compiler/parser/parse_source.go
deleted file mode 100644
index 5c71436d..00000000
--- a/vendor/github.com/d5/tengo/compiler/parser/parse_source.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package parser
-
-import (
- "io"
-
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/source"
-)
-
-// ParseSource parses source code 'src' and builds an AST.
-func ParseSource(filename string, src []byte, trace io.Writer) (res *ast.File, err error) {
- fileSet := source.NewFileSet()
- file := fileSet.AddFile(filename, -1, len(src))
-
- p := NewParser(file, src, trace)
- return p.ParseFile()
-}
diff --git a/vendor/github.com/d5/tengo/compiler/parser/sync.go b/vendor/github.com/d5/tengo/compiler/parser/sync.go
deleted file mode 100644
index e68d623a..00000000
--- a/vendor/github.com/d5/tengo/compiler/parser/sync.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package parser
-
-import "github.com/d5/tengo/compiler/token"
-
-var stmtStart = map[token.Token]bool{
- token.Break: true,
- token.Continue: true,
- token.For: true,
- token.If: true,
- token.Return: true,
- token.Export: true,
-}
diff --git a/vendor/github.com/d5/tengo/compiler/scanner/error_handler.go b/vendor/github.com/d5/tengo/compiler/scanner/error_handler.go
deleted file mode 100644
index 379f0196..00000000
--- a/vendor/github.com/d5/tengo/compiler/scanner/error_handler.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package scanner
-
-import "github.com/d5/tengo/compiler/source"
-
-// ErrorHandler is an error handler for the scanner.
-type ErrorHandler func(pos source.FilePos, msg string)
diff --git a/vendor/github.com/d5/tengo/compiler/scanner/mode.go b/vendor/github.com/d5/tengo/compiler/scanner/mode.go
deleted file mode 100644
index f67ceaf8..00000000
--- a/vendor/github.com/d5/tengo/compiler/scanner/mode.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package scanner
-
-// Mode represents a scanner mode.
-type Mode int
-
-// List of scanner modes.
-const (
- ScanComments Mode = 1 << iota
- DontInsertSemis
-)
diff --git a/vendor/github.com/d5/tengo/compiler/source/file.go b/vendor/github.com/d5/tengo/compiler/source/file.go
deleted file mode 100644
index 9e51c9a4..00000000
--- a/vendor/github.com/d5/tengo/compiler/source/file.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package source
-
-// File represents a source file.
-type File struct {
- // File set for the file
- set *FileSet
- // File name as provided to AddFile
- Name string
- // Pos value range for this file is [base...base+size]
- Base int
- // File size as provided to AddFile
- Size int
- // Lines contains the offset of the first character for each line (the first entry is always 0)
- Lines []int
-}
-
-// Set returns FileSet.
-func (f *File) Set() *FileSet {
- return f.set
-}
-
-// LineCount returns the current number of lines.
-func (f *File) LineCount() int {
- return len(f.Lines)
-}
-
-// AddLine adds a new line.
-func (f *File) AddLine(offset int) {
- if i := len(f.Lines); (i == 0 || f.Lines[i-1] < offset) && offset < f.Size {
- f.Lines = append(f.Lines, offset)
- }
-}
-
-// LineStart returns the position of the first character in the line.
-func (f *File) LineStart(line int) Pos {
- if line < 1 {
- panic("illegal line number (line numbering starts at 1)")
- }
-
- if line > len(f.Lines) {
- panic("illegal line number")
- }
-
- return Pos(f.Base + f.Lines[line-1])
-}
-
-// FileSetPos returns the position in the file set.
-func (f *File) FileSetPos(offset int) Pos {
- if offset > f.Size {
- panic("illegal file offset")
- }
-
- return Pos(f.Base + offset)
-}
-
-// Offset translates the file set position into the file offset.
-func (f *File) Offset(p Pos) int {
- if int(p) < f.Base || int(p) > f.Base+f.Size {
- panic("illegal Pos value")
- }
-
- return int(p) - f.Base
-}
-
-// Position translates the file set position into the file position.
-func (f *File) Position(p Pos) (pos FilePos) {
- if p != NoPos {
- if int(p) < f.Base || int(p) > f.Base+f.Size {
- panic("illegal Pos value")
- }
-
- pos = f.position(p)
- }
-
- return
-}
-
-func (f *File) position(p Pos) (pos FilePos) {
- offset := int(p) - f.Base
- pos.Offset = offset
- pos.Filename, pos.Line, pos.Column = f.unpack(offset)
-
- return
-}
-
-func (f *File) unpack(offset int) (filename string, line, column int) {
- filename = f.Name
- if i := searchInts(f.Lines, offset); i >= 0 {
- line, column = i+1, offset-f.Lines[i]+1
- }
-
- return
-}
-
-func searchInts(a []int, x int) int {
- // This function body is a manually inlined version of:
- // return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
- i, j := 0, len(a)
- for i < j {
- h := i + (j-i)/2 // avoid overflow when computing h
- // i ≤ h < j
- if a[h] <= x {
- i = h + 1
- } else {
- j = h
- }
- }
-
- return i - 1
-}
diff --git a/vendor/github.com/d5/tengo/compiler/source/file_pos.go b/vendor/github.com/d5/tengo/compiler/source/file_pos.go
deleted file mode 100644
index 4055fe6d..00000000
--- a/vendor/github.com/d5/tengo/compiler/source/file_pos.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package source
-
-import "fmt"
-
-// FilePos represents a position information in the file.
-type FilePos struct {
- Filename string // filename, if any
- Offset int // offset, starting at 0
- Line int // line number, starting at 1
- Column int // column number, starting at 1 (byte count)
-}
-
-// IsValid returns true if the position is valid.
-func (p FilePos) IsValid() bool {
- return p.Line > 0
-}
-
-// String returns a string in one of several forms:
-//
-// file:line:column valid position with file name
-// file:line valid position with file name but no column (column == 0)
-// line:column valid position without file name
-// line valid position without file name and no column (column == 0)
-// file invalid position with file name
-// - invalid position without file name
-//
-func (p FilePos) String() string {
- s := p.Filename
-
- if p.IsValid() {
- if s != "" {
- s += ":"
- }
-
- s += fmt.Sprintf("%d", p.Line)
-
- if p.Column != 0 {
- s += fmt.Sprintf(":%d", p.Column)
- }
- }
-
- if s == "" {
- s = "-"
- }
-
- return s
-}
diff --git a/vendor/github.com/d5/tengo/compiler/source/file_set.go b/vendor/github.com/d5/tengo/compiler/source/file_set.go
deleted file mode 100644
index da342364..00000000
--- a/vendor/github.com/d5/tengo/compiler/source/file_set.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package source
-
-import (
- "sort"
-)
-
-// FileSet represents a set of source files.
-type FileSet struct {
- Base int // base offset for the next file
- Files []*File // list of files in the order added to the set
- LastFile *File // cache of last file looked up
-}
-
-// NewFileSet creates a new file set.
-func NewFileSet() *FileSet {
- return &FileSet{
- Base: 1, // 0 == NoPos
- }
-}
-
-// AddFile adds a new file in the file set.
-func (s *FileSet) AddFile(filename string, base, size int) *File {
- if base < 0 {
- base = s.Base
- }
- if base < s.Base || size < 0 {
- panic("illegal base or size")
- }
-
- f := &File{
- set: s,
- Name: filename,
- Base: base,
- Size: size,
- Lines: []int{0},
- }
-
- base += size + 1 // +1 because EOF also has a position
- if base < 0 {
- panic("offset overflow (> 2G of source code in file set)")
- }
-
- // add the file to the file set
- s.Base = base
- s.Files = append(s.Files, f)
- s.LastFile = f
-
- return f
-}
-
-// File returns the file that contains the position p.
-// If no such file is found (for instance for p == NoPos),
-// the result is nil.
-//
-func (s *FileSet) File(p Pos) (f *File) {
- if p != NoPos {
- f = s.file(p)
- }
-
- return
-}
-
-// Position converts a Pos p in the fileset into a FilePos value.
-func (s *FileSet) Position(p Pos) (pos FilePos) {
- if p != NoPos {
- if f := s.file(p); f != nil {
- return f.position(p)
- }
- }
-
- return
-}
-
-func (s *FileSet) file(p Pos) *File {
- // common case: p is in last file
- if f := s.LastFile; f != nil && f.Base <= int(p) && int(p) <= f.Base+f.Size {
- return f
- }
-
- // p is not in last file - search all files
- if i := searchFiles(s.Files, int(p)); i >= 0 {
- f := s.Files[i]
-
- // f.base <= int(p) by definition of searchFiles
- if int(p) <= f.Base+f.Size {
- s.LastFile = f // race is ok - s.last is only a cache
- return f
- }
- }
-
- return nil
-}
-
-func searchFiles(a []*File, x int) int {
- return sort.Search(len(a), func(i int) bool { return a[i].Base > x }) - 1
-}
diff --git a/vendor/github.com/d5/tengo/compiler/symbol.go b/vendor/github.com/d5/tengo/compiler/symbol.go
deleted file mode 100644
index bcd53234..00000000
--- a/vendor/github.com/d5/tengo/compiler/symbol.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package compiler
-
-// Symbol represents a symbol in the symbol table.
-type Symbol struct {
- Name string
- Scope SymbolScope
- Index int
- LocalAssigned bool // if the local symbol is assigned at least once
-}
diff --git a/vendor/github.com/d5/tengo/compiler/symbol_scopes.go b/vendor/github.com/d5/tengo/compiler/symbol_scopes.go
deleted file mode 100644
index e0c0d94b..00000000
--- a/vendor/github.com/d5/tengo/compiler/symbol_scopes.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package compiler
-
-// SymbolScope represents a symbol scope.
-type SymbolScope string
-
-// List of symbol scopes
-const (
- ScopeGlobal SymbolScope = "GLOBAL"
- ScopeLocal SymbolScope = "LOCAL"
- ScopeBuiltin SymbolScope = "BUILTIN"
- ScopeFree SymbolScope = "FREE"
-)
diff --git a/vendor/github.com/d5/tengo/compiler/token/keywords.go b/vendor/github.com/d5/tengo/compiler/token/keywords.go
deleted file mode 100644
index fd6e9d0b..00000000
--- a/vendor/github.com/d5/tengo/compiler/token/keywords.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package token
-
-var keywords map[string]Token
-
-func init() {
- keywords = make(map[string]Token)
- for i := _keywordBeg + 1; i < _keywordEnd; i++ {
- keywords[tokens[i]] = i
- }
-}
-
-// Lookup returns corresponding keyword if ident is a keyword.
-func Lookup(ident string) Token {
- if tok, isKeyword := keywords[ident]; isKeyword {
- return tok
- }
-
- return Ident
-}
diff --git a/vendor/github.com/d5/tengo/go.mod b/vendor/github.com/d5/tengo/go.mod
deleted file mode 100644
index 8421e273..00000000
--- a/vendor/github.com/d5/tengo/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/d5/tengo
-
-go 1.12
diff --git a/vendor/github.com/d5/tengo/objects/array.go b/vendor/github.com/d5/tengo/objects/array.go
deleted file mode 100644
index 1e917c59..00000000
--- a/vendor/github.com/d5/tengo/objects/array.go
+++ /dev/null
@@ -1,130 +0,0 @@
-package objects
-
-import (
- "fmt"
- "strings"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Array represents an array of objects.
-type Array struct {
- Value []Object
-}
-
-// TypeName returns the name of the type.
-func (o *Array) TypeName() string {
- return "array"
-}
-
-func (o *Array) String() string {
- var elements []string
- for _, e := range o.Value {
- elements = append(elements, e.String())
- }
-
- return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Array) BinaryOp(op token.Token, rhs Object) (Object, error) {
- if rhs, ok := rhs.(*Array); ok {
- switch op {
- case token.Add:
- if len(rhs.Value) == 0 {
- return o, nil
- }
- return &Array{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Array) Copy() Object {
- var c []Object
- for _, elem := range o.Value {
- c = append(c, elem.Copy())
- }
-
- return &Array{Value: c}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Array) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Array) Equals(x Object) bool {
- var xVal []Object
- switch x := x.(type) {
- case *Array:
- xVal = x.Value
- case *ImmutableArray:
- xVal = x.Value
- default:
- return false
- }
-
- if len(o.Value) != len(xVal) {
- return false
- }
-
- for i, e := range o.Value {
- if !e.Equals(xVal[i]) {
- return false
- }
- }
-
- return true
-}
-
-// IndexGet returns an element at a given index.
-func (o *Array) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- idxVal := int(intIdx.Value)
-
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
-
- res = o.Value[idxVal]
-
- return
-}
-
-// IndexSet sets an element at a given index.
-func (o *Array) IndexSet(index, value Object) (err error) {
- intIdx, ok := ToInt(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- if intIdx < 0 || intIdx >= len(o.Value) {
- err = ErrIndexOutOfBounds
- return
- }
-
- o.Value[intIdx] = value
-
- return nil
-}
-
-// Iterate creates an array iterator.
-func (o *Array) Iterate() Iterator {
- return &ArrayIterator{
- v: o.Value,
- l: len(o.Value),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/array_iterator.go b/vendor/github.com/d5/tengo/objects/array_iterator.go
deleted file mode 100644
index 204faa41..00000000
--- a/vendor/github.com/d5/tengo/objects/array_iterator.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// ArrayIterator is an iterator for an array.
-type ArrayIterator struct {
- v []Object
- i int
- l int
-}
-
-// TypeName returns the name of the type.
-func (i *ArrayIterator) TypeName() string {
- return "array-iterator"
-}
-
-func (i *ArrayIterator) String() string {
- return "<array-iterator>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (i *ArrayIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (i *ArrayIterator) IsFalsy() bool {
- return true
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (i *ArrayIterator) Equals(Object) bool {
- return false
-}
-
-// Copy returns a copy of the type.
-func (i *ArrayIterator) Copy() Object {
- return &ArrayIterator{v: i.v, i: i.i, l: i.l}
-}
-
-// Next returns true if there are more elements to iterate.
-func (i *ArrayIterator) Next() bool {
- i.i++
- return i.i <= i.l
-}
-
-// Key returns the key or index value of the current element.
-func (i *ArrayIterator) Key() Object {
- return &Int{Value: int64(i.i - 1)}
-}
-
-// Value returns the value of the current element.
-func (i *ArrayIterator) Value() Object {
- return i.v[i.i-1]
-}
diff --git a/vendor/github.com/d5/tengo/objects/bool.go b/vendor/github.com/d5/tengo/objects/bool.go
deleted file mode 100644
index ac9949e4..00000000
--- a/vendor/github.com/d5/tengo/objects/bool.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// Bool represents a boolean value.
-type Bool struct {
- // this is intentionally non-public to force using objects.TrueValue and FalseValue always
- value bool
-}
-
-func (o *Bool) String() string {
- if o.value {
- return "true"
- }
-
- return "false"
-}
-
-// TypeName returns the name of the type.
-func (o *Bool) TypeName() string {
- return "bool"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Bool) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Bool) Copy() Object {
- return o
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Bool) IsFalsy() bool {
- return !o.value
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Bool) Equals(x Object) bool {
- return o == x
-}
-
-// GobDecode decodes bool value from input bytes.
-func (o *Bool) GobDecode(b []byte) (err error) {
- o.value = b[0] == 1
-
- return
-}
-
-// GobEncode encodes bool values into bytes.
-func (o *Bool) GobEncode() (b []byte, err error) {
- if o.value {
- b = []byte{1}
- } else {
- b = []byte{0}
- }
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_append.go b/vendor/github.com/d5/tengo/objects/builtin_append.go
deleted file mode 100644
index 9fb14b82..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_append.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package objects
-
-// append(arr, items...)
-func builtinAppend(args ...Object) (Object, error) {
- if len(args) < 2 {
- return nil, ErrWrongNumArguments
- }
-
- switch arg := args[0].(type) {
- case *Array:
- return &Array{Value: append(arg.Value, args[1:]...)}, nil
- case *ImmutableArray:
- return &Array{Value: append(arg.Value, args[1:]...)}, nil
- default:
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: arg.TypeName(),
- }
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_convert.go b/vendor/github.com/d5/tengo/objects/builtin_convert.go
deleted file mode 100644
index b5f2d05d..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_convert.go
+++ /dev/null
@@ -1,169 +0,0 @@
-package objects
-
-import "github.com/d5/tengo"
-
-func builtinString(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*String); ok {
- return args[0], nil
- }
-
- v, ok := ToString(args[0])
- if ok {
- if len(v) > tengo.MaxStringLen {
- return nil, ErrStringLimit
- }
-
- return &String{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinInt(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Int); ok {
- return args[0], nil
- }
-
- v, ok := ToInt64(args[0])
- if ok {
- return &Int{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinFloat(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Float); ok {
- return args[0], nil
- }
-
- v, ok := ToFloat64(args[0])
- if ok {
- return &Float{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinBool(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Bool); ok {
- return args[0], nil
- }
-
- v, ok := ToBool(args[0])
- if ok {
- if v {
- return TrueValue, nil
- }
-
- return FalseValue, nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinChar(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Char); ok {
- return args[0], nil
- }
-
- v, ok := ToRune(args[0])
- if ok {
- return &Char{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinBytes(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- // bytes(N) => create a new bytes with given size N
- if n, ok := args[0].(*Int); ok {
- if n.Value > int64(tengo.MaxBytesLen) {
- return nil, ErrBytesLimit
- }
-
- return &Bytes{Value: make([]byte, int(n.Value))}, nil
- }
-
- v, ok := ToByteSlice(args[0])
- if ok {
- if len(v) > tengo.MaxBytesLen {
- return nil, ErrBytesLimit
- }
-
- return &Bytes{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
-
-func builtinTime(args ...Object) (Object, error) {
- argsLen := len(args)
- if !(argsLen == 1 || argsLen == 2) {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Time); ok {
- return args[0], nil
- }
-
- v, ok := ToTime(args[0])
- if ok {
- return &Time{Value: v}, nil
- }
-
- if argsLen == 2 {
- return args[1], nil
- }
-
- return UndefinedValue, nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_copy.go b/vendor/github.com/d5/tengo/objects/builtin_copy.go
deleted file mode 100644
index 4b254b2b..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_copy.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package objects
-
-func builtinCopy(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- return args[0].Copy(), nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_format.go b/vendor/github.com/d5/tengo/objects/builtin_format.go
deleted file mode 100644
index 1f0e75ed..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_format.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package objects
-
-func builtinFormat(args ...Object) (Object, error) {
- numArgs := len(args)
- if numArgs == 0 {
- return nil, ErrWrongNumArguments
- }
-
- format, ok := args[0].(*String)
- if !ok {
- return nil, ErrInvalidArgumentType{
- Name: "format",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- }
- if numArgs == 1 {
- return format, nil // okay to return 'format' directly as String is immutable
- }
-
- s, err := Format(format.Value, args[1:]...)
- if err != nil {
- return nil, err
- }
-
- return &String{Value: s}, nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_function.go b/vendor/github.com/d5/tengo/objects/builtin_function.go
deleted file mode 100644
index 1d021617..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_function.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// BuiltinFunction represents a builtin function.
-type BuiltinFunction struct {
- Name string
- Value CallableFunc
-}
-
-// TypeName returns the name of the type.
-func (o *BuiltinFunction) TypeName() string {
- return "builtin-function:" + o.Name
-}
-
-func (o *BuiltinFunction) String() string {
- return "<builtin-function>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *BuiltinFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *BuiltinFunction) Copy() Object {
- return &BuiltinFunction{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *BuiltinFunction) IsFalsy() bool {
- return false
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *BuiltinFunction) Equals(x Object) bool {
- return false
-}
-
-// Call executes a builtin function.
-func (o *BuiltinFunction) Call(args ...Object) (Object, error) {
- return o.Value(args...)
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_len.go b/vendor/github.com/d5/tengo/objects/builtin_len.go
deleted file mode 100644
index 39fbedd8..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_len.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package objects
-
-// len(obj object) => int
-func builtinLen(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- switch arg := args[0].(type) {
- case *Array:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *ImmutableArray:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *String:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *Bytes:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *Map:
- return &Int{Value: int64(len(arg.Value))}, nil
- case *ImmutableMap:
- return &Int{Value: int64(len(arg.Value))}, nil
- default:
- return nil, ErrInvalidArgumentType{
- Name: "first",
- Expected: "array/string/bytes/map",
- Found: arg.TypeName(),
- }
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_module.go b/vendor/github.com/d5/tengo/objects/builtin_module.go
deleted file mode 100644
index 0ad1d99d..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_module.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package objects
-
-// BuiltinModule is an importable module that's written in Go.
-type BuiltinModule struct {
- Attrs map[string]Object
-}
-
-// Import returns an immutable map for the module.
-func (m *BuiltinModule) Import(moduleName string) (interface{}, error) {
- return m.AsImmutableMap(moduleName), nil
-}
-
-// AsImmutableMap converts builtin module into an immutable map.
-func (m *BuiltinModule) AsImmutableMap(moduleName string) *ImmutableMap {
- attrs := make(map[string]Object, len(m.Attrs))
- for k, v := range m.Attrs {
- attrs[k] = v.Copy()
- }
-
- attrs["__module_name__"] = &String{Value: moduleName}
-
- return &ImmutableMap{Value: attrs}
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_type.go b/vendor/github.com/d5/tengo/objects/builtin_type.go
deleted file mode 100644
index 376c26bb..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_type.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package objects
-
-func builtinTypeName(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- return &String{Value: args[0].TypeName()}, nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtin_type_checks.go b/vendor/github.com/d5/tengo/objects/builtin_type_checks.go
deleted file mode 100644
index d1e8471d..00000000
--- a/vendor/github.com/d5/tengo/objects/builtin_type_checks.go
+++ /dev/null
@@ -1,195 +0,0 @@
-package objects
-
-func builtinIsString(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*String); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsInt(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Int); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsFloat(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Float); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsBool(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Bool); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsChar(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Char); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsBytes(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Bytes); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsArray(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Array); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsImmutableArray(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*ImmutableArray); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsMap(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Map); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsImmutableMap(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*ImmutableMap); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsTime(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Time); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsError(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(*Error); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsUndefined(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if args[0] == UndefinedValue {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsFunction(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- switch args[0].(type) {
- case *CompiledFunction, *Closure:
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsCallable(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- switch args[0].(type) {
- case *CompiledFunction, *Closure, Callable: // BuiltinFunction is Callable
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
-
-func builtinIsIterable(args ...Object) (Object, error) {
- if len(args) != 1 {
- return nil, ErrWrongNumArguments
- }
-
- if _, ok := args[0].(Iterable); ok {
- return TrueValue, nil
- }
-
- return FalseValue, nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/builtins.go b/vendor/github.com/d5/tengo/objects/builtins.go
deleted file mode 100644
index 773636ec..00000000
--- a/vendor/github.com/d5/tengo/objects/builtins.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package objects
-
-// Builtins contains all default builtin functions.
-// Use GetBuiltinFunctions instead of accessing Builtins directly.
-var Builtins = []*BuiltinFunction{
- {
- Name: "len",
- Value: builtinLen,
- },
- {
- Name: "copy",
- Value: builtinCopy,
- },
- {
- Name: "append",
- Value: builtinAppend,
- },
- {
- Name: "string",
- Value: builtinString,
- },
- {
- Name: "int",
- Value: builtinInt,
- },
- {
- Name: "bool",
- Value: builtinBool,
- },
- {
- Name: "float",
- Value: builtinFloat,
- },
- {
- Name: "char",
- Value: builtinChar,
- },
- {
- Name: "bytes",
- Value: builtinBytes,
- },
- {
- Name: "time",
- Value: builtinTime,
- },
- {
- Name: "is_int",
- Value: builtinIsInt,
- },
- {
- Name: "is_float",
- Value: builtinIsFloat,
- },
- {
- Name: "is_string",
- Value: builtinIsString,
- },
- {
- Name: "is_bool",
- Value: builtinIsBool,
- },
- {
- Name: "is_char",
- Value: builtinIsChar,
- },
- {
- Name: "is_bytes",
- Value: builtinIsBytes,
- },
- {
- Name: "is_array",
- Value: builtinIsArray,
- },
- {
- Name: "is_immutable_array",
- Value: builtinIsImmutableArray,
- },
- {
- Name: "is_map",
- Value: builtinIsMap,
- },
- {
- Name: "is_immutable_map",
- Value: builtinIsImmutableMap,
- },
- {
- Name: "is_iterable",
- Value: builtinIsIterable,
- },
- {
- Name: "is_time",
- Value: builtinIsTime,
- },
- {
- Name: "is_error",
- Value: builtinIsError,
- },
- {
- Name: "is_undefined",
- Value: builtinIsUndefined,
- },
- {
- Name: "is_function",
- Value: builtinIsFunction,
- },
- {
- Name: "is_callable",
- Value: builtinIsCallable,
- },
- {
- Name: "type_name",
- Value: builtinTypeName,
- },
- {
- Name: "format",
- Value: builtinFormat,
- },
-}
diff --git a/vendor/github.com/d5/tengo/objects/bytes.go b/vendor/github.com/d5/tengo/objects/bytes.go
deleted file mode 100644
index 5159c22f..00000000
--- a/vendor/github.com/d5/tengo/objects/bytes.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package objects
-
-import (
- "bytes"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/compiler/token"
-)
-
-// Bytes represents a byte array.
-type Bytes struct {
- Value []byte
-}
-
-func (o *Bytes) String() string {
- return string(o.Value)
-}
-
-// TypeName returns the name of the type.
-func (o *Bytes) TypeName() string {
- return "bytes"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Bytes) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch op {
- case token.Add:
- switch rhs := rhs.(type) {
- case *Bytes:
- if len(o.Value)+len(rhs.Value) > tengo.MaxBytesLen {
- return nil, ErrBytesLimit
- }
-
- return &Bytes{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Bytes) Copy() Object {
- return &Bytes{Value: append([]byte{}, o.Value...)}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Bytes) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Bytes) Equals(x Object) bool {
- t, ok := x.(*Bytes)
- if !ok {
- return false
- }
-
- return bytes.Equal(o.Value, t.Value)
-}
-
-// IndexGet returns an element (as Int) at a given index.
-func (o *Bytes) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- idxVal := int(intIdx.Value)
-
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
-
- res = &Int{Value: int64(o.Value[idxVal])}
-
- return
-}
-
-// Iterate creates a bytes iterator.
-func (o *Bytes) Iterate() Iterator {
- return &BytesIterator{
- v: o.Value,
- l: len(o.Value),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/bytes_iterator.go b/vendor/github.com/d5/tengo/objects/bytes_iterator.go
deleted file mode 100644
index 18a36e17..00000000
--- a/vendor/github.com/d5/tengo/objects/bytes_iterator.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// BytesIterator represents an iterator for a string.
-type BytesIterator struct {
- v []byte
- i int
- l int
-}
-
-// TypeName returns the name of the type.
-func (i *BytesIterator) TypeName() string {
- return "bytes-iterator"
-}
-
-func (i *BytesIterator) String() string {
- return "<bytes-iterator>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (i *BytesIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (i *BytesIterator) IsFalsy() bool {
- return true
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (i *BytesIterator) Equals(Object) bool {
- return false
-}
-
-// Copy returns a copy of the type.
-func (i *BytesIterator) Copy() Object {
- return &BytesIterator{v: i.v, i: i.i, l: i.l}
-}
-
-// Next returns true if there are more elements to iterate.
-func (i *BytesIterator) Next() bool {
- i.i++
- return i.i <= i.l
-}
-
-// Key returns the key or index value of the current element.
-func (i *BytesIterator) Key() Object {
- return &Int{Value: int64(i.i - 1)}
-}
-
-// Value returns the value of the current element.
-func (i *BytesIterator) Value() Object {
- return &Int{Value: int64(i.v[i.i-1])}
-}
diff --git a/vendor/github.com/d5/tengo/objects/callable.go b/vendor/github.com/d5/tengo/objects/callable.go
deleted file mode 100644
index a066e1b9..00000000
--- a/vendor/github.com/d5/tengo/objects/callable.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package objects
-
-// Callable represents an object that can be called like a function.
-type Callable interface {
- // Call should take an arbitrary number of arguments
- // and returns a return value and/or an error,
- // which the VM will consider as a run-time error.
- Call(args ...Object) (ret Object, err error)
-}
diff --git a/vendor/github.com/d5/tengo/objects/callable_func.go b/vendor/github.com/d5/tengo/objects/callable_func.go
deleted file mode 100644
index ad25e65d..00000000
--- a/vendor/github.com/d5/tengo/objects/callable_func.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package objects
-
-// CallableFunc is a function signature for the callable functions.
-type CallableFunc = func(args ...Object) (ret Object, err error)
diff --git a/vendor/github.com/d5/tengo/objects/char.go b/vendor/github.com/d5/tengo/objects/char.go
deleted file mode 100644
index 4458bd12..00000000
--- a/vendor/github.com/d5/tengo/objects/char.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// Char represents a character value.
-type Char struct {
- Value rune
-}
-
-func (o *Char) String() string {
- return string(o.Value)
-}
-
-// TypeName returns the name of the type.
-func (o *Char) TypeName() string {
- return "char"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Char:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + rune(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Sub:
- r := o.Value - rune(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Char{Value: r}, nil
- case token.Less:
- if int64(o.Value) < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if int64(o.Value) > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if int64(o.Value) <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if int64(o.Value) >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Char) Copy() Object {
- return &Char{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Char) IsFalsy() bool {
- return o.Value == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Char) Equals(x Object) bool {
- t, ok := x.(*Char)
- if !ok {
- return false
- }
-
- return o.Value == t.Value
-}
diff --git a/vendor/github.com/d5/tengo/objects/closure.go b/vendor/github.com/d5/tengo/objects/closure.go
deleted file mode 100644
index 06058b23..00000000
--- a/vendor/github.com/d5/tengo/objects/closure.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// Closure represents a function closure.
-type Closure struct {
- Fn *CompiledFunction
- Free []*ObjectPtr
-}
-
-// TypeName returns the name of the type.
-func (o *Closure) TypeName() string {
- return "closure"
-}
-
-func (o *Closure) String() string {
- return "<closure>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Closure) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Closure) Copy() Object {
- return &Closure{
- Fn: o.Fn.Copy().(*CompiledFunction),
- Free: append([]*ObjectPtr{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
- }
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Closure) IsFalsy() bool {
- return false
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Closure) Equals(x Object) bool {
- return false
-}
diff --git a/vendor/github.com/d5/tengo/objects/compiled_function.go b/vendor/github.com/d5/tengo/objects/compiled_function.go
deleted file mode 100644
index d42e69ec..00000000
--- a/vendor/github.com/d5/tengo/objects/compiled_function.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
-)
-
-// CompiledFunction represents a compiled function.
-type CompiledFunction struct {
- Instructions []byte
- NumLocals int // number of local variables (including function parameters)
- NumParameters int
- VarArgs bool
- SourceMap map[int]source.Pos
-}
-
-// TypeName returns the name of the type.
-func (o *CompiledFunction) TypeName() string {
- return "compiled-function"
-}
-
-func (o *CompiledFunction) String() string {
- return "<compiled-function>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *CompiledFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *CompiledFunction) Copy() Object {
- return &CompiledFunction{
- Instructions: append([]byte{}, o.Instructions...),
- NumLocals: o.NumLocals,
- NumParameters: o.NumParameters,
- VarArgs: o.VarArgs,
- }
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *CompiledFunction) IsFalsy() bool {
- return false
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *CompiledFunction) Equals(x Object) bool {
- return false
-}
-
-// SourcePos returns the source position of the instruction at ip.
-func (o *CompiledFunction) SourcePos(ip int) source.Pos {
- for ip >= 0 {
- if p, ok := o.SourceMap[ip]; ok {
- return p
- }
- ip--
- }
- return source.NoPos
-}
diff --git a/vendor/github.com/d5/tengo/objects/count_objects.go b/vendor/github.com/d5/tengo/objects/count_objects.go
deleted file mode 100644
index 8c482eb3..00000000
--- a/vendor/github.com/d5/tengo/objects/count_objects.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package objects
-
-// CountObjects returns the number of objects that a given object o contains.
-// For scalar value types, it will always be 1. For compound value types,
-// this will include its elements and all of their elements recursively.
-func CountObjects(o Object) (c int) {
- c = 1
-
- switch o := o.(type) {
- case *Array:
- for _, v := range o.Value {
- c += CountObjects(v)
- }
- case *ImmutableArray:
- for _, v := range o.Value {
- c += CountObjects(v)
- }
- case *Map:
- for _, v := range o.Value {
- c += CountObjects(v)
- }
- case *ImmutableMap:
- for _, v := range o.Value {
- c += CountObjects(v)
- }
- case *Error:
- c += CountObjects(o.Value)
- }
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/objects/error.go b/vendor/github.com/d5/tengo/objects/error.go
deleted file mode 100644
index be21de03..00000000
--- a/vendor/github.com/d5/tengo/objects/error.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package objects
-
-import (
- "fmt"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Error represents a string value.
-type Error struct {
- Value Object
-}
-
-// TypeName returns the name of the type.
-func (o *Error) TypeName() string {
- return "error"
-}
-
-func (o *Error) String() string {
- if o.Value != nil {
- return fmt.Sprintf("error: %s", o.Value.String())
- }
-
- return "error"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Error) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Error) IsFalsy() bool {
- return true // error is always false.
-}
-
-// Copy returns a copy of the type.
-func (o *Error) Copy() Object {
- return &Error{Value: o.Value.Copy()}
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Error) Equals(x Object) bool {
- return o == x // pointer equality
-}
diff --git a/vendor/github.com/d5/tengo/objects/errors.go b/vendor/github.com/d5/tengo/objects/errors.go
deleted file mode 100644
index bcd480a1..00000000
--- a/vendor/github.com/d5/tengo/objects/errors.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package objects
-
-import (
- "errors"
- "fmt"
-)
-
-// ErrIndexOutOfBounds is an error where a given index is out of the bounds.
-var ErrIndexOutOfBounds = errors.New("index out of bounds")
-
-// ErrInvalidIndexType represents an invalid index type.
-var ErrInvalidIndexType = errors.New("invalid index type")
-
-// ErrInvalidIndexValueType represents an invalid index value type.
-var ErrInvalidIndexValueType = errors.New("invalid index value type")
-
-// ErrInvalidOperator represents an error for invalid operator usage.
-var ErrInvalidOperator = errors.New("invalid operator")
-
-// ErrWrongNumArguments represents a wrong number of arguments error.
-var ErrWrongNumArguments = errors.New("wrong number of arguments")
-
-// ErrBytesLimit represents an error where the size of bytes value exceeds the limit.
-var ErrBytesLimit = errors.New("exceeding bytes size limit")
-
-// ErrStringLimit represents an error where the size of string value exceeds the limit.
-var ErrStringLimit = errors.New("exceeding string size limit")
-
-// ErrInvalidArgumentType represents an invalid argument value type error.
-type ErrInvalidArgumentType struct {
- Name string
- Expected string
- Found string
-}
-
-func (e ErrInvalidArgumentType) Error() string {
- return fmt.Sprintf("invalid type for argument '%s': expected %s, found %s", e.Name, e.Expected, e.Found)
-}
diff --git a/vendor/github.com/d5/tengo/objects/float.go b/vendor/github.com/d5/tengo/objects/float.go
deleted file mode 100644
index 65997303..00000000
--- a/vendor/github.com/d5/tengo/objects/float.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package objects
-
-import (
- "math"
- "strconv"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Float represents a floating point number value.
-type Float struct {
- Value float64
-}
-
-func (o *Float) String() string {
- return strconv.FormatFloat(o.Value, 'f', -1, 64)
-}
-
-// TypeName returns the name of the type.
-func (o *Float) TypeName() string {
- return "float"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Float:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Mul:
- r := o.Value * rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Quo:
- r := o.Value / rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Sub:
- r := o.Value - float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Mul:
- r := o.Value * float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Quo:
- r := o.Value / float64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Float{Value: r}, nil
- case token.Less:
- if o.Value < float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= float64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Float) Copy() Object {
- return &Float{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Float) IsFalsy() bool {
- return math.IsNaN(o.Value)
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Float) Equals(x Object) bool {
- t, ok := x.(*Float)
- if !ok {
- return false
- }
-
- return o.Value == t.Value
-}
diff --git a/vendor/github.com/d5/tengo/objects/immutable_array.go b/vendor/github.com/d5/tengo/objects/immutable_array.go
deleted file mode 100644
index f3621e29..00000000
--- a/vendor/github.com/d5/tengo/objects/immutable_array.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package objects
-
-import (
- "fmt"
- "strings"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// ImmutableArray represents an immutable array of objects.
-type ImmutableArray struct {
- Value []Object
-}
-
-// TypeName returns the name of the type.
-func (o *ImmutableArray) TypeName() string {
- return "immutable-array"
-}
-
-func (o *ImmutableArray) String() string {
- var elements []string
- for _, e := range o.Value {
- elements = append(elements, e.String())
- }
-
- return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *ImmutableArray) BinaryOp(op token.Token, rhs Object) (Object, error) {
- if rhs, ok := rhs.(*ImmutableArray); ok {
- switch op {
- case token.Add:
- return &Array{Value: append(o.Value, rhs.Value...)}, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *ImmutableArray) Copy() Object {
- var c []Object
- for _, elem := range o.Value {
- c = append(c, elem.Copy())
- }
-
- return &Array{Value: c}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *ImmutableArray) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *ImmutableArray) Equals(x Object) bool {
- var xVal []Object
- switch x := x.(type) {
- case *Array:
- xVal = x.Value
- case *ImmutableArray:
- xVal = x.Value
- default:
- return false
- }
-
- if len(o.Value) != len(xVal) {
- return false
- }
-
- for i, e := range o.Value {
- if !e.Equals(xVal[i]) {
- return false
- }
- }
-
- return true
-}
-
-// IndexGet returns an element at a given index.
-func (o *ImmutableArray) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- idxVal := int(intIdx.Value)
-
- if idxVal < 0 || idxVal >= len(o.Value) {
- res = UndefinedValue
- return
- }
-
- res = o.Value[idxVal]
-
- return
-}
-
-// Iterate creates an array iterator.
-func (o *ImmutableArray) Iterate() Iterator {
- return &ArrayIterator{
- v: o.Value,
- l: len(o.Value),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/immutable_map.go b/vendor/github.com/d5/tengo/objects/immutable_map.go
deleted file mode 100644
index 8f58701b..00000000
--- a/vendor/github.com/d5/tengo/objects/immutable_map.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package objects
-
-import (
- "fmt"
- "strings"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// ImmutableMap represents an immutable map object.
-type ImmutableMap struct {
- Value map[string]Object
-}
-
-// TypeName returns the name of the type.
-func (o *ImmutableMap) TypeName() string {
- return "immutable-map"
-}
-
-func (o *ImmutableMap) String() string {
- var pairs []string
- for k, v := range o.Value {
- pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
- }
-
- return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *ImmutableMap) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *ImmutableMap) Copy() Object {
- c := make(map[string]Object)
- for k, v := range o.Value {
- c[k] = v.Copy()
- }
-
- return &Map{Value: c}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *ImmutableMap) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// IndexGet returns the value for the given key.
-func (o *ImmutableMap) IndexGet(index Object) (res Object, err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- val, ok := o.Value[strIdx]
- if !ok {
- val = UndefinedValue
- }
-
- return val, nil
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *ImmutableMap) Equals(x Object) bool {
- var xVal map[string]Object
- switch x := x.(type) {
- case *Map:
- xVal = x.Value
- case *ImmutableMap:
- xVal = x.Value
- default:
- return false
- }
-
- if len(o.Value) != len(xVal) {
- return false
- }
-
- for k, v := range o.Value {
- tv := xVal[k]
- if !v.Equals(tv) {
- return false
- }
- }
-
- return true
-}
-
-// Iterate creates an immutable map iterator.
-func (o *ImmutableMap) Iterate() Iterator {
- var keys []string
- for k := range o.Value {
- keys = append(keys, k)
- }
-
- return &MapIterator{
- v: o.Value,
- k: keys,
- l: len(keys),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/importable.go b/vendor/github.com/d5/tengo/objects/importable.go
deleted file mode 100644
index 9fd86ae8..00000000
--- a/vendor/github.com/d5/tengo/objects/importable.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package objects
-
-// Importable interface represents importable module instance.
-type Importable interface {
- // Import should return either an Object or module source code ([]byte).
- Import(moduleName string) (interface{}, error)
-}
diff --git a/vendor/github.com/d5/tengo/objects/index_assignable.go b/vendor/github.com/d5/tengo/objects/index_assignable.go
deleted file mode 100644
index a1c6cbff..00000000
--- a/vendor/github.com/d5/tengo/objects/index_assignable.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package objects
-
-// IndexAssignable is an object that can take an index and a value
-// on the left-hand side of the assignment statement.
-type IndexAssignable interface {
- // IndexSet should take an index Object and a value Object.
- // If an error is returned, it will be treated as a run-time error.
- IndexSet(index, value Object) error
-}
diff --git a/vendor/github.com/d5/tengo/objects/indexable.go b/vendor/github.com/d5/tengo/objects/indexable.go
deleted file mode 100644
index bbc81633..00000000
--- a/vendor/github.com/d5/tengo/objects/indexable.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package objects
-
-// Indexable is an object that can take an index and return an object.
-type Indexable interface {
- // IndexGet should take an index Object and return a result Object or an error.
- // If error is returned, the runtime will treat it as a run-time error and ignore returned value.
- // If nil is returned as value, it will be converted to Undefined value by the runtime.
- IndexGet(index Object) (value Object, err error)
-}
diff --git a/vendor/github.com/d5/tengo/objects/int.go b/vendor/github.com/d5/tengo/objects/int.go
deleted file mode 100644
index e902c93a..00000000
--- a/vendor/github.com/d5/tengo/objects/int.go
+++ /dev/null
@@ -1,198 +0,0 @@
-package objects
-
-import (
- "strconv"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Int represents an integer value.
-type Int struct {
- Value int64
-}
-
-func (o *Int) String() string {
- return strconv.FormatInt(o.Value, 10)
-}
-
-// TypeName returns the name of the type.
-func (o *Int) TypeName() string {
- return "int"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Int:
- switch op {
- case token.Add:
- r := o.Value + rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Sub:
- r := o.Value - rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Mul:
- r := o.Value * rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Quo:
- r := o.Value / rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Rem:
- r := o.Value % rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.And:
- r := o.Value & rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Or:
- r := o.Value | rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Xor:
- r := o.Value ^ rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.AndNot:
- r := o.Value &^ rhs.Value
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Shl:
- r := o.Value << uint64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Shr:
- r := o.Value >> uint64(rhs.Value)
- if r == o.Value {
- return o, nil
- }
- return &Int{Value: r}, nil
- case token.Less:
- if o.Value < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Float:
- switch op {
- case token.Add:
- return &Float{float64(o.Value) + rhs.Value}, nil
- case token.Sub:
- return &Float{float64(o.Value) - rhs.Value}, nil
- case token.Mul:
- return &Float{float64(o.Value) * rhs.Value}, nil
- case token.Quo:
- return &Float{float64(o.Value) / rhs.Value}, nil
- case token.Less:
- if float64(o.Value) < rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if float64(o.Value) > rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if float64(o.Value) <= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if float64(o.Value) >= rhs.Value {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- case *Char:
- switch op {
- case token.Add:
- return &Char{rune(o.Value) + rhs.Value}, nil
- case token.Sub:
- return &Char{rune(o.Value) - rhs.Value}, nil
- case token.Less:
- if o.Value < int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value > int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value <= int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value >= int64(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Int) Copy() Object {
- return &Int{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Int) IsFalsy() bool {
- return o.Value == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Int) Equals(x Object) bool {
- t, ok := x.(*Int)
- if !ok {
- return false
- }
-
- return o.Value == t.Value
-}
diff --git a/vendor/github.com/d5/tengo/objects/iterable.go b/vendor/github.com/d5/tengo/objects/iterable.go
deleted file mode 100644
index e431d3d7..00000000
--- a/vendor/github.com/d5/tengo/objects/iterable.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package objects
-
-// Iterable represents an object that has iterator.
-type Iterable interface {
- // Iterate should return an Iterator for the type.
- Iterate() Iterator
-}
diff --git a/vendor/github.com/d5/tengo/objects/iterator.go b/vendor/github.com/d5/tengo/objects/iterator.go
deleted file mode 100644
index 01522ba5..00000000
--- a/vendor/github.com/d5/tengo/objects/iterator.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package objects
-
-// Iterator represents an iterator for underlying data type.
-type Iterator interface {
- Object
-
- // Next returns true if there are more elements to iterate.
- Next() bool
-
- // Key returns the key or index value of the current element.
- Key() Object
-
- // Value returns the value of the current element.
- Value() Object
-}
diff --git a/vendor/github.com/d5/tengo/objects/map.go b/vendor/github.com/d5/tengo/objects/map.go
deleted file mode 100644
index 9208872c..00000000
--- a/vendor/github.com/d5/tengo/objects/map.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package objects
-
-import (
- "fmt"
- "strings"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Map represents a map of objects.
-type Map struct {
- Value map[string]Object
-}
-
-// TypeName returns the name of the type.
-func (o *Map) TypeName() string {
- return "map"
-}
-
-func (o *Map) String() string {
- var pairs []string
- for k, v := range o.Value {
- pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
- }
-
- return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Map) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Map) Copy() Object {
- c := make(map[string]Object)
- for k, v := range o.Value {
- c[k] = v.Copy()
- }
-
- return &Map{Value: c}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Map) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Map) Equals(x Object) bool {
- var xVal map[string]Object
- switch x := x.(type) {
- case *Map:
- xVal = x.Value
- case *ImmutableMap:
- xVal = x.Value
- default:
- return false
- }
-
- if len(o.Value) != len(xVal) {
- return false
- }
-
- for k, v := range o.Value {
- tv := xVal[k]
- if !v.Equals(tv) {
- return false
- }
- }
-
- return true
-}
-
-// IndexGet returns the value for the given key.
-func (o *Map) IndexGet(index Object) (res Object, err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- val, ok := o.Value[strIdx]
- if !ok {
- val = UndefinedValue
- }
-
- return val, nil
-}
-
-// IndexSet sets the value for the given key.
-func (o *Map) IndexSet(index, value Object) (err error) {
- strIdx, ok := ToString(index)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- o.Value[strIdx] = value
-
- return nil
-}
-
-// Iterate creates a map iterator.
-func (o *Map) Iterate() Iterator {
- var keys []string
- for k := range o.Value {
- keys = append(keys, k)
- }
-
- return &MapIterator{
- v: o.Value,
- k: keys,
- l: len(keys),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/map_iterator.go b/vendor/github.com/d5/tengo/objects/map_iterator.go
deleted file mode 100644
index d60dd0e1..00000000
--- a/vendor/github.com/d5/tengo/objects/map_iterator.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// MapIterator represents an iterator for the map.
-type MapIterator struct {
- v map[string]Object
- k []string
- i int
- l int
-}
-
-// TypeName returns the name of the type.
-func (i *MapIterator) TypeName() string {
- return "map-iterator"
-}
-
-func (i *MapIterator) String() string {
- return "<map-iterator>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (i *MapIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (i *MapIterator) IsFalsy() bool {
- return true
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (i *MapIterator) Equals(Object) bool {
- return false
-}
-
-// Copy returns a copy of the type.
-func (i *MapIterator) Copy() Object {
- return &MapIterator{v: i.v, k: i.k, i: i.i, l: i.l}
-}
-
-// Next returns true if there are more elements to iterate.
-func (i *MapIterator) Next() bool {
- i.i++
- return i.i <= i.l
-}
-
-// Key returns the key or index value of the current element.
-func (i *MapIterator) Key() Object {
- k := i.k[i.i-1]
-
- return &String{Value: k}
-}
-
-// Value returns the value of the current element.
-func (i *MapIterator) Value() Object {
- k := i.k[i.i-1]
-
- return i.v[k]
-}
diff --git a/vendor/github.com/d5/tengo/objects/object.go b/vendor/github.com/d5/tengo/objects/object.go
deleted file mode 100644
index 4c5aa7ae..00000000
--- a/vendor/github.com/d5/tengo/objects/object.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// Object represents an object in the VM.
-type Object interface {
- // TypeName should return the name of the type.
- TypeName() string
-
- // String should return a string representation of the type's value.
- String() string
-
- // BinaryOp should return another object that is the result of
- // a given binary operator and a right-hand side object.
- // If BinaryOp returns an error, the VM will treat it as a run-time error.
- BinaryOp(op token.Token, rhs Object) (Object, error)
-
- // IsFalsy should return true if the value of the type
- // should be considered as falsy.
- IsFalsy() bool
-
- // Equals should return true if the value of the type
- // should be considered as equal to the value of another object.
- Equals(another Object) bool
-
- // Copy should return a copy of the type (and its value).
- // Copy function will be used for copy() builtin function
- // which is expected to deep-copy the values generally.
- Copy() Object
-}
diff --git a/vendor/github.com/d5/tengo/objects/object_ptr.go b/vendor/github.com/d5/tengo/objects/object_ptr.go
deleted file mode 100644
index 2c87c561..00000000
--- a/vendor/github.com/d5/tengo/objects/object_ptr.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// ObjectPtr represents a free variable.
-type ObjectPtr struct {
- Value *Object
-}
-
-func (o *ObjectPtr) String() string {
- return "free-var"
-}
-
-// TypeName returns the name of the type.
-func (o *ObjectPtr) TypeName() string {
- return "<free-var>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *ObjectPtr) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *ObjectPtr) Copy() Object {
- return o
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *ObjectPtr) IsFalsy() bool {
- return o.Value == nil
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *ObjectPtr) Equals(x Object) bool {
- return o == x
-}
diff --git a/vendor/github.com/d5/tengo/objects/objects.go b/vendor/github.com/d5/tengo/objects/objects.go
deleted file mode 100644
index f3878b11..00000000
--- a/vendor/github.com/d5/tengo/objects/objects.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package objects
-
-var (
- // TrueValue represents a true value.
- TrueValue Object = &Bool{value: true}
-
- // FalseValue represents a false value.
- FalseValue Object = &Bool{value: false}
-
- // UndefinedValue represents an undefined value.
- UndefinedValue Object = &Undefined{}
-)
diff --git a/vendor/github.com/d5/tengo/objects/source_module.go b/vendor/github.com/d5/tengo/objects/source_module.go
deleted file mode 100644
index 577fddf2..00000000
--- a/vendor/github.com/d5/tengo/objects/source_module.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package objects
-
-// SourceModule is an importable module that's written in Tengo.
-type SourceModule struct {
- Src []byte
-}
-
-// Import returns a module source code.
-func (m *SourceModule) Import(_ string) (interface{}, error) {
- return m.Src, nil
-}
diff --git a/vendor/github.com/d5/tengo/objects/string.go b/vendor/github.com/d5/tengo/objects/string.go
deleted file mode 100644
index c25b0502..00000000
--- a/vendor/github.com/d5/tengo/objects/string.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package objects
-
-import (
- "strconv"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/compiler/token"
-)
-
-// String represents a string value.
-type String struct {
- Value string
- runeStr []rune
-}
-
-// TypeName returns the name of the type.
-func (o *String) TypeName() string {
- return "string"
-}
-
-func (o *String) String() string {
- return strconv.Quote(o.Value)
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *String) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch op {
- case token.Add:
- switch rhs := rhs.(type) {
- case *String:
- if len(o.Value)+len(rhs.Value) > tengo.MaxStringLen {
- return nil, ErrStringLimit
- }
- return &String{Value: o.Value + rhs.Value}, nil
- default:
- rhsStr := rhs.String()
- if len(o.Value)+len(rhsStr) > tengo.MaxStringLen {
- return nil, ErrStringLimit
- }
- return &String{Value: o.Value + rhsStr}, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *String) IsFalsy() bool {
- return len(o.Value) == 0
-}
-
-// Copy returns a copy of the type.
-func (o *String) Copy() Object {
- return &String{Value: o.Value}
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *String) Equals(x Object) bool {
- t, ok := x.(*String)
- if !ok {
- return false
- }
-
- return o.Value == t.Value
-}
-
-// IndexGet returns a character at a given index.
-func (o *String) IndexGet(index Object) (res Object, err error) {
- intIdx, ok := index.(*Int)
- if !ok {
- err = ErrInvalidIndexType
- return
- }
-
- idxVal := int(intIdx.Value)
-
- if o.runeStr == nil {
- o.runeStr = []rune(o.Value)
- }
-
- if idxVal < 0 || idxVal >= len(o.runeStr) {
- res = UndefinedValue
- return
- }
-
- res = &Char{Value: o.runeStr[idxVal]}
-
- return
-}
-
-// Iterate creates a string iterator.
-func (o *String) Iterate() Iterator {
- if o.runeStr == nil {
- o.runeStr = []rune(o.Value)
- }
-
- return &StringIterator{
- v: o.runeStr,
- l: len(o.runeStr),
- }
-}
diff --git a/vendor/github.com/d5/tengo/objects/string_iterator.go b/vendor/github.com/d5/tengo/objects/string_iterator.go
deleted file mode 100644
index 8bc95eb5..00000000
--- a/vendor/github.com/d5/tengo/objects/string_iterator.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// StringIterator represents an iterator for a string.
-type StringIterator struct {
- v []rune
- i int
- l int
-}
-
-// TypeName returns the name of the type.
-func (i *StringIterator) TypeName() string {
- return "string-iterator"
-}
-
-func (i *StringIterator) String() string {
- return "<string-iterator>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (i *StringIterator) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (i *StringIterator) IsFalsy() bool {
- return true
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (i *StringIterator) Equals(Object) bool {
- return false
-}
-
-// Copy returns a copy of the type.
-func (i *StringIterator) Copy() Object {
- return &StringIterator{v: i.v, i: i.i, l: i.l}
-}
-
-// Next returns true if there are more elements to iterate.
-func (i *StringIterator) Next() bool {
- i.i++
- return i.i <= i.l
-}
-
-// Key returns the key or index value of the current element.
-func (i *StringIterator) Key() Object {
- return &Int{Value: int64(i.i - 1)}
-}
-
-// Value returns the value of the current element.
-func (i *StringIterator) Value() Object {
- return &Char{Value: i.v[i.i-1]}
-}
diff --git a/vendor/github.com/d5/tengo/objects/time.go b/vendor/github.com/d5/tengo/objects/time.go
deleted file mode 100644
index 4e783cc8..00000000
--- a/vendor/github.com/d5/tengo/objects/time.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package objects
-
-import (
- "time"
-
- "github.com/d5/tengo/compiler/token"
-)
-
-// Time represents a time value.
-type Time struct {
- Value time.Time
-}
-
-func (o *Time) String() string {
- return o.Value.String()
-}
-
-// TypeName returns the name of the type.
-func (o *Time) TypeName() string {
- return "time"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
- switch rhs := rhs.(type) {
- case *Int:
- switch op {
- case token.Add: // time + int => time
- if rhs.Value == 0 {
- return o, nil
- }
- return &Time{Value: o.Value.Add(time.Duration(rhs.Value))}, nil
- case token.Sub: // time - int => time
- if rhs.Value == 0 {
- return o, nil
- }
- return &Time{Value: o.Value.Add(time.Duration(-rhs.Value))}, nil
- }
- case *Time:
- switch op {
- case token.Sub: // time - time => int (duration)
- return &Int{Value: int64(o.Value.Sub(rhs.Value))}, nil
- case token.Less: // time < time => bool
- if o.Value.Before(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.Greater:
- if o.Value.After(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.LessEq:
- if o.Value.Equal(rhs.Value) || o.Value.Before(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- case token.GreaterEq:
- if o.Value.Equal(rhs.Value) || o.Value.After(rhs.Value) {
- return TrueValue, nil
- }
- return FalseValue, nil
- }
- }
-
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Time) Copy() Object {
- return &Time{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Time) IsFalsy() bool {
- return o.Value.IsZero()
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Time) Equals(x Object) bool {
- t, ok := x.(*Time)
- if !ok {
- return false
- }
-
- return o.Value.Equal(t.Value)
-}
diff --git a/vendor/github.com/d5/tengo/objects/undefined.go b/vendor/github.com/d5/tengo/objects/undefined.go
deleted file mode 100644
index 0fdbc084..00000000
--- a/vendor/github.com/d5/tengo/objects/undefined.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package objects
-
-import "github.com/d5/tengo/compiler/token"
-
-// Undefined represents an undefined value.
-type Undefined struct{}
-
-// TypeName returns the name of the type.
-func (o *Undefined) TypeName() string {
- return "undefined"
-}
-
-func (o *Undefined) String() string {
- return "<undefined>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *Undefined) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *Undefined) Copy() Object {
- return o
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *Undefined) IsFalsy() bool {
- return true
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *Undefined) Equals(x Object) bool {
- return o == x
-}
-
-// IndexGet returns an element at a given index.
-func (o *Undefined) IndexGet(index Object) (Object, error) {
- return UndefinedValue, nil
-}
-
-// Iterate creates a map iterator.
-func (o *Undefined) Iterate() Iterator {
- return o
-}
-
-// Next returns true if there are more elements to iterate.
-func (o *Undefined) Next() bool {
- return false
-}
-
-// Key returns the key or index value of the current element.
-func (o *Undefined) Key() Object {
- return o
-}
-
-// Value returns the value of the current element.
-func (o *Undefined) Value() Object {
- return o
-}
diff --git a/vendor/github.com/d5/tengo/objects/user_function.go b/vendor/github.com/d5/tengo/objects/user_function.go
deleted file mode 100644
index a896788b..00000000
--- a/vendor/github.com/d5/tengo/objects/user_function.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package objects
-
-import (
- "github.com/d5/tengo/compiler/token"
-)
-
-// UserFunction represents a user function.
-type UserFunction struct {
- Name string
- Value CallableFunc
- EncodingID string
-}
-
-// TypeName returns the name of the type.
-func (o *UserFunction) TypeName() string {
- return "user-function:" + o.Name
-}
-
-func (o *UserFunction) String() string {
- return "<user-function>"
-}
-
-// BinaryOp returns another object that is the result of
-// a given binary operator and a right-hand side object.
-func (o *UserFunction) BinaryOp(op token.Token, rhs Object) (Object, error) {
- return nil, ErrInvalidOperator
-}
-
-// Copy returns a copy of the type.
-func (o *UserFunction) Copy() Object {
- return &UserFunction{Value: o.Value}
-}
-
-// IsFalsy returns true if the value of the type is falsy.
-func (o *UserFunction) IsFalsy() bool {
- return false
-}
-
-// Equals returns true if the value of the type
-// is equal to the value of another object.
-func (o *UserFunction) Equals(x Object) bool {
- return false
-}
-
-// Call invokes a user function.
-func (o *UserFunction) Call(args ...Object) (Object, error) {
- return o.Value(args...)
-}
diff --git a/vendor/github.com/d5/tengo/runtime/errors.go b/vendor/github.com/d5/tengo/runtime/errors.go
deleted file mode 100644
index fc7ca0e9..00000000
--- a/vendor/github.com/d5/tengo/runtime/errors.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package runtime
-
-import (
- "errors"
-)
-
-// ErrStackOverflow is a stack overflow error.
-var ErrStackOverflow = errors.New("stack overflow")
-
-// ErrObjectAllocLimit is an objects allocation limit error.
-var ErrObjectAllocLimit = errors.New("object allocation limit exceeded")
diff --git a/vendor/github.com/d5/tengo/runtime/frame.go b/vendor/github.com/d5/tengo/runtime/frame.go
deleted file mode 100644
index cbaadbdb..00000000
--- a/vendor/github.com/d5/tengo/runtime/frame.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package runtime
-
-import (
- "github.com/d5/tengo/objects"
-)
-
-// Frame represents a function call frame.
-type Frame struct {
- fn *objects.CompiledFunction
- freeVars []*objects.ObjectPtr
- ip int
- basePointer int
-}
diff --git a/vendor/github.com/d5/tengo/script/compiled.go b/vendor/github.com/d5/tengo/script/compiled.go
deleted file mode 100644
index ce50f498..00000000
--- a/vendor/github.com/d5/tengo/script/compiled.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package script
-
-import (
- "context"
- "fmt"
- "sync"
-
- "github.com/d5/tengo/compiler"
- "github.com/d5/tengo/objects"
- "github.com/d5/tengo/runtime"
-)
-
-// Compiled is a compiled instance of the user script.
-// Use Script.Compile() to create Compiled object.
-type Compiled struct {
- globalIndexes map[string]int // global symbol name to index
- bytecode *compiler.Bytecode
- globals []objects.Object
- maxAllocs int64
- lock sync.RWMutex
-}
-
-// Run executes the compiled script in the virtual machine.
-func (c *Compiled) Run() error {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- v := runtime.NewVM(c.bytecode, c.globals, c.maxAllocs)
-
- return v.Run()
-}
-
-// RunContext is like Run but includes a context.
-func (c *Compiled) RunContext(ctx context.Context) (err error) {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- v := runtime.NewVM(c.bytecode, c.globals, c.maxAllocs)
-
- ch := make(chan error, 1)
-
- go func() {
- ch <- v.Run()
- }()
-
- select {
- case <-ctx.Done():
- v.Abort()
- <-ch
- err = ctx.Err()
- case err = <-ch:
- }
-
- return
-}
-
-// Clone creates a new copy of Compiled.
-// Cloned copies are safe for concurrent use by multiple goroutines.
-func (c *Compiled) Clone() *Compiled {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- clone := &Compiled{
- globalIndexes: c.globalIndexes,
- bytecode: c.bytecode,
- globals: make([]objects.Object, len(c.globals)),
- maxAllocs: c.maxAllocs,
- }
-
- // copy global objects
- for idx, g := range c.globals {
- if g != nil {
- clone.globals[idx] = g
- }
- }
-
- return clone
-}
-
-// IsDefined returns true if the variable name is defined (has value) before or after the execution.
-func (c *Compiled) IsDefined(name string) bool {
- c.lock.RLock()
- defer c.lock.RUnlock()
-
- idx, ok := c.globalIndexes[name]
- if !ok {
- return false
- }
-
- v := c.globals[idx]
- if v == nil {
- return false
- }
-
- return v != objects.UndefinedValue
-}
-
-// Get returns a variable identified by the name.
-func (c *Compiled) Get(name string) *Variable {
- c.lock.RLock()
- defer c.lock.RUnlock()
-
- value := objects.UndefinedValue
-
- if idx, ok := c.globalIndexes[name]; ok {
- value = c.globals[idx]
- if value == nil {
- value = objects.UndefinedValue
- }
- }
-
- return &Variable{
- name: name,
- value: value,
- }
-}
-
-// GetAll returns all the variables that are defined by the compiled script.
-func (c *Compiled) GetAll() []*Variable {
- c.lock.RLock()
- defer c.lock.RUnlock()
-
- var vars []*Variable
-
- for name, idx := range c.globalIndexes {
- value := c.globals[idx]
- if value == nil {
- value = objects.UndefinedValue
- }
-
- vars = append(vars, &Variable{
- name: name,
- value: value,
- })
- }
-
- return vars
-}
-
-// Set replaces the value of a global variable identified by the name.
-// An error will be returned if the name was not defined during compilation.
-func (c *Compiled) Set(name string, value interface{}) error {
- c.lock.Lock()
- defer c.lock.Unlock()
-
- obj, err := objects.FromInterface(value)
- if err != nil {
- return err
- }
-
- idx, ok := c.globalIndexes[name]
- if !ok {
- return fmt.Errorf("'%s' is not defined", name)
- }
-
- c.globals[idx] = obj
-
- return nil
-}
diff --git a/vendor/github.com/d5/tengo/script/script.go b/vendor/github.com/d5/tengo/script/script.go
deleted file mode 100644
index 2ee67b61..00000000
--- a/vendor/github.com/d5/tengo/script/script.go
+++ /dev/null
@@ -1,185 +0,0 @@
-package script
-
-import (
- "context"
- "fmt"
-
- "github.com/d5/tengo/compiler"
- "github.com/d5/tengo/compiler/parser"
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/objects"
- "github.com/d5/tengo/runtime"
-)
-
-// Script can simplify compilation and execution of embedded scripts.
-type Script struct {
- variables map[string]*Variable
- modules *objects.ModuleMap
- input []byte
- maxAllocs int64
- maxConstObjects int
- enableFileImport bool
-}
-
-// New creates a Script instance with an input script.
-func New(input []byte) *Script {
- return &Script{
- variables: make(map[string]*Variable),
- input: input,
- maxAllocs: -1,
- maxConstObjects: -1,
- }
-}
-
-// Add adds a new variable or updates an existing variable to the script.
-func (s *Script) Add(name string, value interface{}) error {
- obj, err := objects.FromInterface(value)
- if err != nil {
- return err
- }
-
- s.variables[name] = &Variable{
- name: name,
- value: obj,
- }
-
- return nil
-}
-
-// Remove removes (undefines) an existing variable for the script.
-// It returns false if the variable name is not defined.
-func (s *Script) Remove(name string) bool {
- if _, ok := s.variables[name]; !ok {
- return false
- }
-
- delete(s.variables, name)
-
- return true
-}
-
-// SetImports sets import modules.
-func (s *Script) SetImports(modules *objects.ModuleMap) {
- s.modules = modules
-}
-
-// SetMaxAllocs sets the maximum number of objects allocations during the run time.
-// Compiled script will return runtime.ErrObjectAllocLimit error if it exceeds this limit.
-func (s *Script) SetMaxAllocs(n int64) {
- s.maxAllocs = n
-}
-
-// SetMaxConstObjects sets the maximum number of objects in the compiled constants.
-func (s *Script) SetMaxConstObjects(n int) {
- s.maxConstObjects = n
-}
-
-// EnableFileImport enables or disables module loading from local files.
-// Local file modules are disabled by default.
-func (s *Script) EnableFileImport(enable bool) {
- s.enableFileImport = enable
-}
-
-// Compile compiles the script with all the defined variables, and, returns Compiled object.
-func (s *Script) Compile() (*Compiled, error) {
- symbolTable, globals, err := s.prepCompile()
- if err != nil {
- return nil, err
- }
-
- fileSet := source.NewFileSet()
- srcFile := fileSet.AddFile("(main)", -1, len(s.input))
-
- p := parser.NewParser(srcFile, s.input, nil)
- file, err := p.ParseFile()
- if err != nil {
- return nil, err
- }
-
- c := compiler.NewCompiler(srcFile, symbolTable, nil, s.modules, nil)
- c.EnableFileImport(s.enableFileImport)
- if err := c.Compile(file); err != nil {
- return nil, err
- }
-
- // reduce globals size
- globals = globals[:symbolTable.MaxSymbols()+1]
-
- // global symbol names to indexes
- globalIndexes := make(map[string]int, len(globals))
- for _, name := range symbolTable.Names() {
- symbol, _, _ := symbolTable.Resolve(name)
- if symbol.Scope == compiler.ScopeGlobal {
- globalIndexes[name] = symbol.Index
- }
- }
-
- // remove duplicates from constants
- bytecode := c.Bytecode()
- bytecode.RemoveDuplicates()
-
- // check the constant objects limit
- if s.maxConstObjects >= 0 {
- cnt := bytecode.CountObjects()
- if cnt > s.maxConstObjects {
- return nil, fmt.Errorf("exceeding constant objects limit: %d", cnt)
- }
- }
-
- return &Compiled{
- globalIndexes: globalIndexes,
- bytecode: bytecode,
- globals: globals,
- maxAllocs: s.maxAllocs,
- }, nil
-}
-
-// Run compiles and runs the scripts.
-// Use returned compiled object to access global variables.
-func (s *Script) Run() (compiled *Compiled, err error) {
- compiled, err = s.Compile()
- if err != nil {
- return
- }
-
- err = compiled.Run()
-
- return
-}
-
-// RunContext is like Run but includes a context.
-func (s *Script) RunContext(ctx context.Context) (compiled *Compiled, err error) {
- compiled, err = s.Compile()
- if err != nil {
- return
- }
-
- err = compiled.RunContext(ctx)
-
- return
-}
-
-func (s *Script) prepCompile() (symbolTable *compiler.SymbolTable, globals []objects.Object, err error) {
- var names []string
- for name := range s.variables {
- names = append(names, name)
- }
-
- symbolTable = compiler.NewSymbolTable()
- for idx, fn := range objects.Builtins {
- symbolTable.DefineBuiltin(idx, fn.Name)
- }
-
- globals = make([]objects.Object, runtime.GlobalsSize)
-
- for idx, name := range names {
- symbol := symbolTable.Define(name)
- if symbol.Index != idx {
- panic(fmt.Errorf("wrong symbol index: %d != %d", idx, symbol.Index))
- }
-
- globals[symbol.Index] = s.variables[name].value
- }
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/base64.go b/vendor/github.com/d5/tengo/stdlib/base64.go
deleted file mode 100644
index 40a746ce..00000000
--- a/vendor/github.com/d5/tengo/stdlib/base64.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package stdlib
-
-import (
- "encoding/base64"
- "github.com/d5/tengo/objects"
-)
-
-var base64Module = map[string]objects.Object{
- "encode": &objects.UserFunction{Value: FuncAYRS(base64.StdEncoding.EncodeToString)},
- "decode": &objects.UserFunction{Value: FuncASRYE(base64.StdEncoding.DecodeString)},
-
- "raw_encode": &objects.UserFunction{Value: FuncAYRS(base64.RawStdEncoding.EncodeToString)},
- "raw_decode": &objects.UserFunction{Value: FuncASRYE(base64.RawStdEncoding.DecodeString)},
-
- "url_encode": &objects.UserFunction{Value: FuncAYRS(base64.URLEncoding.EncodeToString)},
- "url_decode": &objects.UserFunction{Value: FuncASRYE(base64.URLEncoding.DecodeString)},
-
- "raw_url_encode": &objects.UserFunction{Value: FuncAYRS(base64.RawURLEncoding.EncodeToString)},
- "raw_url_decode": &objects.UserFunction{Value: FuncASRYE(base64.RawURLEncoding.DecodeString)},
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/builtin_modules.go b/vendor/github.com/d5/tengo/stdlib/builtin_modules.go
deleted file mode 100644
index 722461b2..00000000
--- a/vendor/github.com/d5/tengo/stdlib/builtin_modules.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package stdlib
-
-import "github.com/d5/tengo/objects"
-
-// BuiltinModules are builtin type standard library modules.
-var BuiltinModules = map[string]map[string]objects.Object{
- "math": mathModule,
- "os": osModule,
- "text": textModule,
- "times": timesModule,
- "rand": randModule,
- "fmt": fmtModule,
- "json": jsonModule,
- "base64": base64Module,
- "hex": hexModule,
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/errors.go b/vendor/github.com/d5/tengo/stdlib/errors.go
deleted file mode 100644
index a2942bb0..00000000
--- a/vendor/github.com/d5/tengo/stdlib/errors.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package stdlib
-
-import "github.com/d5/tengo/objects"
-
-func wrapError(err error) objects.Object {
- if err == nil {
- return objects.TrueValue
- }
-
- return &objects.Error{Value: &objects.String{Value: err.Error()}}
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/fmt.go b/vendor/github.com/d5/tengo/stdlib/fmt.go
deleted file mode 100644
index b8f64278..00000000
--- a/vendor/github.com/d5/tengo/stdlib/fmt.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package stdlib
-
-import (
- "fmt"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
-)
-
-var fmtModule = map[string]objects.Object{
- "print": &objects.UserFunction{Name: "print", Value: fmtPrint},
- "printf": &objects.UserFunction{Name: "printf", Value: fmtPrintf},
- "println": &objects.UserFunction{Name: "println", Value: fmtPrintln},
- "sprintf": &objects.UserFunction{Name: "sprintf", Value: fmtSprintf},
-}
-
-func fmtPrint(args ...objects.Object) (ret objects.Object, err error) {
- printArgs, err := getPrintArgs(args...)
- if err != nil {
- return nil, err
- }
-
- _, _ = fmt.Print(printArgs...)
-
- return nil, nil
-}
-
-func fmtPrintf(args ...objects.Object) (ret objects.Object, err error) {
- numArgs := len(args)
- if numArgs == 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- format, ok := args[0].(*objects.String)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "format",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- }
- if numArgs == 1 {
- fmt.Print(format)
- return nil, nil
- }
-
- s, err := objects.Format(format.Value, args[1:]...)
- if err != nil {
- return nil, err
- }
-
- fmt.Print(s)
-
- return nil, nil
-}
-
-func fmtPrintln(args ...objects.Object) (ret objects.Object, err error) {
- printArgs, err := getPrintArgs(args...)
- if err != nil {
- return nil, err
- }
-
- printArgs = append(printArgs, "\n")
- _, _ = fmt.Print(printArgs...)
-
- return nil, nil
-}
-
-func fmtSprintf(args ...objects.Object) (ret objects.Object, err error) {
- numArgs := len(args)
- if numArgs == 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- format, ok := args[0].(*objects.String)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "format",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- }
- if numArgs == 1 {
- return format, nil // okay to return 'format' directly as String is immutable
- }
-
- s, err := objects.Format(format.Value, args[1:]...)
- if err != nil {
- return nil, err
- }
-
- return &objects.String{Value: s}, nil
-}
-
-func getPrintArgs(args ...objects.Object) ([]interface{}, error) {
- var printArgs []interface{}
- l := 0
- for _, arg := range args {
- s, _ := objects.ToString(arg)
- slen := len(s)
- if l+slen > tengo.MaxStringLen { // make sure length does not exceed the limit
- return nil, objects.ErrStringLimit
- }
- l += slen
-
- printArgs = append(printArgs, s)
- }
-
- return printArgs, nil
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/func_typedefs.go b/vendor/github.com/d5/tengo/stdlib/func_typedefs.go
deleted file mode 100644
index c7bd11fa..00000000
--- a/vendor/github.com/d5/tengo/stdlib/func_typedefs.go
+++ /dev/null
@@ -1,1178 +0,0 @@
-package stdlib
-
-import (
- "fmt"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
-)
-
-// FuncAR transform a function of 'func()' signature
-// into CallableFunc type.
-func FuncAR(fn func()) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- fn()
-
- return objects.UndefinedValue, nil
- }
-}
-
-// FuncARI transform a function of 'func() int' signature
-// into CallableFunc type.
-func FuncARI(fn func() int) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return &objects.Int{Value: int64(fn())}, nil
- }
-}
-
-// FuncARI64 transform a function of 'func() int64' signature
-// into CallableFunc type.
-func FuncARI64(fn func() int64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return &objects.Int{Value: fn()}, nil
- }
-}
-
-// FuncAI64RI64 transform a function of 'func(int64) int64' signature
-// into CallableFunc type.
-func FuncAI64RI64(fn func(int64) int64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return &objects.Int{Value: fn(i1)}, nil
- }
-}
-
-// FuncAI64R transform a function of 'func(int64)' signature
-// into CallableFunc type.
-func FuncAI64R(fn func(int64)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- fn(i1)
-
- return objects.UndefinedValue, nil
- }
-}
-
-// FuncARB transform a function of 'func() bool' signature
-// into CallableFunc type.
-func FuncARB(fn func() bool) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- if fn() {
- return objects.TrueValue, nil
- }
-
- return objects.FalseValue, nil
- }
-}
-
-// FuncARE transform a function of 'func() error' signature
-// into CallableFunc type.
-func FuncARE(fn func() error) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return wrapError(fn()), nil
- }
-}
-
-// FuncARS transform a function of 'func() string' signature
-// into CallableFunc type.
-func FuncARS(fn func() string) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s := fn()
-
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
-
-// FuncARSE transform a function of 'func() (string, error)' signature
-// into CallableFunc type.
-func FuncARSE(fn func() (string, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- res, err := fn()
- if err != nil {
- return wrapError(err), nil
- }
-
- if len(res) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: res}, nil
- }
-}
-
-// FuncARYE transform a function of 'func() ([]byte, error)' signature
-// into CallableFunc type.
-func FuncARYE(fn func() ([]byte, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- res, err := fn()
- if err != nil {
- return wrapError(err), nil
- }
-
- if len(res) > tengo.MaxBytesLen {
- return nil, objects.ErrBytesLimit
- }
-
- return &objects.Bytes{Value: res}, nil
- }
-}
-
-// FuncARF transform a function of 'func() float64' signature
-// into CallableFunc type.
-func FuncARF(fn func() float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return &objects.Float{Value: fn()}, nil
- }
-}
-
-// FuncARSs transform a function of 'func() []string' signature
-// into CallableFunc type.
-func FuncARSs(fn func() []string) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- arr := &objects.Array{}
- for _, elem := range fn() {
- if len(elem) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: elem})
- }
-
- return arr, nil
- }
-}
-
-// FuncARIsE transform a function of 'func() ([]int, error)' signature
-// into CallableFunc type.
-func FuncARIsE(fn func() ([]int, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- res, err := fn()
- if err != nil {
- return wrapError(err), nil
- }
-
- arr := &objects.Array{}
- for _, v := range res {
- arr.Value = append(arr.Value, &objects.Int{Value: int64(v)})
- }
-
- return arr, nil
- }
-}
-
-// FuncAIRIs transform a function of 'func(int) []int' signature
-// into CallableFunc type.
-func FuncAIRIs(fn func(int) []int) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res := fn(i1)
-
- arr := &objects.Array{}
- for _, v := range res {
- arr.Value = append(arr.Value, &objects.Int{Value: int64(v)})
- }
-
- return arr, nil
- }
-}
-
-// FuncAFRF transform a function of 'func(float64) float64' signature
-// into CallableFunc type.
-func FuncAFRF(fn func(float64) float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return &objects.Float{Value: fn(f1)}, nil
- }
-}
-
-// FuncAIR transform a function of 'func(int)' signature
-// into CallableFunc type.
-func FuncAIR(fn func(int)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- fn(i1)
-
- return objects.UndefinedValue, nil
- }
-}
-
-// FuncAIRF transform a function of 'func(int) float64' signature
-// into CallableFunc type.
-func FuncAIRF(fn func(int) float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return &objects.Float{Value: fn(i1)}, nil
- }
-}
-
-// FuncAFRI transform a function of 'func(float64) int' signature
-// into CallableFunc type.
-func FuncAFRI(fn func(float64) int) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return &objects.Int{Value: int64(fn(f1))}, nil
- }
-}
-
-// FuncAFFRF transform a function of 'func(float64, float64) float64' signature
-// into CallableFunc type.
-func FuncAFFRF(fn func(float64, float64) float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- f2, ok := objects.ToFloat64(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "float(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return &objects.Float{Value: fn(f1, f2)}, nil
- }
-}
-
-// FuncAIFRF transform a function of 'func(int, float64) float64' signature
-// into CallableFunc type.
-func FuncAIFRF(fn func(int, float64) float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- f2, ok := objects.ToFloat64(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "float(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return &objects.Float{Value: fn(i1, f2)}, nil
- }
-}
-
-// FuncAFIRF transform a function of 'func(float64, int) float64' signature
-// into CallableFunc type.
-func FuncAFIRF(fn func(float64, int) float64) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return &objects.Float{Value: fn(f1, i2)}, nil
- }
-}
-
-// FuncAFIRB transform a function of 'func(float64, int) bool' signature
-// into CallableFunc type.
-func FuncAFIRB(fn func(float64, int) bool) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- if fn(f1, i2) {
- return objects.TrueValue, nil
- }
-
- return objects.FalseValue, nil
- }
-}
-
-// FuncAFRB transform a function of 'func(float64) bool' signature
-// into CallableFunc type.
-func FuncAFRB(fn func(float64) bool) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- f1, ok := objects.ToFloat64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- if fn(f1) {
- return objects.TrueValue, nil
- }
-
- return objects.FalseValue, nil
- }
-}
-
-// FuncASRS transform a function of 'func(string) string' signature into CallableFunc type.
-// User function will return 'true' if underlying native function returns nil.
-func FuncASRS(fn func(string) string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s := fn(s1)
-
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
-
-// FuncASRSs transform a function of 'func(string) []string' signature into CallableFunc type.
-func FuncASRSs(fn func(string) []string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res := fn(s1)
-
- arr := &objects.Array{}
- for _, elem := range res {
- if len(elem) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: elem})
- }
-
- return arr, nil
- }
-}
-
-// FuncASRSE transform a function of 'func(string) (string, error)' signature into CallableFunc type.
-// User function will return 'true' if underlying native function returns nil.
-func FuncASRSE(fn func(string) (string, error)) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := fn(s1)
- if err != nil {
- return wrapError(err), nil
- }
-
- if len(res) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: res}, nil
- }
-}
-
-// FuncASRE transform a function of 'func(string) error' signature into CallableFunc type.
-// User function will return 'true' if underlying native function returns nil.
-func FuncASRE(fn func(string) error) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return wrapError(fn(s1)), nil
- }
-}
-
-// FuncASSRE transform a function of 'func(string, string) error' signature into CallableFunc type.
-// User function will return 'true' if underlying native function returns nil.
-func FuncASSRE(fn func(string, string) error) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return wrapError(fn(s1, s2)), nil
- }
-}
-
-// FuncASSRSs transform a function of 'func(string, string) []string' signature into CallableFunc type.
-func FuncASSRSs(fn func(string, string) []string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- arr := &objects.Array{}
- for _, res := range fn(s1, s2) {
- if len(res) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: res})
- }
-
- return arr, nil
- }
-}
-
-// FuncASSIRSs transform a function of 'func(string, string, int) []string' signature into CallableFunc type.
-func FuncASSIRSs(fn func(string, string, int) []string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 3 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- }
-
- arr := &objects.Array{}
- for _, res := range fn(s1, s2, i3) {
- if len(res) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: res})
- }
-
- return arr, nil
- }
-}
-
-// FuncASSRI transform a function of 'func(string, string) int' signature into CallableFunc type.
-func FuncASSRI(fn func(string, string) int) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return &objects.Int{Value: int64(fn(s1, s2))}, nil
- }
-}
-
-// FuncASSRS transform a function of 'func(string, string) string' signature into CallableFunc type.
-func FuncASSRS(fn func(string, string) string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- s := fn(s1, s2)
-
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
-
-// FuncASSRB transform a function of 'func(string, string) bool' signature into CallableFunc type.
-func FuncASSRB(fn func(string, string) bool) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- if fn(s1, s2) {
- return objects.TrueValue, nil
- }
-
- return objects.FalseValue, nil
- }
-}
-
-// FuncASsSRS transform a function of 'func([]string, string) string' signature into CallableFunc type.
-func FuncASsSRS(fn func([]string, string) string) objects.CallableFunc {
- return func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- var ss1 []string
- switch arg0 := args[0].(type) {
- case *objects.Array:
- for idx, a := range arg0.Value {
- as, ok := objects.ToString(a)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("first[%d]", idx),
- Expected: "string(compatible)",
- Found: a.TypeName(),
- }
- }
- ss1 = append(ss1, as)
- }
- case *objects.ImmutableArray:
- for idx, a := range arg0.Value {
- as, ok := objects.ToString(a)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("first[%d]", idx),
- Expected: "string(compatible)",
- Found: a.TypeName(),
- }
- }
- ss1 = append(ss1, as)
- }
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- s := fn(ss1, s2)
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
-
-// FuncASI64RE transform a function of 'func(string, int64) error' signature
-// into CallableFunc type.
-func FuncASI64RE(fn func(string, int64) error) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt64(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return wrapError(fn(s1, i2)), nil
- }
-}
-
-// FuncAIIRE transform a function of 'func(int, int) error' signature
-// into CallableFunc type.
-func FuncAIIRE(fn func(int, int) error) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return wrapError(fn(i1, i2)), nil
- }
-}
-
-// FuncASIRS transform a function of 'func(string, int) string' signature
-// into CallableFunc type.
-func FuncASIRS(fn func(string, int) string) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- s := fn(s1, i2)
-
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
-
-// FuncASIIRE transform a function of 'func(string, int, int) error' signature
-// into CallableFunc type.
-func FuncASIIRE(fn func(string, int, int) error) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 3 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- }
-
- return wrapError(fn(s1, i2, i3)), nil
- }
-}
-
-// FuncAYRIE transform a function of 'func([]byte) (int, error)' signature
-// into CallableFunc type.
-func FuncAYRIE(fn func([]byte) (int, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- y1, ok := objects.ToByteSlice(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := fn(y1)
- if err != nil {
- return wrapError(err), nil
- }
-
- return &objects.Int{Value: int64(res)}, nil
- }
-}
-
-// FuncAYRS transform a function of 'func([]byte) string' signature
-// into CallableFunc type.
-func FuncAYRS(fn func([]byte) string) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- y1, ok := objects.ToByteSlice(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res := fn(y1)
-
- return &objects.String{Value: res}, nil
- }
-}
-
-// FuncASRIE transform a function of 'func(string) (int, error)' signature
-// into CallableFunc type.
-func FuncASRIE(fn func(string) (int, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := fn(s1)
- if err != nil {
- return wrapError(err), nil
- }
-
- return &objects.Int{Value: int64(res)}, nil
- }
-}
-
-// FuncASRYE transform a function of 'func(string) ([]byte, error)' signature
-// into CallableFunc type.
-func FuncASRYE(fn func(string) ([]byte, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := fn(s1)
- if err != nil {
- return wrapError(err), nil
- }
-
- if len(res) > tengo.MaxBytesLen {
- return nil, objects.ErrBytesLimit
- }
-
- return &objects.Bytes{Value: res}, nil
- }
-}
-
-// FuncAIRSsE transform a function of 'func(int) ([]string, error)' signature
-// into CallableFunc type.
-func FuncAIRSsE(fn func(int) ([]string, error)) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := fn(i1)
- if err != nil {
- return wrapError(err), nil
- }
-
- arr := &objects.Array{}
- for _, r := range res {
- if len(r) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: r})
- }
-
- return arr, nil
- }
-}
-
-// FuncAIRS transform a function of 'func(int) string' signature
-// into CallableFunc type.
-func FuncAIRS(fn func(int) string) objects.CallableFunc {
- return func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- s := fn(i1)
-
- if len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/hex.go b/vendor/github.com/d5/tengo/stdlib/hex.go
deleted file mode 100644
index acc29e6a..00000000
--- a/vendor/github.com/d5/tengo/stdlib/hex.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package stdlib
-
-import (
- "encoding/hex"
- "github.com/d5/tengo/objects"
-)
-
-var hexModule = map[string]objects.Object{
- "encode": &objects.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
- "decode": &objects.UserFunction{Value: FuncASRYE(hex.DecodeString)},
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/json.go b/vendor/github.com/d5/tengo/stdlib/json.go
deleted file mode 100644
index f913dc48..00000000
--- a/vendor/github.com/d5/tengo/stdlib/json.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package stdlib
-
-import (
- "bytes"
- gojson "encoding/json"
-
- "github.com/d5/tengo/objects"
- "github.com/d5/tengo/stdlib/json"
-)
-
-var jsonModule = map[string]objects.Object{
- "decode": &objects.UserFunction{Name: "decode", Value: jsonDecode},
- "encode": &objects.UserFunction{Name: "encode", Value: jsonEncode},
- "indent": &objects.UserFunction{Name: "encode", Value: jsonIndent},
- "html_escape": &objects.UserFunction{Name: "html_escape", Value: jsonHTMLEscape},
-}
-
-func jsonDecode(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- switch o := args[0].(type) {
- case *objects.Bytes:
- v, err := json.Decode(o.Value)
- if err != nil {
- return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
- }
- return v, nil
- case *objects.String:
- v, err := json.Decode([]byte(o.Value))
- if err != nil {
- return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
- }
- return v, nil
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes/string",
- Found: args[0].TypeName(),
- }
- }
-}
-
-func jsonEncode(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- b, err := json.Encode(args[0])
- if err != nil {
- return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
- }
-
- return &objects.Bytes{Value: b}, nil
-}
-
-func jsonIndent(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 3 {
- return nil, objects.ErrWrongNumArguments
- }
-
- prefix, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "prefix",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- indent, ok := objects.ToString(args[2])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "indent",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- }
-
- switch o := args[0].(type) {
- case *objects.Bytes:
- var dst bytes.Buffer
- err := gojson.Indent(&dst, o.Value, prefix, indent)
- if err != nil {
- return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
- }
- return &objects.Bytes{Value: dst.Bytes()}, nil
- case *objects.String:
- var dst bytes.Buffer
- err := gojson.Indent(&dst, []byte(o.Value), prefix, indent)
- if err != nil {
- return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
- }
- return &objects.Bytes{Value: dst.Bytes()}, nil
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes/string",
- Found: args[0].TypeName(),
- }
- }
-}
-
-func jsonHTMLEscape(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- switch o := args[0].(type) {
- case *objects.Bytes:
- var dst bytes.Buffer
- gojson.HTMLEscape(&dst, o.Value)
- return &objects.Bytes{Value: dst.Bytes()}, nil
- case *objects.String:
- var dst bytes.Buffer
- gojson.HTMLEscape(&dst, []byte(o.Value))
- return &objects.Bytes{Value: dst.Bytes()}, nil
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes/string",
- Found: args[0].TypeName(),
- }
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/math.go b/vendor/github.com/d5/tengo/stdlib/math.go
deleted file mode 100644
index 08d82bdf..00000000
--- a/vendor/github.com/d5/tengo/stdlib/math.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package stdlib
-
-import (
- "math"
-
- "github.com/d5/tengo/objects"
-)
-
-var mathModule = map[string]objects.Object{
- "e": &objects.Float{Value: math.E},
- "pi": &objects.Float{Value: math.Pi},
- "phi": &objects.Float{Value: math.Phi},
- "sqrt2": &objects.Float{Value: math.Sqrt2},
- "sqrtE": &objects.Float{Value: math.SqrtE},
- "sqrtPi": &objects.Float{Value: math.SqrtPi},
- "sqrtPhi": &objects.Float{Value: math.SqrtPhi},
- "ln2": &objects.Float{Value: math.Ln2},
- "log2E": &objects.Float{Value: math.Log2E},
- "ln10": &objects.Float{Value: math.Ln10},
- "log10E": &objects.Float{Value: math.Log10E},
- "abs": &objects.UserFunction{Name: "abs", Value: FuncAFRF(math.Abs)},
- "acos": &objects.UserFunction{Name: "acos", Value: FuncAFRF(math.Acos)},
- "acosh": &objects.UserFunction{Name: "acosh", Value: FuncAFRF(math.Acosh)},
- "asin": &objects.UserFunction{Name: "asin", Value: FuncAFRF(math.Asin)},
- "asinh": &objects.UserFunction{Name: "asinh", Value: FuncAFRF(math.Asinh)},
- "atan": &objects.UserFunction{Name: "atan", Value: FuncAFRF(math.Atan)},
- "atan2": &objects.UserFunction{Name: "atan2", Value: FuncAFFRF(math.Atan2)},
- "atanh": &objects.UserFunction{Name: "atanh", Value: FuncAFRF(math.Atanh)},
- "cbrt": &objects.UserFunction{Name: "cbrt", Value: FuncAFRF(math.Cbrt)},
- "ceil": &objects.UserFunction{Name: "ceil", Value: FuncAFRF(math.Ceil)},
- "copysign": &objects.UserFunction{Name: "copysign", Value: FuncAFFRF(math.Copysign)},
- "cos": &objects.UserFunction{Name: "cos", Value: FuncAFRF(math.Cos)},
- "cosh": &objects.UserFunction{Name: "cosh", Value: FuncAFRF(math.Cosh)},
- "dim": &objects.UserFunction{Name: "dim", Value: FuncAFFRF(math.Dim)},
- "erf": &objects.UserFunction{Name: "erf", Value: FuncAFRF(math.Erf)},
- "erfc": &objects.UserFunction{Name: "erfc", Value: FuncAFRF(math.Erfc)},
- "exp": &objects.UserFunction{Name: "exp", Value: FuncAFRF(math.Exp)},
- "exp2": &objects.UserFunction{Name: "exp2", Value: FuncAFRF(math.Exp2)},
- "expm1": &objects.UserFunction{Name: "expm1", Value: FuncAFRF(math.Expm1)},
- "floor": &objects.UserFunction{Name: "floor", Value: FuncAFRF(math.Floor)},
- "gamma": &objects.UserFunction{Name: "gamma", Value: FuncAFRF(math.Gamma)},
- "hypot": &objects.UserFunction{Name: "hypot", Value: FuncAFFRF(math.Hypot)},
- "ilogb": &objects.UserFunction{Name: "ilogb", Value: FuncAFRI(math.Ilogb)},
- "inf": &objects.UserFunction{Name: "inf", Value: FuncAIRF(math.Inf)},
- "is_inf": &objects.UserFunction{Name: "is_inf", Value: FuncAFIRB(math.IsInf)},
- "is_nan": &objects.UserFunction{Name: "is_nan", Value: FuncAFRB(math.IsNaN)},
- "j0": &objects.UserFunction{Name: "j0", Value: FuncAFRF(math.J0)},
- "j1": &objects.UserFunction{Name: "j1", Value: FuncAFRF(math.J1)},
- "jn": &objects.UserFunction{Name: "jn", Value: FuncAIFRF(math.Jn)},
- "ldexp": &objects.UserFunction{Name: "ldexp", Value: FuncAFIRF(math.Ldexp)},
- "log": &objects.UserFunction{Name: "log", Value: FuncAFRF(math.Log)},
- "log10": &objects.UserFunction{Name: "log10", Value: FuncAFRF(math.Log10)},
- "log1p": &objects.UserFunction{Name: "log1p", Value: FuncAFRF(math.Log1p)},
- "log2": &objects.UserFunction{Name: "log2", Value: FuncAFRF(math.Log2)},
- "logb": &objects.UserFunction{Name: "logb", Value: FuncAFRF(math.Logb)},
- "max": &objects.UserFunction{Name: "max", Value: FuncAFFRF(math.Max)},
- "min": &objects.UserFunction{Name: "min", Value: FuncAFFRF(math.Min)},
- "mod": &objects.UserFunction{Name: "mod", Value: FuncAFFRF(math.Mod)},
- "nan": &objects.UserFunction{Name: "nan", Value: FuncARF(math.NaN)},
- "nextafter": &objects.UserFunction{Name: "nextafter", Value: FuncAFFRF(math.Nextafter)},
- "pow": &objects.UserFunction{Name: "pow", Value: FuncAFFRF(math.Pow)},
- "pow10": &objects.UserFunction{Name: "pow10", Value: FuncAIRF(math.Pow10)},
- "remainder": &objects.UserFunction{Name: "remainder", Value: FuncAFFRF(math.Remainder)},
- "signbit": &objects.UserFunction{Name: "signbit", Value: FuncAFRB(math.Signbit)},
- "sin": &objects.UserFunction{Name: "sin", Value: FuncAFRF(math.Sin)},
- "sinh": &objects.UserFunction{Name: "sinh", Value: FuncAFRF(math.Sinh)},
- "sqrt": &objects.UserFunction{Name: "sqrt", Value: FuncAFRF(math.Sqrt)},
- "tan": &objects.UserFunction{Name: "tan", Value: FuncAFRF(math.Tan)},
- "tanh": &objects.UserFunction{Name: "tanh", Value: FuncAFRF(math.Tanh)},
- "trunc": &objects.UserFunction{Name: "trunc", Value: FuncAFRF(math.Trunc)},
- "y0": &objects.UserFunction{Name: "y0", Value: FuncAFRF(math.Y0)},
- "y1": &objects.UserFunction{Name: "y1", Value: FuncAFRF(math.Y1)},
- "yn": &objects.UserFunction{Name: "yn", Value: FuncAIFRF(math.Yn)},
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/os.go b/vendor/github.com/d5/tengo/stdlib/os.go
deleted file mode 100644
index a7890cc1..00000000
--- a/vendor/github.com/d5/tengo/stdlib/os.go
+++ /dev/null
@@ -1,492 +0,0 @@
-package stdlib
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
-)
-
-var osModule = map[string]objects.Object{
- "o_rdonly": &objects.Int{Value: int64(os.O_RDONLY)},
- "o_wronly": &objects.Int{Value: int64(os.O_WRONLY)},
- "o_rdwr": &objects.Int{Value: int64(os.O_RDWR)},
- "o_append": &objects.Int{Value: int64(os.O_APPEND)},
- "o_create": &objects.Int{Value: int64(os.O_CREATE)},
- "o_excl": &objects.Int{Value: int64(os.O_EXCL)},
- "o_sync": &objects.Int{Value: int64(os.O_SYNC)},
- "o_trunc": &objects.Int{Value: int64(os.O_TRUNC)},
- "mode_dir": &objects.Int{Value: int64(os.ModeDir)},
- "mode_append": &objects.Int{Value: int64(os.ModeAppend)},
- "mode_exclusive": &objects.Int{Value: int64(os.ModeExclusive)},
- "mode_temporary": &objects.Int{Value: int64(os.ModeTemporary)},
- "mode_symlink": &objects.Int{Value: int64(os.ModeSymlink)},
- "mode_device": &objects.Int{Value: int64(os.ModeDevice)},
- "mode_named_pipe": &objects.Int{Value: int64(os.ModeNamedPipe)},
- "mode_socket": &objects.Int{Value: int64(os.ModeSocket)},
- "mode_setuid": &objects.Int{Value: int64(os.ModeSetuid)},
- "mode_setgui": &objects.Int{Value: int64(os.ModeSetgid)},
- "mode_char_device": &objects.Int{Value: int64(os.ModeCharDevice)},
- "mode_sticky": &objects.Int{Value: int64(os.ModeSticky)},
- "mode_type": &objects.Int{Value: int64(os.ModeType)},
- "mode_perm": &objects.Int{Value: int64(os.ModePerm)},
- "path_separator": &objects.Char{Value: os.PathSeparator},
- "path_list_separator": &objects.Char{Value: os.PathListSeparator},
- "dev_null": &objects.String{Value: os.DevNull},
- "seek_set": &objects.Int{Value: int64(io.SeekStart)},
- "seek_cur": &objects.Int{Value: int64(io.SeekCurrent)},
- "seek_end": &objects.Int{Value: int64(io.SeekEnd)},
- "args": &objects.UserFunction{Name: "args", Value: osArgs}, // args() => array(string)
- "chdir": &objects.UserFunction{Name: "chdir", Value: FuncASRE(os.Chdir)}, // chdir(dir string) => error
- "chmod": osFuncASFmRE("chmod", os.Chmod), // chmod(name string, mode int) => error
- "chown": &objects.UserFunction{Name: "chown", Value: FuncASIIRE(os.Chown)}, // chown(name string, uid int, gid int) => error
- "clearenv": &objects.UserFunction{Name: "clearenv", Value: FuncAR(os.Clearenv)}, // clearenv()
- "environ": &objects.UserFunction{Name: "environ", Value: FuncARSs(os.Environ)}, // environ() => array(string)
- "exit": &objects.UserFunction{Name: "exit", Value: FuncAIR(os.Exit)}, // exit(code int)
- "expand_env": &objects.UserFunction{Name: "expand_env", Value: osExpandEnv}, // expand_env(s string) => string
- "getegid": &objects.UserFunction{Name: "getegid", Value: FuncARI(os.Getegid)}, // getegid() => int
- "getenv": &objects.UserFunction{Name: "getenv", Value: FuncASRS(os.Getenv)}, // getenv(s string) => string
- "geteuid": &objects.UserFunction{Name: "geteuid", Value: FuncARI(os.Geteuid)}, // geteuid() => int
- "getgid": &objects.UserFunction{Name: "getgid", Value: FuncARI(os.Getgid)}, // getgid() => int
- "getgroups": &objects.UserFunction{Name: "getgroups", Value: FuncARIsE(os.Getgroups)}, // getgroups() => array(string)/error
- "getpagesize": &objects.UserFunction{Name: "getpagesize", Value: FuncARI(os.Getpagesize)}, // getpagesize() => int
- "getpid": &objects.UserFunction{Name: "getpid", Value: FuncARI(os.Getpid)}, // getpid() => int
- "getppid": &objects.UserFunction{Name: "getppid", Value: FuncARI(os.Getppid)}, // getppid() => int
- "getuid": &objects.UserFunction{Name: "getuid", Value: FuncARI(os.Getuid)}, // getuid() => int
- "getwd": &objects.UserFunction{Name: "getwd", Value: FuncARSE(os.Getwd)}, // getwd() => string/error
- "hostname": &objects.UserFunction{Name: "hostname", Value: FuncARSE(os.Hostname)}, // hostname() => string/error
- "lchown": &objects.UserFunction{Name: "lchown", Value: FuncASIIRE(os.Lchown)}, // lchown(name string, uid int, gid int) => error
- "link": &objects.UserFunction{Name: "link", Value: FuncASSRE(os.Link)}, // link(oldname string, newname string) => error
- "lookup_env": &objects.UserFunction{Name: "lookup_env", Value: osLookupEnv}, // lookup_env(key string) => string/false
- "mkdir": osFuncASFmRE("mkdir", os.Mkdir), // mkdir(name string, perm int) => error
- "mkdir_all": osFuncASFmRE("mkdir_all", os.MkdirAll), // mkdir_all(name string, perm int) => error
- "readlink": &objects.UserFunction{Name: "readlink", Value: FuncASRSE(os.Readlink)}, // readlink(name string) => string/error
- "remove": &objects.UserFunction{Name: "remove", Value: FuncASRE(os.Remove)}, // remove(name string) => error
- "remove_all": &objects.UserFunction{Name: "remove_all", Value: FuncASRE(os.RemoveAll)}, // remove_all(name string) => error
- "rename": &objects.UserFunction{Name: "rename", Value: FuncASSRE(os.Rename)}, // rename(oldpath string, newpath string) => error
- "setenv": &objects.UserFunction{Name: "setenv", Value: FuncASSRE(os.Setenv)}, // setenv(key string, value string) => error
- "symlink": &objects.UserFunction{Name: "symlink", Value: FuncASSRE(os.Symlink)}, // symlink(oldname string newname string) => error
- "temp_dir": &objects.UserFunction{Name: "temp_dir", Value: FuncARS(os.TempDir)}, // temp_dir() => string
- "truncate": &objects.UserFunction{Name: "truncate", Value: FuncASI64RE(os.Truncate)}, // truncate(name string, size int) => error
- "unsetenv": &objects.UserFunction{Name: "unsetenv", Value: FuncASRE(os.Unsetenv)}, // unsetenv(key string) => error
- "create": &objects.UserFunction{Name: "create", Value: osCreate}, // create(name string) => imap(file)/error
- "open": &objects.UserFunction{Name: "open", Value: osOpen}, // open(name string) => imap(file)/error
- "open_file": &objects.UserFunction{Name: "open_file", Value: osOpenFile}, // open_file(name string, flag int, perm int) => imap(file)/error
- "find_process": &objects.UserFunction{Name: "find_process", Value: osFindProcess}, // find_process(pid int) => imap(process)/error
- "start_process": &objects.UserFunction{Name: "start_process", Value: osStartProcess}, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
- "exec_look_path": &objects.UserFunction{Name: "exec_look_path", Value: FuncASRSE(exec.LookPath)}, // exec_look_path(file) => string/error
- "exec": &objects.UserFunction{Name: "exec", Value: osExec}, // exec(name, args...) => command
- "stat": &objects.UserFunction{Name: "stat", Value: osStat}, // stat(name) => imap(fileinfo)/error
- "read_file": &objects.UserFunction{Name: "read_file", Value: osReadFile}, // readfile(name) => array(byte)/error
-}
-
-func osReadFile(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- fname, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- bytes, err := ioutil.ReadFile(fname)
- if err != nil {
- return wrapError(err), nil
- }
-
- if len(bytes) > tengo.MaxBytesLen {
- return nil, objects.ErrBytesLimit
- }
-
- return &objects.Bytes{Value: bytes}, nil
-}
-
-func osStat(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- fname, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- stat, err := os.Stat(fname)
- if err != nil {
- return wrapError(err), nil
- }
-
- fstat := &objects.ImmutableMap{
- Value: map[string]objects.Object{
- "name": &objects.String{Value: stat.Name()},
- "mtime": &objects.Time{Value: stat.ModTime()},
- "size": &objects.Int{Value: stat.Size()},
- "mode": &objects.Int{Value: int64(stat.Mode())},
- },
- }
-
- if stat.IsDir() {
- fstat.Value["directory"] = objects.TrueValue
- } else {
- fstat.Value["directory"] = objects.FalseValue
- }
-
- return fstat, nil
-}
-
-func osCreate(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := os.Create(s1)
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSFile(res), nil
-}
-
-func osOpen(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := os.Open(s1)
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSFile(res), nil
-}
-
-func osOpenFile(args ...objects.Object) (objects.Object, error) {
- if len(args) != 3 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- }
-
- res, err := os.OpenFile(s1, i2, os.FileMode(i3))
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSFile(res), nil
-}
-
-func osArgs(args ...objects.Object) (objects.Object, error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- arr := &objects.Array{}
- for _, osArg := range os.Args {
- if len(osArg) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- arr.Value = append(arr.Value, &objects.String{Value: osArg})
- }
-
- return arr, nil
-}
-
-func osFuncASFmRE(name string, fn func(string, os.FileMode) error) *objects.UserFunction {
- return &objects.UserFunction{
- Name: name,
- Value: func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
- i2, ok := objects.ToInt64(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- return wrapError(fn(s1, os.FileMode(i2))), nil
- },
- }
-}
-
-func osLookupEnv(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- res, ok := os.LookupEnv(s1)
- if !ok {
- return objects.FalseValue, nil
- }
-
- if len(res) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: res}, nil
-}
-
-func osExpandEnv(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- var vlen int
- var failed bool
- s := os.Expand(s1, func(k string) string {
- if failed {
- return ""
- }
-
- v := os.Getenv(k)
-
- // this does not count the other texts that are not being replaced
- // but the code checks the final length at the end
- vlen += len(v)
- if vlen > tengo.MaxStringLen {
- failed = true
- return ""
- }
-
- return v
- })
-
- if failed || len(s) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: s}, nil
-}
-
-func osExec(args ...objects.Object) (objects.Object, error) {
- if len(args) == 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- name, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- var execArgs []string
- for idx, arg := range args[1:] {
- execArg, ok := objects.ToString(arg)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("args[%d]", idx),
- Expected: "string(compatible)",
- Found: args[1+idx].TypeName(),
- }
- }
-
- execArgs = append(execArgs, execArg)
- }
-
- return makeOSExecCommand(exec.Command(name, execArgs...)), nil
-}
-
-func osFindProcess(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- proc, err := os.FindProcess(i1)
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSProcess(proc), nil
-}
-
-func osStartProcess(args ...objects.Object) (objects.Object, error) {
- if len(args) != 4 {
- return nil, objects.ErrWrongNumArguments
- }
-
- name, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- var argv []string
- var err error
- switch arg1 := args[1].(type) {
- case *objects.Array:
- argv, err = stringArray(arg1.Value, "second")
- if err != nil {
- return nil, err
- }
- case *objects.ImmutableArray:
- argv, err = stringArray(arg1.Value, "second")
- if err != nil {
- return nil, err
- }
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "array",
- Found: arg1.TypeName(),
- }
- }
-
- dir, ok := objects.ToString(args[2])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- }
-
- var env []string
- switch arg3 := args[3].(type) {
- case *objects.Array:
- env, err = stringArray(arg3.Value, "fourth")
- if err != nil {
- return nil, err
- }
- case *objects.ImmutableArray:
- env, err = stringArray(arg3.Value, "fourth")
- if err != nil {
- return nil, err
- }
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "fourth",
- Expected: "array",
- Found: arg3.TypeName(),
- }
- }
-
- proc, err := os.StartProcess(name, argv, &os.ProcAttr{
- Dir: dir,
- Env: env,
- })
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSProcess(proc), nil
-}
-
-func stringArray(arr []objects.Object, argName string) ([]string, error) {
- var sarr []string
- for idx, elem := range arr {
- str, ok := elem.(*objects.String)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("%s[%d]", argName, idx),
- Expected: "string",
- Found: elem.TypeName(),
- }
- }
-
- sarr = append(sarr, str.Value)
- }
-
- return sarr, nil
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/os_exec.go b/vendor/github.com/d5/tengo/stdlib/os_exec.go
deleted file mode 100644
index 5274c36a..00000000
--- a/vendor/github.com/d5/tengo/stdlib/os_exec.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package stdlib
-
-import (
- "os/exec"
-
- "github.com/d5/tengo/objects"
-)
-
-func makeOSExecCommand(cmd *exec.Cmd) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
- // combined_output() => bytes/error
- "combined_output": &objects.UserFunction{Name: "combined_output", Value: FuncARYE(cmd.CombinedOutput)}, //
- // output() => bytes/error
- "output": &objects.UserFunction{Name: "output", Value: FuncARYE(cmd.Output)}, //
- // run() => error
- "run": &objects.UserFunction{Name: "run", Value: FuncARE(cmd.Run)}, //
- // start() => error
- "start": &objects.UserFunction{Name: "start", Value: FuncARE(cmd.Start)}, //
- // wait() => error
- "wait": &objects.UserFunction{Name: "wait", Value: FuncARE(cmd.Wait)}, //
- // set_path(path string)
- "set_path": &objects.UserFunction{
- Name: "set_path",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- cmd.Path = s1
-
- return objects.UndefinedValue, nil
- },
- },
- // set_dir(dir string)
- "set_dir": &objects.UserFunction{
- Name: "set_dir",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- cmd.Dir = s1
-
- return objects.UndefinedValue, nil
- },
- },
- // set_env(env array(string))
- "set_env": &objects.UserFunction{
- Name: "set_env",
- Value: func(args ...objects.Object) (objects.Object, error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- var env []string
- var err error
- switch arg0 := args[0].(type) {
- case *objects.Array:
- env, err = stringArray(arg0.Value, "first")
- if err != nil {
- return nil, err
- }
- case *objects.ImmutableArray:
- env, err = stringArray(arg0.Value, "first")
- if err != nil {
- return nil, err
- }
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: arg0.TypeName(),
- }
- }
-
- cmd.Env = env
-
- return objects.UndefinedValue, nil
- },
- },
- // process() => imap(process)
- "process": &objects.UserFunction{
- Name: "process",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return makeOSProcess(cmd.Process), nil
- },
- },
- },
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/os_file.go b/vendor/github.com/d5/tengo/stdlib/os_file.go
deleted file mode 100644
index ee9f625a..00000000
--- a/vendor/github.com/d5/tengo/stdlib/os_file.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package stdlib
-
-import (
- "os"
-
- "github.com/d5/tengo/objects"
-)
-
-func makeOSFile(file *os.File) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
- // chdir() => true/error
- "chdir": &objects.UserFunction{Name: "chdir", Value: FuncARE(file.Chdir)}, //
- // chown(uid int, gid int) => true/error
- "chown": &objects.UserFunction{Name: "chown", Value: FuncAIIRE(file.Chown)}, //
- // close() => error
- "close": &objects.UserFunction{Name: "close", Value: FuncARE(file.Close)}, //
- // name() => string
- "name": &objects.UserFunction{Name: "name", Value: FuncARS(file.Name)}, //
- // readdirnames(n int) => array(string)/error
- "readdirnames": &objects.UserFunction{Name: "readdirnames", Value: FuncAIRSsE(file.Readdirnames)}, //
- // sync() => error
- "sync": &objects.UserFunction{Name: "sync", Value: FuncARE(file.Sync)}, //
- // write(bytes) => int/error
- "write": &objects.UserFunction{Name: "write", Value: FuncAYRIE(file.Write)}, //
- // write(string) => int/error
- "write_string": &objects.UserFunction{Name: "write_string", Value: FuncASRIE(file.WriteString)}, //
- // read(bytes) => int/error
- "read": &objects.UserFunction{Name: "read", Value: FuncAYRIE(file.Read)}, //
- // chmod(mode int) => error
- "chmod": &objects.UserFunction{
- Name: "chmod",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return wrapError(file.Chmod(os.FileMode(i1))), nil
- },
- },
- // seek(offset int, whence int) => int/error
- "seek": &objects.UserFunction{
- Name: "seek",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- res, err := file.Seek(i1, i2)
- if err != nil {
- return wrapError(err), nil
- }
-
- return &objects.Int{Value: res}, nil
- },
- },
- // stat() => imap(fileinfo)/error
- "stat": &objects.UserFunction{
- Name: "start",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- return osStat(&objects.String{Value: file.Name()})
- },
- },
- },
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/os_process.go b/vendor/github.com/d5/tengo/stdlib/os_process.go
deleted file mode 100644
index 801ccdef..00000000
--- a/vendor/github.com/d5/tengo/stdlib/os_process.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package stdlib
-
-import (
- "os"
- "syscall"
-
- "github.com/d5/tengo/objects"
-)
-
-func makeOSProcessState(state *os.ProcessState) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
- "exited": &objects.UserFunction{Name: "exited", Value: FuncARB(state.Exited)}, //
- "pid": &objects.UserFunction{Name: "pid", Value: FuncARI(state.Pid)}, //
- "string": &objects.UserFunction{Name: "string", Value: FuncARS(state.String)}, //
- "success": &objects.UserFunction{Name: "success", Value: FuncARB(state.Success)}, //
- },
- }
-}
-
-func makeOSProcess(proc *os.Process) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
- "kill": &objects.UserFunction{Name: "kill", Value: FuncARE(proc.Kill)}, //
- "release": &objects.UserFunction{Name: "release", Value: FuncARE(proc.Release)}, //
- "signal": &objects.UserFunction{
- Name: "signal",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- return wrapError(proc.Signal(syscall.Signal(i1))), nil
- },
- },
- "wait": &objects.UserFunction{
- Name: "wait",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- return nil, objects.ErrWrongNumArguments
- }
-
- state, err := proc.Wait()
- if err != nil {
- return wrapError(err), nil
- }
-
- return makeOSProcessState(state), nil
- },
- },
- },
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/rand.go b/vendor/github.com/d5/tengo/stdlib/rand.go
deleted file mode 100644
index 6efe1de8..00000000
--- a/vendor/github.com/d5/tengo/stdlib/rand.go
+++ /dev/null
@@ -1,102 +0,0 @@
-package stdlib
-
-import (
- "math/rand"
-
- "github.com/d5/tengo/objects"
-)
-
-var randModule = map[string]objects.Object{
- "int": &objects.UserFunction{Name: "int", Value: FuncARI64(rand.Int63)},
- "float": &objects.UserFunction{Name: "float", Value: FuncARF(rand.Float64)},
- "intn": &objects.UserFunction{Name: "intn", Value: FuncAI64RI64(rand.Int63n)},
- "exp_float": &objects.UserFunction{Name: "exp_float", Value: FuncARF(rand.ExpFloat64)},
- "norm_float": &objects.UserFunction{Name: "norm_float", Value: FuncARF(rand.NormFloat64)},
- "perm": &objects.UserFunction{Name: "perm", Value: FuncAIRIs(rand.Perm)},
- "seed": &objects.UserFunction{Name: "seed", Value: FuncAI64R(rand.Seed)},
- "read": &objects.UserFunction{
- Name: "read",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- y1, ok := args[0].(*objects.Bytes)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := rand.Read(y1.Value)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- return &objects.Int{Value: int64(res)}, nil
- },
- },
- "rand": &objects.UserFunction{
- Name: "rand",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- src := rand.NewSource(i1)
-
- return randRand(rand.New(src)), nil
- },
- },
-}
-
-func randRand(r *rand.Rand) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
- "int": &objects.UserFunction{Name: "int", Value: FuncARI64(r.Int63)},
- "float": &objects.UserFunction{Name: "float", Value: FuncARF(r.Float64)},
- "intn": &objects.UserFunction{Name: "intn", Value: FuncAI64RI64(r.Int63n)},
- "exp_float": &objects.UserFunction{Name: "exp_float", Value: FuncARF(r.ExpFloat64)},
- "norm_float": &objects.UserFunction{Name: "norm_float", Value: FuncARF(r.NormFloat64)},
- "perm": &objects.UserFunction{Name: "perm", Value: FuncAIRIs(r.Perm)},
- "seed": &objects.UserFunction{Name: "seed", Value: FuncAI64R(r.Seed)},
- "read": &objects.UserFunction{
- Name: "read",
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- return nil, objects.ErrWrongNumArguments
- }
-
- y1, ok := args[0].(*objects.Bytes)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bytes",
- Found: args[0].TypeName(),
- }
- }
-
- res, err := r.Read(y1.Value)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- return &objects.Int{Value: int64(res)}, nil
- },
- },
- },
- }
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/text.go b/vendor/github.com/d5/tengo/stdlib/text.go
deleted file mode 100644
index 4b5729ec..00000000
--- a/vendor/github.com/d5/tengo/stdlib/text.go
+++ /dev/null
@@ -1,930 +0,0 @@
-package stdlib
-
-import (
- "fmt"
- "regexp"
- "strconv"
- "strings"
- "unicode/utf8"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
-)
-
-var textModule = map[string]objects.Object{
- "re_match": &objects.UserFunction{Name: "re_match", Value: textREMatch}, // re_match(pattern, text) => bool/error
- "re_find": &objects.UserFunction{Name: "re_find", Value: textREFind}, // re_find(pattern, text, count) => [[{text:,begin:,end:}]]/undefined
- "re_replace": &objects.UserFunction{Name: "re_replace", Value: textREReplace}, // re_replace(pattern, text, repl) => string/error
- "re_split": &objects.UserFunction{Name: "re_split", Value: textRESplit}, // re_split(pattern, text, count) => [string]/error
- "re_compile": &objects.UserFunction{Name: "re_compile", Value: textRECompile}, // re_compile(pattern) => Regexp/error
- "compare": &objects.UserFunction{Name: "compare", Value: FuncASSRI(strings.Compare)}, // compare(a, b) => int
- "contains": &objects.UserFunction{Name: "contains", Value: FuncASSRB(strings.Contains)}, // contains(s, substr) => bool
- "contains_any": &objects.UserFunction{Name: "contains_any", Value: FuncASSRB(strings.ContainsAny)}, // contains_any(s, chars) => bool
- "count": &objects.UserFunction{Name: "count", Value: FuncASSRI(strings.Count)}, // count(s, substr) => int
- "equal_fold": &objects.UserFunction{Name: "equal_fold", Value: FuncASSRB(strings.EqualFold)}, // "equal_fold(s, t) => bool
- "fields": &objects.UserFunction{Name: "fields", Value: FuncASRSs(strings.Fields)}, // fields(s) => [string]
- "has_prefix": &objects.UserFunction{Name: "has_prefix", Value: FuncASSRB(strings.HasPrefix)}, // has_prefix(s, prefix) => bool
- "has_suffix": &objects.UserFunction{Name: "has_suffix", Value: FuncASSRB(strings.HasSuffix)}, // has_suffix(s, suffix) => bool
- "index": &objects.UserFunction{Name: "index", Value: FuncASSRI(strings.Index)}, // index(s, substr) => int
- "index_any": &objects.UserFunction{Name: "index_any", Value: FuncASSRI(strings.IndexAny)}, // index_any(s, chars) => int
- "join": &objects.UserFunction{Name: "join", Value: textJoin}, // join(arr, sep) => string
- "last_index": &objects.UserFunction{Name: "last_index", Value: FuncASSRI(strings.LastIndex)}, // last_index(s, substr) => int
- "last_index_any": &objects.UserFunction{Name: "last_index_any", Value: FuncASSRI(strings.LastIndexAny)}, // last_index_any(s, chars) => int
- "repeat": &objects.UserFunction{Name: "repeat", Value: textRepeat}, // repeat(s, count) => string
- "replace": &objects.UserFunction{Name: "replace", Value: textReplace}, // replace(s, old, new, n) => string
- "substr": &objects.UserFunction{Name: "substr", Value: textSubstring}, // substr(s, lower, upper) => string
- "split": &objects.UserFunction{Name: "split", Value: FuncASSRSs(strings.Split)}, // split(s, sep) => [string]
- "split_after": &objects.UserFunction{Name: "split_after", Value: FuncASSRSs(strings.SplitAfter)}, // split_after(s, sep) => [string]
- "split_after_n": &objects.UserFunction{Name: "split_after_n", Value: FuncASSIRSs(strings.SplitAfterN)}, // split_after_n(s, sep, n) => [string]
- "split_n": &objects.UserFunction{Name: "split_n", Value: FuncASSIRSs(strings.SplitN)}, // split_n(s, sep, n) => [string]
- "title": &objects.UserFunction{Name: "title", Value: FuncASRS(strings.Title)}, // title(s) => string
- "to_lower": &objects.UserFunction{Name: "to_lower", Value: FuncASRS(strings.ToLower)}, // to_lower(s) => string
- "to_title": &objects.UserFunction{Name: "to_title", Value: FuncASRS(strings.ToTitle)}, // to_title(s) => string
- "to_upper": &objects.UserFunction{Name: "to_upper", Value: FuncASRS(strings.ToUpper)}, // to_upper(s) => string
- "pad_left": &objects.UserFunction{Name: "pad_left", Value: textPadLeft}, // pad_left(s, pad_len, pad_with) => string
- "pad_right": &objects.UserFunction{Name: "pad_right", Value: textPadRight}, // pad_right(s, pad_len, pad_with) => string
- "trim": &objects.UserFunction{Name: "trim", Value: FuncASSRS(strings.Trim)}, // trim(s, cutset) => string
- "trim_left": &objects.UserFunction{Name: "trim_left", Value: FuncASSRS(strings.TrimLeft)}, // trim_left(s, cutset) => string
- "trim_prefix": &objects.UserFunction{Name: "trim_prefix", Value: FuncASSRS(strings.TrimPrefix)}, // trim_prefix(s, prefix) => string
- "trim_right": &objects.UserFunction{Name: "trim_right", Value: FuncASSRS(strings.TrimRight)}, // trim_right(s, cutset) => string
- "trim_space": &objects.UserFunction{Name: "trim_space", Value: FuncASRS(strings.TrimSpace)}, // trim_space(s) => string
- "trim_suffix": &objects.UserFunction{Name: "trim_suffix", Value: FuncASSRS(strings.TrimSuffix)}, // trim_suffix(s, suffix) => string
- "atoi": &objects.UserFunction{Name: "atoi", Value: FuncASRIE(strconv.Atoi)}, // atoi(str) => int/error
- "format_bool": &objects.UserFunction{Name: "format_bool", Value: textFormatBool}, // format_bool(b) => string
- "format_float": &objects.UserFunction{Name: "format_float", Value: textFormatFloat}, // format_float(f, fmt, prec, bits) => string
- "format_int": &objects.UserFunction{Name: "format_int", Value: textFormatInt}, // format_int(i, base) => string
- "itoa": &objects.UserFunction{Name: "itoa", Value: FuncAIRS(strconv.Itoa)}, // itoa(i) => string
- "parse_bool": &objects.UserFunction{Name: "parse_bool", Value: textParseBool}, // parse_bool(str) => bool/error
- "parse_float": &objects.UserFunction{Name: "parse_float", Value: textParseFloat}, // parse_float(str, bits) => float/error
- "parse_int": &objects.UserFunction{Name: "parse_int", Value: textParseInt}, // parse_int(str, base, bits) => int/error
- "quote": &objects.UserFunction{Name: "quote", Value: FuncASRS(strconv.Quote)}, // quote(str) => string
- "unquote": &objects.UserFunction{Name: "unquote", Value: FuncASRSE(strconv.Unquote)}, // unquote(str) => string/error
-}
-
-func textREMatch(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- matched, err := regexp.MatchString(s1, s2)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- if matched {
- ret = objects.TrueValue
- } else {
- ret = objects.FalseValue
- }
-
- return
-}
-
-func textREFind(args ...objects.Object) (ret objects.Object, err error) {
- numArgs := len(args)
- if numArgs != 2 && numArgs != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- re, err := regexp.Compile(s1)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- if numArgs < 3 {
- m := re.FindStringSubmatchIndex(s2)
- if m == nil {
- ret = objects.UndefinedValue
- return
- }
-
- arr := &objects.Array{}
- for i := 0; i < len(m); i += 2 {
- arr.Value = append(arr.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
- "text": &objects.String{Value: s2[m[i]:m[i+1]]},
- "begin": &objects.Int{Value: int64(m[i])},
- "end": &objects.Int{Value: int64(m[i+1])},
- }})
- }
-
- ret = &objects.Array{Value: []objects.Object{arr}}
-
- return
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- m := re.FindAllStringSubmatchIndex(s2, i3)
- if m == nil {
- ret = objects.UndefinedValue
- return
- }
-
- arr := &objects.Array{}
- for _, m := range m {
- subMatch := &objects.Array{}
- for i := 0; i < len(m); i += 2 {
- subMatch.Value = append(subMatch.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
- "text": &objects.String{Value: s2[m[i]:m[i+1]]},
- "begin": &objects.Int{Value: int64(m[i])},
- "end": &objects.Int{Value: int64(m[i+1])},
- }})
- }
-
- arr.Value = append(arr.Value, subMatch)
- }
-
- ret = arr
-
- return
-}
-
-func textREReplace(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- s3, ok := objects.ToString(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
-
- re, err := regexp.Compile(s1)
- if err != nil {
- ret = wrapError(err)
- } else {
- s, ok := doTextRegexpReplace(re, s2, s3)
- if !ok {
- return nil, objects.ErrStringLimit
- }
-
- ret = &objects.String{Value: s}
- }
-
- return
-}
-
-func textRESplit(args ...objects.Object) (ret objects.Object, err error) {
- numArgs := len(args)
- if numArgs != 2 && numArgs != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- var i3 = -1
- if numArgs > 2 {
- i3, ok = objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- }
-
- re, err := regexp.Compile(s1)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- arr := &objects.Array{}
- for _, s := range re.Split(s2, i3) {
- arr.Value = append(arr.Value, &objects.String{Value: s})
- }
-
- ret = arr
-
- return
-}
-
-func textRECompile(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- re, err := regexp.Compile(s1)
- if err != nil {
- ret = wrapError(err)
- } else {
- ret = makeTextRegexp(re)
- }
-
- return
-}
-
-func textReplace(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 4 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- s3, ok := objects.ToString(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
-
- i4, ok := objects.ToInt(args[3])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "fourth",
- Expected: "int(compatible)",
- Found: args[3].TypeName(),
- }
- return
- }
-
- s, ok := doTextReplace(s1, s2, s3, i4)
- if !ok {
- err = objects.ErrStringLimit
- return
- }
-
- ret = &objects.String{Value: s}
-
- return
-}
-
-func textSubstring(args ...objects.Object) (ret objects.Object, err error) {
- argslen := len(args)
- if argslen != 2 && argslen != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- strlen := len(s1)
- i3 := strlen
- if argslen == 3 {
- i3, ok = objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- }
-
- if i2 > i3 {
- err = objects.ErrInvalidIndexType
- return
- }
-
- if i2 < 0 {
- i2 = 0
- } else if i2 > strlen {
- i2 = strlen
- }
-
- if i3 < 0 {
- i3 = 0
- } else if i3 > strlen {
- i3 = strlen
- }
-
- ret = &objects.String{Value: s1[i2:i3]}
-
- return
-}
-
-func textPadLeft(args ...objects.Object) (ret objects.Object, err error) {
- argslen := len(args)
- if argslen != 2 && argslen != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- if i2 > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- sLen := len(s1)
- if sLen >= i2 {
- ret = &objects.String{Value: s1}
- return
- }
-
- s3 := " "
- if argslen == 3 {
- s3, ok = objects.ToString(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- }
-
- padStrLen := len(s3)
- if padStrLen == 0 {
- ret = &objects.String{Value: s1}
- return
- }
-
- padCount := ((i2 - padStrLen) / padStrLen) + 1
- retStr := strings.Repeat(s3, int(padCount)) + s1
- ret = &objects.String{Value: retStr[len(retStr)-i2:]}
-
- return
-}
-
-func textPadRight(args ...objects.Object) (ret objects.Object, err error) {
- argslen := len(args)
- if argslen != 2 && argslen != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- if i2 > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- sLen := len(s1)
- if sLen >= i2 {
- ret = &objects.String{Value: s1}
- return
- }
-
- s3 := " "
- if argslen == 3 {
- s3, ok = objects.ToString(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "string(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- }
-
- padStrLen := len(s3)
- if padStrLen == 0 {
- ret = &objects.String{Value: s1}
- return
- }
-
- padCount := ((i2 - padStrLen) / padStrLen) + 1
- retStr := s1 + strings.Repeat(s3, int(padCount))
- ret = &objects.String{Value: retStr[:i2]}
-
- return
-}
-
-func textRepeat(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- if len(s1)*i2 > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: strings.Repeat(s1, i2)}, nil
-}
-
-func textJoin(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- return nil, objects.ErrWrongNumArguments
- }
-
- var slen int
- var ss1 []string
- switch arg0 := args[0].(type) {
- case *objects.Array:
- for idx, a := range arg0.Value {
- as, ok := objects.ToString(a)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("first[%d]", idx),
- Expected: "string(compatible)",
- Found: a.TypeName(),
- }
- }
- slen += len(as)
- ss1 = append(ss1, as)
- }
- case *objects.ImmutableArray:
- for idx, a := range arg0.Value {
- as, ok := objects.ToString(a)
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: fmt.Sprintf("first[%d]", idx),
- Expected: "string(compatible)",
- Found: a.TypeName(),
- }
- }
- slen += len(as)
- ss1 = append(ss1, as)
- }
- default:
- return nil, objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "array",
- Found: args[0].TypeName(),
- }
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- return nil, objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- }
-
- // make sure output length does not exceed the limit
- if slen+len(s2)*(len(ss1)-1) > tengo.MaxStringLen {
- return nil, objects.ErrStringLimit
- }
-
- return &objects.String{Value: strings.Join(ss1, s2)}, nil
-}
-
-func textFormatBool(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- b1, ok := args[0].(*objects.Bool)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "bool",
- Found: args[0].TypeName(),
- }
- return
- }
-
- if b1 == objects.TrueValue {
- ret = &objects.String{Value: "true"}
- } else {
- ret = &objects.String{Value: "false"}
- }
-
- return
-}
-
-func textFormatFloat(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 4 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- f1, ok := args[0].(*objects.Float)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "float",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
-
- i4, ok := objects.ToInt(args[3])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "fourth",
- Expected: "int(compatible)",
- Found: args[3].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: strconv.FormatFloat(f1.Value, s2[0], i3, i4)}
-
- return
-}
-
-func textFormatInt(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := args[0].(*objects.Int)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: strconv.FormatInt(i1.Value, i2)}
-
- return
-}
-
-func textParseBool(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := args[0].(*objects.String)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- return
- }
-
- parsed, err := strconv.ParseBool(s1.Value)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- if parsed {
- ret = objects.TrueValue
- } else {
- ret = objects.FalseValue
- }
-
- return
-}
-
-func textParseFloat(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := args[0].(*objects.String)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- parsed, err := strconv.ParseFloat(s1.Value, i2)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- ret = &objects.Float{Value: parsed}
-
- return
-}
-
-func textParseInt(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 3 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := args[0].(*objects.String)
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
-
- parsed, err := strconv.ParseInt(s1.Value, i2, i3)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- ret = &objects.Int{Value: parsed}
-
- return
-}
-
-// Modified implementation of strings.Replace
-// to limit the maximum length of output string.
-func doTextReplace(s, old, new string, n int) (string, bool) {
- if old == new || n == 0 {
- return s, true // avoid allocation
- }
-
- // Compute number of replacements.
- if m := strings.Count(s, old); m == 0 {
- return s, true // avoid allocation
- } else if n < 0 || m < n {
- n = m
- }
-
- // Apply replacements to buffer.
- t := make([]byte, len(s)+n*(len(new)-len(old)))
- w := 0
- start := 0
- for i := 0; i < n; i++ {
- j := start
- if len(old) == 0 {
- if i > 0 {
- _, wid := utf8.DecodeRuneInString(s[start:])
- j += wid
- }
- } else {
- j += strings.Index(s[start:], old)
- }
-
- ssj := s[start:j]
- if w+len(ssj)+len(new) > tengo.MaxStringLen {
- return "", false
- }
-
- w += copy(t[w:], ssj)
- w += copy(t[w:], new)
- start = j + len(old)
- }
-
- ss := s[start:]
- if w+len(ss) > tengo.MaxStringLen {
- return "", false
- }
-
- w += copy(t[w:], ss)
-
- return string(t[0:w]), true
-}
diff --git a/vendor/github.com/d5/tengo/stdlib/times.go b/vendor/github.com/d5/tengo/stdlib/times.go
deleted file mode 100644
index 111c877a..00000000
--- a/vendor/github.com/d5/tengo/stdlib/times.go
+++ /dev/null
@@ -1,989 +0,0 @@
-package stdlib
-
-import (
- "time"
-
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
-)
-
-var timesModule = map[string]objects.Object{
- "format_ansic": &objects.String{Value: time.ANSIC},
- "format_unix_date": &objects.String{Value: time.UnixDate},
- "format_ruby_date": &objects.String{Value: time.RubyDate},
- "format_rfc822": &objects.String{Value: time.RFC822},
- "format_rfc822z": &objects.String{Value: time.RFC822Z},
- "format_rfc850": &objects.String{Value: time.RFC850},
- "format_rfc1123": &objects.String{Value: time.RFC1123},
- "format_rfc1123z": &objects.String{Value: time.RFC1123Z},
- "format_rfc3339": &objects.String{Value: time.RFC3339},
- "format_rfc3339_nano": &objects.String{Value: time.RFC3339Nano},
- "format_kitchen": &objects.String{Value: time.Kitchen},
- "format_stamp": &objects.String{Value: time.Stamp},
- "format_stamp_milli": &objects.String{Value: time.StampMilli},
- "format_stamp_micro": &objects.String{Value: time.StampMicro},
- "format_stamp_nano": &objects.String{Value: time.StampNano},
- "nanosecond": &objects.Int{Value: int64(time.Nanosecond)},
- "microsecond": &objects.Int{Value: int64(time.Microsecond)},
- "millisecond": &objects.Int{Value: int64(time.Millisecond)},
- "second": &objects.Int{Value: int64(time.Second)},
- "minute": &objects.Int{Value: int64(time.Minute)},
- "hour": &objects.Int{Value: int64(time.Hour)},
- "january": &objects.Int{Value: int64(time.January)},
- "february": &objects.Int{Value: int64(time.February)},
- "march": &objects.Int{Value: int64(time.March)},
- "april": &objects.Int{Value: int64(time.April)},
- "may": &objects.Int{Value: int64(time.May)},
- "june": &objects.Int{Value: int64(time.June)},
- "july": &objects.Int{Value: int64(time.July)},
- "august": &objects.Int{Value: int64(time.August)},
- "september": &objects.Int{Value: int64(time.September)},
- "october": &objects.Int{Value: int64(time.October)},
- "november": &objects.Int{Value: int64(time.November)},
- "december": &objects.Int{Value: int64(time.December)},
- "sleep": &objects.UserFunction{Name: "sleep", Value: timesSleep}, // sleep(int)
- "parse_duration": &objects.UserFunction{Name: "parse_duration", Value: timesParseDuration}, // parse_duration(str) => int
- "since": &objects.UserFunction{Name: "since", Value: timesSince}, // since(time) => int
- "until": &objects.UserFunction{Name: "until", Value: timesUntil}, // until(time) => int
- "duration_hours": &objects.UserFunction{Name: "duration_hours", Value: timesDurationHours}, // duration_hours(int) => float
- "duration_minutes": &objects.UserFunction{Name: "duration_minutes", Value: timesDurationMinutes}, // duration_minutes(int) => float
- "duration_nanoseconds": &objects.UserFunction{Name: "duration_nanoseconds", Value: timesDurationNanoseconds}, // duration_nanoseconds(int) => int
- "duration_seconds": &objects.UserFunction{Name: "duration_seconds", Value: timesDurationSeconds}, // duration_seconds(int) => float
- "duration_string": &objects.UserFunction{Name: "duration_string", Value: timesDurationString}, // duration_string(int) => string
- "month_string": &objects.UserFunction{Name: "month_string", Value: timesMonthString}, // month_string(int) => string
- "date": &objects.UserFunction{Name: "date", Value: timesDate}, // date(year, month, day, hour, min, sec, nsec) => time
- "now": &objects.UserFunction{Name: "now", Value: timesNow}, // now() => time
- "parse": &objects.UserFunction{Name: "parse", Value: timesParse}, // parse(format, str) => time
- "unix": &objects.UserFunction{Name: "unix", Value: timesUnix}, // unix(sec, nsec) => time
- "add": &objects.UserFunction{Name: "add", Value: timesAdd}, // add(time, int) => time
- "add_date": &objects.UserFunction{Name: "add_date", Value: timesAddDate}, // add_date(time, years, months, days) => time
- "sub": &objects.UserFunction{Name: "sub", Value: timesSub}, // sub(t time, u time) => int
- "after": &objects.UserFunction{Name: "after", Value: timesAfter}, // after(t time, u time) => bool
- "before": &objects.UserFunction{Name: "before", Value: timesBefore}, // before(t time, u time) => bool
- "time_year": &objects.UserFunction{Name: "time_year", Value: timesTimeYear}, // time_year(time) => int
- "time_month": &objects.UserFunction{Name: "time_month", Value: timesTimeMonth}, // time_month(time) => int
- "time_day": &objects.UserFunction{Name: "time_day", Value: timesTimeDay}, // time_day(time) => int
- "time_weekday": &objects.UserFunction{Name: "time_weekday", Value: timesTimeWeekday}, // time_weekday(time) => int
- "time_hour": &objects.UserFunction{Name: "time_hour", Value: timesTimeHour}, // time_hour(time) => int
- "time_minute": &objects.UserFunction{Name: "time_minute", Value: timesTimeMinute}, // time_minute(time) => int
- "time_second": &objects.UserFunction{Name: "time_second", Value: timesTimeSecond}, // time_second(time) => int
- "time_nanosecond": &objects.UserFunction{Name: "time_nanosecond", Value: timesTimeNanosecond}, // time_nanosecond(time) => int
- "time_unix": &objects.UserFunction{Name: "time_unix", Value: timesTimeUnix}, // time_unix(time) => int
- "time_unix_nano": &objects.UserFunction{Name: "time_unix_nano", Value: timesTimeUnixNano}, // time_unix_nano(time) => int
- "time_format": &objects.UserFunction{Name: "time_format", Value: timesTimeFormat}, // time_format(time, format) => string
- "time_location": &objects.UserFunction{Name: "time_location", Value: timesTimeLocation}, // time_location(time) => string
- "time_string": &objects.UserFunction{Name: "time_string", Value: timesTimeString}, // time_string(time) => string
- "is_zero": &objects.UserFunction{Name: "is_zero", Value: timesIsZero}, // is_zero(time) => bool
- "to_local": &objects.UserFunction{Name: "to_local", Value: timesToLocal}, // to_local(time) => time
- "to_utc": &objects.UserFunction{Name: "to_utc", Value: timesToUTC}, // to_utc(time) => time
-}
-
-func timesSleep(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- time.Sleep(time.Duration(i1))
- ret = objects.UndefinedValue
-
- return
-}
-
-func timesParseDuration(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- dur, err := time.ParseDuration(s1)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- ret = &objects.Int{Value: int64(dur)}
-
- return
-}
-
-func timesSince(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(time.Since(t1))}
-
- return
-}
-
-func timesUntil(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(time.Until(t1))}
-
- return
-}
-
-func timesDurationHours(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Float{Value: time.Duration(i1).Hours()}
-
- return
-}
-
-func timesDurationMinutes(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Float{Value: time.Duration(i1).Minutes()}
-
- return
-}
-
-func timesDurationNanoseconds(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: time.Duration(i1).Nanoseconds()}
-
- return
-}
-
-func timesDurationSeconds(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Float{Value: time.Duration(i1).Seconds()}
-
- return
-}
-
-func timesDurationString(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: time.Duration(i1).String()}
-
- return
-}
-
-func timesMonthString(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: time.Month(i1).String()}
-
- return
-}
-
-func timesDate(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 7 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
- i3, ok := objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
- i4, ok := objects.ToInt(args[3])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "fourth",
- Expected: "int(compatible)",
- Found: args[3].TypeName(),
- }
- return
- }
- i5, ok := objects.ToInt(args[4])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "fifth",
- Expected: "int(compatible)",
- Found: args[4].TypeName(),
- }
- return
- }
- i6, ok := objects.ToInt(args[5])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "sixth",
- Expected: "int(compatible)",
- Found: args[5].TypeName(),
- }
- return
- }
- i7, ok := objects.ToInt(args[6])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "seventh",
- Expected: "int(compatible)",
- Found: args[6].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: time.Date(i1, time.Month(i2), i3, i4, i5, i6, i7, time.Now().Location())}
-
- return
-}
-
-func timesNow(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 0 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- ret = &objects.Time{Value: time.Now()}
-
- return
-}
-
-func timesParse(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- s1, ok := objects.ToString(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "string(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- parsed, err := time.Parse(s1, s2)
- if err != nil {
- ret = wrapError(err)
- return
- }
-
- ret = &objects.Time{Value: parsed}
-
- return
-}
-
-func timesUnix(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- i1, ok := objects.ToInt64(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "int(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt64(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: time.Unix(i1, i2)}
-
- return
-}
-
-func timesAdd(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt64(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: t1.Add(time.Duration(i2))}
-
- return
-}
-
-func timesSub(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- t2, ok := objects.ToTime(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "time(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Sub(t2))}
-
- return
-}
-
-func timesAddDate(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 4 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- i2, ok := objects.ToInt(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "int(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- i3, ok := objects.ToInt(args[2])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "third",
- Expected: "int(compatible)",
- Found: args[2].TypeName(),
- }
- return
- }
-
- i4, ok := objects.ToInt(args[3])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "fourth",
- Expected: "int(compatible)",
- Found: args[3].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: t1.AddDate(i2, i3, i4)}
-
- return
-}
-
-func timesAfter(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- t2, ok := objects.ToTime(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "time(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- if t1.After(t2) {
- ret = objects.TrueValue
- } else {
- ret = objects.FalseValue
- }
-
- return
-}
-
-func timesBefore(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- t2, ok := objects.ToTime(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- if t1.Before(t2) {
- ret = objects.TrueValue
- } else {
- ret = objects.FalseValue
- }
-
- return
-}
-
-func timesTimeYear(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Year())}
-
- return
-}
-
-func timesTimeMonth(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Month())}
-
- return
-}
-
-func timesTimeDay(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Day())}
-
- return
-}
-
-func timesTimeWeekday(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Weekday())}
-
- return
-}
-
-func timesTimeHour(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Hour())}
-
- return
-}
-
-func timesTimeMinute(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Minute())}
-
- return
-}
-
-func timesTimeSecond(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Second())}
-
- return
-}
-
-func timesTimeNanosecond(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Nanosecond())}
-
- return
-}
-
-func timesTimeUnix(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.Unix())}
-
- return
-}
-
-func timesTimeUnixNano(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Int{Value: int64(t1.UnixNano())}
-
- return
-}
-
-func timesTimeFormat(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 2 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- s2, ok := objects.ToString(args[1])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "second",
- Expected: "string(compatible)",
- Found: args[1].TypeName(),
- }
- return
- }
-
- s := t1.Format(s2)
- if len(s) > tengo.MaxStringLen {
-
- return nil, objects.ErrStringLimit
- }
-
- ret = &objects.String{Value: s}
-
- return
-}
-
-func timesIsZero(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- if t1.IsZero() {
- ret = objects.TrueValue
- } else {
- ret = objects.FalseValue
- }
-
- return
-}
-
-func timesToLocal(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: t1.Local()}
-
- return
-}
-
-func timesToUTC(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.Time{Value: t1.UTC()}
-
- return
-}
-
-func timesTimeLocation(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: t1.Location().String()}
-
- return
-}
-
-func timesTimeString(args ...objects.Object) (ret objects.Object, err error) {
- if len(args) != 1 {
- err = objects.ErrWrongNumArguments
- return
- }
-
- t1, ok := objects.ToTime(args[0])
- if !ok {
- err = objects.ErrInvalidArgumentType{
- Name: "first",
- Expected: "time(compatible)",
- Found: args[0].TypeName(),
- }
- return
- }
-
- ret = &objects.String{Value: t1.String()}
-
- return
-}
diff --git a/vendor/github.com/d5/tengo/tengo.go b/vendor/github.com/d5/tengo/tengo.go
deleted file mode 100644
index a883bbd7..00000000
--- a/vendor/github.com/d5/tengo/tengo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package tengo
-
-var (
- // MaxStringLen is the maximum byte-length for string value.
- // Note this limit applies to all compiler/VM instances in the process.
- MaxStringLen = 2147483647
-
- // MaxBytesLen is the maximum length for bytes value.
- // Note this limit applies to all compiler/VM instances in the process.
- MaxBytesLen = 2147483647
-)
diff --git a/vendor/github.com/d5/tengo/.gitignore b/vendor/github.com/d5/tengo/v2/.gitignore
index 77738287..77738287 100644
--- a/vendor/github.com/d5/tengo/.gitignore
+++ b/vendor/github.com/d5/tengo/v2/.gitignore
diff --git a/vendor/github.com/d5/tengo/.goreleaser.yml b/vendor/github.com/d5/tengo/v2/.goreleaser.yml
index 9b1dffec..1bd14324 100644
--- a/vendor/github.com/d5/tengo/.goreleaser.yml
+++ b/vendor/github.com/d5/tengo/v2/.goreleaser.yml
@@ -11,15 +11,6 @@ builds:
- darwin
- linux
- windows
- - env:
- - CGO_ENABLED=0
- main: ./cmd/tengomin/main.go
- id: tengomin
- binary: tengomin
- goos:
- - darwin
- - linux
- - windows
archive:
files:
- none*
diff --git a/vendor/github.com/d5/tengo/LICENSE b/vendor/github.com/d5/tengo/v2/LICENSE
index 2516341a..2516341a 100644
--- a/vendor/github.com/d5/tengo/LICENSE
+++ b/vendor/github.com/d5/tengo/v2/LICENSE
diff --git a/vendor/github.com/d5/tengo/Makefile b/vendor/github.com/d5/tengo/v2/Makefile
index 99daafd1..793bc129 100644
--- a/vendor/github.com/d5/tengo/Makefile
+++ b/vendor/github.com/d5/tengo/v2/Makefile
@@ -1,13 +1,10 @@
-vet:
- go vet ./...
-
generate:
go generate ./...
lint:
golint -set_exit_status ./...
-test: generate vet lint
+test: generate lint
go test -race -cover ./...
fmt:
diff --git a/vendor/github.com/d5/tengo/README.md b/vendor/github.com/d5/tengo/v2/README.md
index 6a35cfd1..92277cfe 100644
--- a/vendor/github.com/d5/tengo/README.md
+++ b/vendor/github.com/d5/tengo/v2/README.md
@@ -1,21 +1,21 @@
<p align="center">
- <img src="https://raw.githubusercontent.com/d5/tengolang.com/master/logo_400.png" width="200" height="200">
+ <img src="https://raw.githubusercontent.com/d5/tengolang-share/master/logo_400.png" width="200" height="200">
</p>
# The Tengo Language
-[![GoDoc](https://godoc.org/github.com/d5/tengo?status.svg)](https://godoc.org/github.com/d5/tengo/script)
+[![GoDoc](https://godoc.org/github.com/d5/tengo?status.svg)](https://godoc.org/github.com/d5/tengo)
[![Go Report Card](https://goreportcard.com/badge/github.com/d5/tengo)](https://goreportcard.com/report/github.com/d5/tengo)
-[![Build Status](https://travis-ci.org/d5/tengo.svg?branch=master)](https://travis-ci.org/d5/tengo)
+[![CircleCI](https://circleci.com/gh/d5/tengo.svg?style=svg)](https://circleci.com/gh/d5/tengo)
[![Sourcegraph](https://sourcegraph.com/github.com/d5/tengo/-/badge.svg)](https://sourcegraph.com/github.com/d5/tengo?badge)
**Tengo is a small, dynamic, fast, secure script language for Go.**
-Tengo is **[fast](#benchmark)** and secure because it's compiled/executed as bytecode on stack-based VM that's written in native Go.
+Tengo is **[fast](#benchmark)** and secure because it's compiled/executed as
+bytecode on stack-based VM that's written in native Go.
```golang
/* The Tengo Language */
-
fmt := import("fmt")
each := func(seq, fn) {
@@ -31,19 +31,24 @@ fmt.println(sum(0, [1, 2, 3])) // "6"
fmt.println(sum("", [1, 2, 3])) // "123"
```
-> Run this code in the [Playground](https://tengolang.com/?s=0c8d5d0d88f2795a7093d7f35ae12c3afa17bea3)
+> Test this Tengo code in the
+> [Tengo Playground](https://tengolang.com/?s=0c8d5d0d88f2795a7093d7f35ae12c3afa17bea3)
## Features
-- Simple and highly readable [Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
+- Simple and highly readable
+ [Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
- Dynamic typing with type coercion
- Higher-order functions and closures
- Immutable values
- - Garbage collection
-- [Securely Embeddable](https://github.com/d5/tengo/blob/master/docs/interoperability.md) and [Extensible](https://github.com/d5/tengo/blob/master/docs/objects.md)
+- [Securely Embeddable](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
+ and [Extensible](https://github.com/d5/tengo/blob/master/docs/objects.md)
- Compiler/runtime written in native Go _(no external deps or cgo)_
-- Executable as a [standalone](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md) language / REPL
-- Use cases: rules engine, [state machine](https://github.com/d5/go-fsm), [gaming](https://github.com/d5/pbr), data pipeline, [transpiler](https://github.com/d5/tengo2lua)
+- Executable as a
+ [standalone](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
+ language / REPL
+- Use cases: rules engine, [state machine](https://github.com/d5/go-fsm),
+ data pipeline, [transpiler](https://github.com/d5/tengo2lua)
## Benchmark
@@ -61,16 +66,69 @@ fmt.println(sum("", [1, 2, 3])) // "123"
| [otto](https://github.com/robertkrimen/otto) | `68,377ms` | `11ms` | JS Interpreter on Go |
| [Anko](https://github.com/mattn/anko) | `92,579ms` | `18ms` | Interpreter on Go |
-_* [fib(35)](https://github.com/d5/tengobench/blob/master/code/fib.tengo): Fibonacci(35)_
-_* [fibt(35)](https://github.com/d5/tengobench/blob/master/code/fibtc.tengo): [tail-call](https://en.wikipedia.org/wiki/Tail_call) version of Fibonacci(35)_
+_* [fib(35)](https://github.com/d5/tengobench/blob/master/code/fib.tengo):
+Fibonacci(35)_
+_* [fibt(35)](https://github.com/d5/tengobench/blob/master/code/fibtc.tengo):
+[tail-call](https://en.wikipedia.org/wiki/Tail_call) version of Fibonacci(35)_
_* **Go** does not read the source code from file, while all other cases do_
_* See [here](https://github.com/d5/tengobench) for commands/codes used_
+## Quick Start
+
+A simple Go example code that compiles/runs Tengo script code with some input/output values:
+
+```golang
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/d5/tengo/v2"
+)
+
+func main() {
+ // Tengo script code
+ src := `
+each := func(seq, fn) {
+ for x in seq { fn(x) }
+}
+
+sum := 0
+mul := 1
+each([a, b, c, d], func(x) {
+ sum += x
+ mul *= x
+})`
+
+ // create a new Script instance
+ script := tengo.NewScript([]byte(src))
+
+ // set values
+ _ = script.Add("a", 1)
+ _ = script.Add("b", 9)
+ _ = script.Add("c", 8)
+ _ = script.Add("d", 4)
+
+ // run the script
+ compiled, err := script.RunContext(context.Background())
+ if err != nil {
+ panic(err)
+ }
+
+ // retrieve values
+ sum := compiled.Get("sum")
+ mul := compiled.Get("mul")
+ fmt.Println(sum, mul) // "22 288"
+}
+```
+
## References
- [Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
- [Object Types](https://github.com/d5/tengo/blob/master/docs/objects.md)
-- [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md) and [Operators](https://github.com/d5/tengo/blob/master/docs/operators.md)
+- [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md)
+ and [Operators](https://github.com/d5/tengo/blob/master/docs/operators.md)
- [Builtin Functions](https://github.com/d5/tengo/blob/master/docs/builtins.md)
- [Interoperability](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
- [Tengo CLI](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
diff --git a/vendor/github.com/d5/tengo/v2/builtins.go b/vendor/github.com/d5/tengo/v2/builtins.go
new file mode 100644
index 00000000..87f7fc3d
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/builtins.go
@@ -0,0 +1,502 @@
+package tengo
+
+var builtinFuncs = []*BuiltinFunction{
+ {
+ Name: "len",
+ Value: builtinLen,
+ },
+ {
+ Name: "copy",
+ Value: builtinCopy,
+ },
+ {
+ Name: "append",
+ Value: builtinAppend,
+ },
+ {
+ Name: "string",
+ Value: builtinString,
+ },
+ {
+ Name: "int",
+ Value: builtinInt,
+ },
+ {
+ Name: "bool",
+ Value: builtinBool,
+ },
+ {
+ Name: "float",
+ Value: builtinFloat,
+ },
+ {
+ Name: "char",
+ Value: builtinChar,
+ },
+ {
+ Name: "bytes",
+ Value: builtinBytes,
+ },
+ {
+ Name: "time",
+ Value: builtinTime,
+ },
+ {
+ Name: "is_int",
+ Value: builtinIsInt,
+ },
+ {
+ Name: "is_float",
+ Value: builtinIsFloat,
+ },
+ {
+ Name: "is_string",
+ Value: builtinIsString,
+ },
+ {
+ Name: "is_bool",
+ Value: builtinIsBool,
+ },
+ {
+ Name: "is_char",
+ Value: builtinIsChar,
+ },
+ {
+ Name: "is_bytes",
+ Value: builtinIsBytes,
+ },
+ {
+ Name: "is_array",
+ Value: builtinIsArray,
+ },
+ {
+ Name: "is_immutable_array",
+ Value: builtinIsImmutableArray,
+ },
+ {
+ Name: "is_map",
+ Value: builtinIsMap,
+ },
+ {
+ Name: "is_immutable_map",
+ Value: builtinIsImmutableMap,
+ },
+ {
+ Name: "is_iterable",
+ Value: builtinIsIterable,
+ },
+ {
+ Name: "is_time",
+ Value: builtinIsTime,
+ },
+ {
+ Name: "is_error",
+ Value: builtinIsError,
+ },
+ {
+ Name: "is_undefined",
+ Value: builtinIsUndefined,
+ },
+ {
+ Name: "is_function",
+ Value: builtinIsFunction,
+ },
+ {
+ Name: "is_callable",
+ Value: builtinIsCallable,
+ },
+ {
+ Name: "type_name",
+ Value: builtinTypeName,
+ },
+ {
+ Name: "format",
+ Value: builtinFormat,
+ },
+}
+
+// GetAllBuiltinFunctions returns all builtin function objects.
+func GetAllBuiltinFunctions() []*BuiltinFunction {
+ return append([]*BuiltinFunction{}, builtinFuncs...)
+}
+
+func builtinTypeName(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ return &String{Value: args[0].TypeName()}, nil
+}
+
+func builtinIsString(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*String); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsInt(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Int); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsFloat(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Float); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsBool(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Bool); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsChar(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Char); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsBytes(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Bytes); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsArray(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Array); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsImmutableArray(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*ImmutableArray); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsMap(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Map); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsImmutableMap(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*ImmutableMap); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsTime(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Time); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsError(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Error); ok {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsUndefined(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if args[0] == UndefinedValue {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsFunction(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ switch args[0].(type) {
+ case *CompiledFunction:
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsCallable(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if args[0].CanCall() {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+func builtinIsIterable(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if args[0].CanIterate() {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+}
+
+// len(obj object) => int
+func builtinLen(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ switch arg := args[0].(type) {
+ case *Array:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ case *ImmutableArray:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ case *String:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ case *Bytes:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ case *Map:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ case *ImmutableMap:
+ return &Int{Value: int64(len(arg.Value))}, nil
+ default:
+ return nil, ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "array/string/bytes/map",
+ Found: arg.TypeName(),
+ }
+ }
+}
+
+func builtinFormat(args ...Object) (Object, error) {
+ numArgs := len(args)
+ if numArgs == 0 {
+ return nil, ErrWrongNumArguments
+ }
+ format, ok := args[0].(*String)
+ if !ok {
+ return nil, ErrInvalidArgumentType{
+ Name: "format",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ }
+ if numArgs == 1 {
+ // okay to return 'format' directly as String is immutable
+ return format, nil
+ }
+ s, err := Format(format.Value, args[1:]...)
+ if err != nil {
+ return nil, err
+ }
+ return &String{Value: s}, nil
+}
+
+func builtinCopy(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ return args[0].Copy(), nil
+}
+
+func builtinString(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*String); ok {
+ return args[0], nil
+ }
+ v, ok := ToString(args[0])
+ if ok {
+ if len(v) > MaxStringLen {
+ return nil, ErrStringLimit
+ }
+ return &String{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinInt(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Int); ok {
+ return args[0], nil
+ }
+ v, ok := ToInt64(args[0])
+ if ok {
+ return &Int{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinFloat(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Float); ok {
+ return args[0], nil
+ }
+ v, ok := ToFloat64(args[0])
+ if ok {
+ return &Float{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinBool(args ...Object) (Object, error) {
+ if len(args) != 1 {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Bool); ok {
+ return args[0], nil
+ }
+ v, ok := ToBool(args[0])
+ if ok {
+ if v {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinChar(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Char); ok {
+ return args[0], nil
+ }
+ v, ok := ToRune(args[0])
+ if ok {
+ return &Char{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinBytes(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+
+ // bytes(N) => create a new bytes with given size N
+ if n, ok := args[0].(*Int); ok {
+ if n.Value > int64(MaxBytesLen) {
+ return nil, ErrBytesLimit
+ }
+ return &Bytes{Value: make([]byte, int(n.Value))}, nil
+ }
+ v, ok := ToByteSlice(args[0])
+ if ok {
+ if len(v) > MaxBytesLen {
+ return nil, ErrBytesLimit
+ }
+ return &Bytes{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+func builtinTime(args ...Object) (Object, error) {
+ argsLen := len(args)
+ if !(argsLen == 1 || argsLen == 2) {
+ return nil, ErrWrongNumArguments
+ }
+ if _, ok := args[0].(*Time); ok {
+ return args[0], nil
+ }
+ v, ok := ToTime(args[0])
+ if ok {
+ return &Time{Value: v}, nil
+ }
+ if argsLen == 2 {
+ return args[1], nil
+ }
+ return UndefinedValue, nil
+}
+
+// append(arr, items...)
+func builtinAppend(args ...Object) (Object, error) {
+ if len(args) < 2 {
+ return nil, ErrWrongNumArguments
+ }
+ switch arg := args[0].(type) {
+ case *Array:
+ return &Array{Value: append(arg.Value, args[1:]...)}, nil
+ case *ImmutableArray:
+ return &Array{Value: append(arg.Value, args[1:]...)}, nil
+ default:
+ return nil, ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "array",
+ Found: arg.TypeName(),
+ }
+ }
+}
diff --git a/vendor/github.com/d5/tengo/v2/bytecode.go b/vendor/github.com/d5/tengo/v2/bytecode.go
new file mode 100644
index 00000000..cfd0d0b5
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/bytecode.go
@@ -0,0 +1,292 @@
+package tengo
+
+import (
+ "encoding/gob"
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/d5/tengo/v2/parser"
+)
+
+// Bytecode is a compiled instructions and constants.
+type Bytecode struct {
+ FileSet *parser.SourceFileSet
+ MainFunction *CompiledFunction
+ Constants []Object
+}
+
+// Encode writes Bytecode data to the writer.
+func (b *Bytecode) Encode(w io.Writer) error {
+ enc := gob.NewEncoder(w)
+ if err := enc.Encode(b.FileSet); err != nil {
+ return err
+ }
+ if err := enc.Encode(b.MainFunction); err != nil {
+ return err
+ }
+ return enc.Encode(b.Constants)
+}
+
+// CountObjects returns the number of objects found in Constants.
+func (b *Bytecode) CountObjects() int {
+ n := 0
+ for _, c := range b.Constants {
+ n += CountObjects(c)
+ }
+ return n
+}
+
+// FormatInstructions returns human readable string representations of
+// compiled instructions.
+func (b *Bytecode) FormatInstructions() []string {
+ return FormatInstructions(b.MainFunction.Instructions, 0)
+}
+
+// FormatConstants returns human readable string representations of
+// compiled constants.
+func (b *Bytecode) FormatConstants() (output []string) {
+ for cidx, cn := range b.Constants {
+ switch cn := cn.(type) {
+ case *CompiledFunction:
+ output = append(output, fmt.Sprintf(
+ "[% 3d] (Compiled Function|%p)", cidx, &cn))
+ for _, l := range FormatInstructions(cn.Instructions, 0) {
+ output = append(output, fmt.Sprintf(" %s", l))
+ }
+ default:
+ output = append(output, fmt.Sprintf("[% 3d] %s (%s|%p)",
+ cidx, cn, reflect.TypeOf(cn).Elem().Name(), &cn))
+ }
+ }
+ return
+}
+
+// Decode reads Bytecode data from the reader.
+func (b *Bytecode) Decode(r io.Reader, modules *ModuleMap) error {
+ if modules == nil {
+ modules = NewModuleMap()
+ }
+
+ dec := gob.NewDecoder(r)
+ if err := dec.Decode(&b.FileSet); err != nil {
+ return err
+ }
+ // TODO: files in b.FileSet.File does not have their 'set' field properly
+ // set to b.FileSet as it's private field and not serialized by gob
+ // encoder/decoder.
+ if err := dec.Decode(&b.MainFunction); err != nil {
+ return err
+ }
+ if err := dec.Decode(&b.Constants); err != nil {
+ return err
+ }
+ for i, v := range b.Constants {
+ fv, err := fixDecodedObject(v, modules)
+ if err != nil {
+ return err
+ }
+ b.Constants[i] = fv
+ }
+ return nil
+}
+
+// RemoveDuplicates finds and remove the duplicate values in Constants.
+// Note this function mutates Bytecode.
+func (b *Bytecode) RemoveDuplicates() {
+ var deduped []Object
+
+ indexMap := make(map[int]int) // mapping from old constant index to new index
+ ints := make(map[int64]int)
+ strings := make(map[string]int)
+ floats := make(map[float64]int)
+ chars := make(map[rune]int)
+ immutableMaps := make(map[string]int) // for modules
+
+ for curIdx, c := range b.Constants {
+ switch c := c.(type) {
+ case *CompiledFunction:
+ // add to deduped list
+ indexMap[curIdx] = len(deduped)
+ deduped = append(deduped, c)
+ case *ImmutableMap:
+ modName := inferModuleName(c)
+ newIdx, ok := immutableMaps[modName]
+ if modName != "" && ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ immutableMaps[modName] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
+ case *Int:
+ if newIdx, ok := ints[c.Value]; ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ ints[c.Value] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
+ case *String:
+ if newIdx, ok := strings[c.Value]; ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ strings[c.Value] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
+ case *Float:
+ if newIdx, ok := floats[c.Value]; ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ floats[c.Value] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
+ case *Char:
+ if newIdx, ok := chars[c.Value]; ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ chars[c.Value] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
+ default:
+ panic(fmt.Errorf("unsupported top-level constant type: %s",
+ c.TypeName()))
+ }
+ }
+
+ // replace with de-duplicated constants
+ b.Constants = deduped
+
+ // update CONST instructions with new indexes
+ // main function
+ updateConstIndexes(b.MainFunction.Instructions, indexMap)
+ // other compiled functions in constants
+ for _, c := range b.Constants {
+ switch c := c.(type) {
+ case *CompiledFunction:
+ updateConstIndexes(c.Instructions, indexMap)
+ }
+ }
+}
+
+func fixDecodedObject(
+ o Object,
+ modules *ModuleMap,
+) (Object, error) {
+ switch o := o.(type) {
+ case *Bool:
+ if o.IsFalsy() {
+ return FalseValue, nil
+ }
+ return TrueValue, nil
+ case *Undefined:
+ return UndefinedValue, nil
+ case *Array:
+ for i, v := range o.Value {
+ fv, err := fixDecodedObject(v, modules)
+ if err != nil {
+ return nil, err
+ }
+ o.Value[i] = fv
+ }
+ case *ImmutableArray:
+ for i, v := range o.Value {
+ fv, err := fixDecodedObject(v, modules)
+ if err != nil {
+ return nil, err
+ }
+ o.Value[i] = fv
+ }
+ case *Map:
+ for k, v := range o.Value {
+ fv, err := fixDecodedObject(v, modules)
+ if err != nil {
+ return nil, err
+ }
+ o.Value[k] = fv
+ }
+ case *ImmutableMap:
+ modName := inferModuleName(o)
+ if mod := modules.GetBuiltinModule(modName); mod != nil {
+ return mod.AsImmutableMap(modName), nil
+ }
+
+ for k, v := range o.Value {
+ // encoding of user function not supported
+ if _, isUserFunction := v.(*UserFunction); isUserFunction {
+ return nil, fmt.Errorf("user function not decodable")
+ }
+
+ fv, err := fixDecodedObject(v, modules)
+ if err != nil {
+ return nil, err
+ }
+ o.Value[k] = fv
+ }
+ }
+ return o, nil
+}
+
+func updateConstIndexes(insts []byte, indexMap map[int]int) {
+ i := 0
+ for i < len(insts) {
+ op := insts[i]
+ numOperands := parser.OpcodeOperands[op]
+ _, read := parser.ReadOperands(numOperands, insts[i+1:])
+
+ switch op {
+ case parser.OpConstant:
+ curIdx := int(insts[i+2]) | int(insts[i+1])<<8
+ newIdx, ok := indexMap[curIdx]
+ if !ok {
+ panic(fmt.Errorf("constant index not found: %d", curIdx))
+ }
+ copy(insts[i:], MakeInstruction(op, newIdx))
+ case parser.OpClosure:
+ curIdx := int(insts[i+2]) | int(insts[i+1])<<8
+ numFree := int(insts[i+3])
+ newIdx, ok := indexMap[curIdx]
+ if !ok {
+ panic(fmt.Errorf("constant index not found: %d", curIdx))
+ }
+ copy(insts[i:], MakeInstruction(op, newIdx, numFree))
+ }
+
+ i += 1 + read
+ }
+}
+
+func inferModuleName(mod *ImmutableMap) string {
+ if modName, ok := mod.Value["__module_name__"].(*String); ok {
+ return modName.Value
+ }
+ return ""
+}
+
+func init() {
+ gob.Register(&parser.SourceFileSet{})
+ gob.Register(&parser.SourceFile{})
+ gob.Register(&Array{})
+ gob.Register(&Bool{})
+ gob.Register(&Bytes{})
+ gob.Register(&Char{})
+ gob.Register(&CompiledFunction{})
+ gob.Register(&Error{})
+ gob.Register(&Float{})
+ gob.Register(&ImmutableArray{})
+ gob.Register(&ImmutableMap{})
+ gob.Register(&Int{})
+ gob.Register(&Map{})
+ gob.Register(&String{})
+ gob.Register(&Time{})
+ gob.Register(&Undefined{})
+ gob.Register(&UserFunction{})
+}
diff --git a/vendor/github.com/d5/tengo/v2/compiler.go b/vendor/github.com/d5/tengo/v2/compiler.go
new file mode 100644
index 00000000..eb686ed6
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/compiler.go
@@ -0,0 +1,1312 @@
+package tengo
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "path/filepath"
+ "reflect"
+ "strings"
+
+ "github.com/d5/tengo/v2/parser"
+ "github.com/d5/tengo/v2/token"
+)
+
+// compilationScope represents a compiled instructions and the last two
+// instructions that were emitted.
+type compilationScope struct {
+ Instructions []byte
+ SymbolInit map[string]bool
+ SourceMap map[int]parser.Pos
+}
+
+// loop represents a loop construct that the compiler uses to track the current
+// loop.
+type loop struct {
+ Continues []int
+ Breaks []int
+}
+
+// CompilerError represents a compiler error.
+type CompilerError struct {
+ FileSet *parser.SourceFileSet
+ Node parser.Node
+ Err error
+}
+
+func (e *CompilerError) Error() string {
+ filePos := e.FileSet.Position(e.Node.Pos())
+ return fmt.Sprintf("Compile Error: %s\n\tat %s", e.Err.Error(), filePos)
+}
+
+// Compiler compiles the AST into a bytecode.
+type Compiler struct {
+ file *parser.SourceFile
+ parent *Compiler
+ modulePath string
+ constants []Object
+ symbolTable *SymbolTable
+ scopes []compilationScope
+ scopeIndex int
+ modules *ModuleMap
+ compiledModules map[string]*CompiledFunction
+ allowFileImport bool
+ loops []*loop
+ loopIndex int
+ trace io.Writer
+ indent int
+}
+
+// NewCompiler creates a Compiler.
+func NewCompiler(
+ file *parser.SourceFile,
+ symbolTable *SymbolTable,
+ constants []Object,
+ modules *ModuleMap,
+ trace io.Writer,
+) *Compiler {
+ mainScope := compilationScope{
+ SymbolInit: make(map[string]bool),
+ SourceMap: make(map[int]parser.Pos),
+ }
+
+ // symbol table
+ if symbolTable == nil {
+ symbolTable = NewSymbolTable()
+ }
+
+ // add builtin functions to the symbol table
+ for idx, fn := range builtinFuncs {
+ symbolTable.DefineBuiltin(idx, fn.Name)
+ }
+
+ // builtin modules
+ if modules == nil {
+ modules = NewModuleMap()
+ }
+
+ return &Compiler{
+ file: file,
+ symbolTable: symbolTable,
+ constants: constants,
+ scopes: []compilationScope{mainScope},
+ scopeIndex: 0,
+ loopIndex: -1,
+ trace: trace,
+ modules: modules,
+ compiledModules: make(map[string]*CompiledFunction),
+ }
+}
+
+// Compile compiles the AST node.
+func (c *Compiler) Compile(node parser.Node) error {
+ if c.trace != nil {
+ if node != nil {
+ defer untracec(tracec(c, fmt.Sprintf("%s (%s)",
+ node.String(), reflect.TypeOf(node).Elem().Name())))
+ } else {
+ defer untracec(tracec(c, "<nil>"))
+ }
+ }
+
+ switch node := node.(type) {
+ case *parser.File:
+ for _, stmt := range node.Stmts {
+ if err := c.Compile(stmt); err != nil {
+ return err
+ }
+ }
+ case *parser.ExprStmt:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpPop)
+ case *parser.IncDecStmt:
+ op := token.AddAssign
+ if node.Token == token.Dec {
+ op = token.SubAssign
+ }
+ return c.compileAssign(node, []parser.Expr{node.Expr},
+ []parser.Expr{&parser.IntLit{Value: 1}}, op)
+ case *parser.ParenExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ case *parser.BinaryExpr:
+ if node.Token == token.LAnd || node.Token == token.LOr {
+ return c.compileLogical(node)
+ }
+ if node.Token == token.Less {
+ if err := c.Compile(node.RHS); err != nil {
+ return err
+ }
+ if err := c.Compile(node.LHS); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpBinaryOp, int(token.Greater))
+ return nil
+ } else if node.Token == token.LessEq {
+ if err := c.Compile(node.RHS); err != nil {
+ return err
+ }
+ if err := c.Compile(node.LHS); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
+ return nil
+ }
+ if err := c.Compile(node.LHS); err != nil {
+ return err
+ }
+ if err := c.Compile(node.RHS); err != nil {
+ return err
+ }
+
+ switch node.Token {
+ case token.Add:
+ c.emit(node, parser.OpBinaryOp, int(token.Add))
+ case token.Sub:
+ c.emit(node, parser.OpBinaryOp, int(token.Sub))
+ case token.Mul:
+ c.emit(node, parser.OpBinaryOp, int(token.Mul))
+ case token.Quo:
+ c.emit(node, parser.OpBinaryOp, int(token.Quo))
+ case token.Rem:
+ c.emit(node, parser.OpBinaryOp, int(token.Rem))
+ case token.Greater:
+ c.emit(node, parser.OpBinaryOp, int(token.Greater))
+ case token.GreaterEq:
+ c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
+ case token.Equal:
+ c.emit(node, parser.OpEqual)
+ case token.NotEqual:
+ c.emit(node, parser.OpNotEqual)
+ case token.And:
+ c.emit(node, parser.OpBinaryOp, int(token.And))
+ case token.Or:
+ c.emit(node, parser.OpBinaryOp, int(token.Or))
+ case token.Xor:
+ c.emit(node, parser.OpBinaryOp, int(token.Xor))
+ case token.AndNot:
+ c.emit(node, parser.OpBinaryOp, int(token.AndNot))
+ case token.Shl:
+ c.emit(node, parser.OpBinaryOp, int(token.Shl))
+ case token.Shr:
+ c.emit(node, parser.OpBinaryOp, int(token.Shr))
+ default:
+ return c.errorf(node, "invalid binary operator: %s",
+ node.Token.String())
+ }
+ case *parser.IntLit:
+ c.emit(node, parser.OpConstant,
+ c.addConstant(&Int{Value: node.Value}))
+ case *parser.FloatLit:
+ c.emit(node, parser.OpConstant,
+ c.addConstant(&Float{Value: node.Value}))
+ case *parser.BoolLit:
+ if node.Value {
+ c.emit(node, parser.OpTrue)
+ } else {
+ c.emit(node, parser.OpFalse)
+ }
+ case *parser.StringLit:
+ if len(node.Value) > MaxStringLen {
+ return c.error(node, ErrStringLimit)
+ }
+ c.emit(node, parser.OpConstant,
+ c.addConstant(&String{Value: node.Value}))
+ case *parser.CharLit:
+ c.emit(node, parser.OpConstant,
+ c.addConstant(&Char{Value: node.Value}))
+ case *parser.UndefinedLit:
+ c.emit(node, parser.OpNull)
+ case *parser.UnaryExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+
+ switch node.Token {
+ case token.Not:
+ c.emit(node, parser.OpLNot)
+ case token.Sub:
+ c.emit(node, parser.OpMinus)
+ case token.Xor:
+ c.emit(node, parser.OpBComplement)
+ case token.Add:
+ // do nothing?
+ default:
+ return c.errorf(node,
+ "invalid unary operator: %s", node.Token.String())
+ }
+ case *parser.IfStmt:
+ // open new symbol table for the statement
+ c.symbolTable = c.symbolTable.Fork(true)
+ defer func() {
+ c.symbolTable = c.symbolTable.Parent(false)
+ }()
+
+ if node.Init != nil {
+ if err := c.Compile(node.Init); err != nil {
+ return err
+ }
+ }
+ if err := c.Compile(node.Cond); err != nil {
+ return err
+ }
+
+ // first jump placeholder
+ jumpPos1 := c.emit(node, parser.OpJumpFalsy, 0)
+ if err := c.Compile(node.Body); err != nil {
+ return err
+ }
+ if node.Else != nil {
+ // second jump placeholder
+ jumpPos2 := c.emit(node, parser.OpJump, 0)
+
+ // update first jump offset
+ curPos := len(c.currentInstructions())
+ c.changeOperand(jumpPos1, curPos)
+ if err := c.Compile(node.Else); err != nil {
+ return err
+ }
+
+ // update second jump offset
+ curPos = len(c.currentInstructions())
+ c.changeOperand(jumpPos2, curPos)
+ } else {
+ // update first jump offset
+ curPos := len(c.currentInstructions())
+ c.changeOperand(jumpPos1, curPos)
+ }
+ case *parser.ForStmt:
+ return c.compileForStmt(node)
+ case *parser.ForInStmt:
+ return c.compileForInStmt(node)
+ case *parser.BranchStmt:
+ if node.Token == token.Break {
+ curLoop := c.currentLoop()
+ if curLoop == nil {
+ return c.errorf(node, "break not allowed outside loop")
+ }
+ pos := c.emit(node, parser.OpJump, 0)
+ curLoop.Breaks = append(curLoop.Breaks, pos)
+ } else if node.Token == token.Continue {
+ curLoop := c.currentLoop()
+ if curLoop == nil {
+ return c.errorf(node, "continue not allowed outside loop")
+ }
+ pos := c.emit(node, parser.OpJump, 0)
+ curLoop.Continues = append(curLoop.Continues, pos)
+ } else {
+ panic(fmt.Errorf("invalid branch statement: %s",
+ node.Token.String()))
+ }
+ case *parser.BlockStmt:
+ if len(node.Stmts) == 0 {
+ return nil
+ }
+
+ c.symbolTable = c.symbolTable.Fork(true)
+ defer func() {
+ c.symbolTable = c.symbolTable.Parent(false)
+ }()
+
+ for _, stmt := range node.Stmts {
+ if err := c.Compile(stmt); err != nil {
+ return err
+ }
+ }
+ case *parser.AssignStmt:
+ err := c.compileAssign(node, node.LHS, node.RHS, node.Token)
+ if err != nil {
+ return err
+ }
+ case *parser.Ident:
+ symbol, _, ok := c.symbolTable.Resolve(node.Name)
+ if !ok {
+ return c.errorf(node, "unresolved reference '%s'", node.Name)
+ }
+
+ switch symbol.Scope {
+ case ScopeGlobal:
+ c.emit(node, parser.OpGetGlobal, symbol.Index)
+ case ScopeLocal:
+ c.emit(node, parser.OpGetLocal, symbol.Index)
+ case ScopeBuiltin:
+ c.emit(node, parser.OpGetBuiltin, symbol.Index)
+ case ScopeFree:
+ c.emit(node, parser.OpGetFree, symbol.Index)
+ }
+ case *parser.ArrayLit:
+ for _, elem := range node.Elements {
+ if err := c.Compile(elem); err != nil {
+ return err
+ }
+ }
+ c.emit(node, parser.OpArray, len(node.Elements))
+ case *parser.MapLit:
+ for _, elt := range node.Elements {
+ // key
+ if len(elt.Key) > MaxStringLen {
+ return c.error(node, ErrStringLimit)
+ }
+ c.emit(node, parser.OpConstant,
+ c.addConstant(&String{Value: elt.Key}))
+
+ // value
+ if err := c.Compile(elt.Value); err != nil {
+ return err
+ }
+ }
+ c.emit(node, parser.OpMap, len(node.Elements)*2)
+
+ case *parser.SelectorExpr: // selector on RHS side
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ if err := c.Compile(node.Sel); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpIndex)
+ case *parser.IndexExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ if err := c.Compile(node.Index); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpIndex)
+ case *parser.SliceExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ if node.Low != nil {
+ if err := c.Compile(node.Low); err != nil {
+ return err
+ }
+ } else {
+ c.emit(node, parser.OpNull)
+ }
+ if node.High != nil {
+ if err := c.Compile(node.High); err != nil {
+ return err
+ }
+ } else {
+ c.emit(node, parser.OpNull)
+ }
+ c.emit(node, parser.OpSliceIndex)
+ case *parser.FuncLit:
+ c.enterScope()
+
+ for _, p := range node.Type.Params.List {
+ s := c.symbolTable.Define(p.Name)
+
+ // function arguments is not assigned directly.
+ s.LocalAssigned = true
+ }
+
+ if err := c.Compile(node.Body); err != nil {
+ return err
+ }
+
+ // code optimization
+ c.optimizeFunc(node)
+
+ freeSymbols := c.symbolTable.FreeSymbols()
+ numLocals := c.symbolTable.MaxSymbols()
+ instructions, sourceMap := c.leaveScope()
+
+ for _, s := range freeSymbols {
+ switch s.Scope {
+ case ScopeLocal:
+ if !s.LocalAssigned {
+ // Here, the closure is capturing a local variable that's
+ // not yet assigned its value. One example is a local
+ // recursive function:
+ //
+ // func() {
+ // foo := func(x) {
+ // // ..
+ // return foo(x-1)
+ // }
+ // }
+ //
+ // which translate into
+ //
+ // 0000 GETL 0
+ // 0002 CLOSURE ? 1
+ // 0006 DEFL 0
+ //
+ // . So the local variable (0) is being captured before
+ // it's assigned the value.
+ //
+ // Solution is to transform the code into something like
+ // this:
+ //
+ // func() {
+ // foo := undefined
+ // foo = func(x) {
+ // // ..
+ // return foo(x-1)
+ // }
+ // }
+ //
+ // that is equivalent to
+ //
+ // 0000 NULL
+ // 0001 DEFL 0
+ // 0003 GETL 0
+ // 0005 CLOSURE ? 1
+ // 0009 SETL 0
+ //
+ c.emit(node, parser.OpNull)
+ c.emit(node, parser.OpDefineLocal, s.Index)
+ s.LocalAssigned = true
+ }
+ c.emit(node, parser.OpGetLocalPtr, s.Index)
+ case ScopeFree:
+ c.emit(node, parser.OpGetFreePtr, s.Index)
+ }
+ }
+
+ compiledFunction := &CompiledFunction{
+ Instructions: instructions,
+ NumLocals: numLocals,
+ NumParameters: len(node.Type.Params.List),
+ VarArgs: node.Type.Params.VarArgs,
+ SourceMap: sourceMap,
+ }
+ if len(freeSymbols) > 0 {
+ c.emit(node, parser.OpClosure,
+ c.addConstant(compiledFunction), len(freeSymbols))
+ } else {
+ c.emit(node, parser.OpConstant, c.addConstant(compiledFunction))
+ }
+ case *parser.ReturnStmt:
+ if c.symbolTable.Parent(true) == nil {
+ // outside the function
+ return c.errorf(node, "return not allowed outside function")
+ }
+
+ if node.Result == nil {
+ c.emit(node, parser.OpReturn, 0)
+ } else {
+ if err := c.Compile(node.Result); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpReturn, 1)
+ }
+ case *parser.CallExpr:
+ if err := c.Compile(node.Func); err != nil {
+ return err
+ }
+ for _, arg := range node.Args {
+ if err := c.Compile(arg); err != nil {
+ return err
+ }
+ }
+ c.emit(node, parser.OpCall, len(node.Args))
+ case *parser.ImportExpr:
+ if node.ModuleName == "" {
+ return c.errorf(node, "empty module name")
+ }
+
+ if mod := c.modules.Get(node.ModuleName); mod != nil {
+ v, err := mod.Import(node.ModuleName)
+ if err != nil {
+ return err
+ }
+
+ switch v := v.(type) {
+ case []byte: // module written in Tengo
+ compiled, err := c.compileModule(node,
+ node.ModuleName, node.ModuleName, v)
+ if err != nil {
+ return err
+ }
+ c.emit(node, parser.OpConstant, c.addConstant(compiled))
+ c.emit(node, parser.OpCall, 0)
+ case Object: // builtin module
+ c.emit(node, parser.OpConstant, c.addConstant(v))
+ default:
+ panic(fmt.Errorf("invalid import value type: %T", v))
+ }
+ } else if c.allowFileImport {
+ moduleName := node.ModuleName
+ if !strings.HasSuffix(moduleName, ".tengo") {
+ moduleName += ".tengo"
+ }
+
+ modulePath, err := filepath.Abs(moduleName)
+ if err != nil {
+ return c.errorf(node, "module file path error: %s",
+ err.Error())
+ }
+
+ if err := c.checkCyclicImports(node, modulePath); err != nil {
+ return err
+ }
+
+ moduleSrc, err := ioutil.ReadFile(moduleName)
+ if err != nil {
+ return c.errorf(node, "module file read error: %s",
+ err.Error())
+ }
+
+ compiled, err := c.compileModule(node,
+ moduleName, modulePath, moduleSrc)
+ if err != nil {
+ return err
+ }
+ c.emit(node, parser.OpConstant, c.addConstant(compiled))
+ c.emit(node, parser.OpCall, 0)
+ } else {
+ return c.errorf(node, "module '%s' not found", node.ModuleName)
+ }
+ case *parser.ExportStmt:
+ // export statement must be in top-level scope
+ if c.scopeIndex != 0 {
+ return c.errorf(node, "export not allowed inside function")
+ }
+
+ // export statement is simply ignore when compiling non-module code
+ if c.parent == nil {
+ break
+ }
+ if err := c.Compile(node.Result); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpImmutable)
+ c.emit(node, parser.OpReturn, 1)
+ case *parser.ErrorExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpError)
+ case *parser.ImmutableExpr:
+ if err := c.Compile(node.Expr); err != nil {
+ return err
+ }
+ c.emit(node, parser.OpImmutable)
+ case *parser.CondExpr:
+ if err := c.Compile(node.Cond); err != nil {
+ return err
+ }
+
+ // first jump placeholder
+ jumpPos1 := c.emit(node, parser.OpJumpFalsy, 0)
+ if err := c.Compile(node.True); err != nil {
+ return err
+ }
+
+ // second jump placeholder
+ jumpPos2 := c.emit(node, parser.OpJump, 0)
+
+ // update first jump offset
+ curPos := len(c.currentInstructions())
+ c.changeOperand(jumpPos1, curPos)
+ if err := c.Compile(node.False); err != nil {
+ return err
+ }
+
+ // update second jump offset
+ curPos = len(c.currentInstructions())
+ c.changeOperand(jumpPos2, curPos)
+ }
+ return nil
+}
+
+// Bytecode returns a compiled bytecode.
+func (c *Compiler) Bytecode() *Bytecode {
+ return &Bytecode{
+ FileSet: c.file.Set(),
+ MainFunction: &CompiledFunction{
+ Instructions: append(c.currentInstructions(), parser.OpSuspend),
+ SourceMap: c.currentSourceMap(),
+ },
+ Constants: c.constants,
+ }
+}
+
+// EnableFileImport enables or disables module loading from local files.
+// Local file modules are disabled by default.
+func (c *Compiler) EnableFileImport(enable bool) {
+ c.allowFileImport = enable
+}
+
+func (c *Compiler) compileAssign(
+ node parser.Node,
+ lhs, rhs []parser.Expr,
+ op token.Token,
+) error {
+ numLHS, numRHS := len(lhs), len(rhs)
+ if numLHS > 1 || numRHS > 1 {
+ return c.errorf(node, "tuple assignment not allowed")
+ }
+
+ // resolve and compile left-hand side
+ ident, selectors := resolveAssignLHS(lhs[0])
+ numSel := len(selectors)
+
+ if op == token.Define && numSel > 0 {
+ // using selector on new variable does not make sense
+ return c.errorf(node, "operator ':=' not allowed with selector")
+ }
+
+ symbol, depth, exists := c.symbolTable.Resolve(ident)
+ if op == token.Define {
+ if depth == 0 && exists {
+ return c.errorf(node, "'%s' redeclared in this block", ident)
+ }
+ symbol = c.symbolTable.Define(ident)
+ } else {
+ if !exists {
+ return c.errorf(node, "unresolved reference '%s'", ident)
+ }
+ }
+
+ // +=, -=, *=, /=
+ if op != token.Assign && op != token.Define {
+ if err := c.Compile(lhs[0]); err != nil {
+ return err
+ }
+ }
+
+ // compile RHSs
+ for _, expr := range rhs {
+ if err := c.Compile(expr); err != nil {
+ return err
+ }
+ }
+
+ switch op {
+ case token.AddAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Add))
+ case token.SubAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Sub))
+ case token.MulAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Mul))
+ case token.QuoAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Quo))
+ case token.RemAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Rem))
+ case token.AndAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.And))
+ case token.OrAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Or))
+ case token.AndNotAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.AndNot))
+ case token.XorAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Xor))
+ case token.ShlAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Shl))
+ case token.ShrAssign:
+ c.emit(node, parser.OpBinaryOp, int(token.Shr))
+ }
+
+ // compile selector expressions (right to left)
+ for i := numSel - 1; i >= 0; i-- {
+ if err := c.Compile(selectors[i]); err != nil {
+ return err
+ }
+ }
+
+ switch symbol.Scope {
+ case ScopeGlobal:
+ if numSel > 0 {
+ c.emit(node, parser.OpSetSelGlobal, symbol.Index, numSel)
+ } else {
+ c.emit(node, parser.OpSetGlobal, symbol.Index)
+ }
+ case ScopeLocal:
+ if numSel > 0 {
+ c.emit(node, parser.OpSetSelLocal, symbol.Index, numSel)
+ } else {
+ if op == token.Define && !symbol.LocalAssigned {
+ c.emit(node, parser.OpDefineLocal, symbol.Index)
+ } else {
+ c.emit(node, parser.OpSetLocal, symbol.Index)
+ }
+ }
+
+ // mark the symbol as local-assigned
+ symbol.LocalAssigned = true
+ case ScopeFree:
+ if numSel > 0 {
+ c.emit(node, parser.OpSetSelFree, symbol.Index, numSel)
+ } else {
+ c.emit(node, parser.OpSetFree, symbol.Index)
+ }
+ default:
+ panic(fmt.Errorf("invalid assignment variable scope: %s",
+ symbol.Scope))
+ }
+ return nil
+}
+
+func (c *Compiler) compileLogical(node *parser.BinaryExpr) error {
+ // left side term
+ if err := c.Compile(node.LHS); err != nil {
+ return err
+ }
+
+ // jump position
+ var jumpPos int
+ if node.Token == token.LAnd {
+ jumpPos = c.emit(node, parser.OpAndJump, 0)
+ } else {
+ jumpPos = c.emit(node, parser.OpOrJump, 0)
+ }
+
+ // right side term
+ if err := c.Compile(node.RHS); err != nil {
+ return err
+ }
+
+ c.changeOperand(jumpPos, len(c.currentInstructions()))
+ return nil
+}
+
+func (c *Compiler) compileForStmt(stmt *parser.ForStmt) error {
+ c.symbolTable = c.symbolTable.Fork(true)
+ defer func() {
+ c.symbolTable = c.symbolTable.Parent(false)
+ }()
+
+ // init statement
+ if stmt.Init != nil {
+ if err := c.Compile(stmt.Init); err != nil {
+ return err
+ }
+ }
+
+ // pre-condition position
+ preCondPos := len(c.currentInstructions())
+
+ // condition expression
+ postCondPos := -1
+ if stmt.Cond != nil {
+ if err := c.Compile(stmt.Cond); err != nil {
+ return err
+ }
+ // condition jump position
+ postCondPos = c.emit(stmt, parser.OpJumpFalsy, 0)
+ }
+
+ // enter loop
+ loop := c.enterLoop()
+
+ // body statement
+ if err := c.Compile(stmt.Body); err != nil {
+ c.leaveLoop()
+ return err
+ }
+
+ c.leaveLoop()
+
+ // post-body position
+ postBodyPos := len(c.currentInstructions())
+
+ // post statement
+ if stmt.Post != nil {
+ if err := c.Compile(stmt.Post); err != nil {
+ return err
+ }
+ }
+
+ // back to condition
+ c.emit(stmt, parser.OpJump, preCondPos)
+
+ // post-statement position
+ postStmtPos := len(c.currentInstructions())
+ if postCondPos >= 0 {
+ c.changeOperand(postCondPos, postStmtPos)
+ }
+
+ // update all break/continue jump positions
+ for _, pos := range loop.Breaks {
+ c.changeOperand(pos, postStmtPos)
+ }
+ for _, pos := range loop.Continues {
+ c.changeOperand(pos, postBodyPos)
+ }
+ return nil
+}
+
+func (c *Compiler) compileForInStmt(stmt *parser.ForInStmt) error {
+ c.symbolTable = c.symbolTable.Fork(true)
+ defer func() {
+ c.symbolTable = c.symbolTable.Parent(false)
+ }()
+
+ // for-in statement is compiled like following:
+ //
+ // for :it := iterator(iterable); :it.next(); {
+ // k, v := :it.get() // DEFINE operator
+ //
+ // ... body ...
+ // }
+ //
+ // ":it" is a local variable but will be conflict with other user variables
+ // because character ":" is not allowed.
+
+ // init
+ // :it = iterator(iterable)
+ itSymbol := c.symbolTable.Define(":it")
+ if err := c.Compile(stmt.Iterable); err != nil {
+ return err
+ }
+ c.emit(stmt, parser.OpIteratorInit)
+ if itSymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpSetGlobal, itSymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpDefineLocal, itSymbol.Index)
+ }
+
+ // pre-condition position
+ preCondPos := len(c.currentInstructions())
+
+ // condition
+ // :it.HasMore()
+ if itSymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
+ }
+ c.emit(stmt, parser.OpIteratorNext)
+
+ // condition jump position
+ postCondPos := c.emit(stmt, parser.OpJumpFalsy, 0)
+
+ // enter loop
+ loop := c.enterLoop()
+
+ // assign key variable
+ if stmt.Key.Name != "_" {
+ keySymbol := c.symbolTable.Define(stmt.Key.Name)
+ if itSymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
+ }
+ c.emit(stmt, parser.OpIteratorKey)
+ if keySymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpSetGlobal, keySymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpDefineLocal, keySymbol.Index)
+ }
+ }
+
+ // assign value variable
+ if stmt.Value.Name != "_" {
+ valueSymbol := c.symbolTable.Define(stmt.Value.Name)
+ if itSymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
+ }
+ c.emit(stmt, parser.OpIteratorValue)
+ if valueSymbol.Scope == ScopeGlobal {
+ c.emit(stmt, parser.OpSetGlobal, valueSymbol.Index)
+ } else {
+ c.emit(stmt, parser.OpDefineLocal, valueSymbol.Index)
+ }
+ }
+
+ // body statement
+ if err := c.Compile(stmt.Body); err != nil {
+ c.leaveLoop()
+ return err
+ }
+
+ c.leaveLoop()
+
+ // post-body position
+ postBodyPos := len(c.currentInstructions())
+
+ // back to condition
+ c.emit(stmt, parser.OpJump, preCondPos)
+
+ // post-statement position
+ postStmtPos := len(c.currentInstructions())
+ c.changeOperand(postCondPos, postStmtPos)
+
+ // update all break/continue jump positions
+ for _, pos := range loop.Breaks {
+ c.changeOperand(pos, postStmtPos)
+ }
+ for _, pos := range loop.Continues {
+ c.changeOperand(pos, postBodyPos)
+ }
+ return nil
+}
+
+func (c *Compiler) checkCyclicImports(
+ node parser.Node,
+ modulePath string,
+) error {
+ if c.modulePath == modulePath {
+ return c.errorf(node, "cyclic module import: %s", modulePath)
+ } else if c.parent != nil {
+ return c.parent.checkCyclicImports(node, modulePath)
+ }
+ return nil
+}
+
+func (c *Compiler) compileModule(
+ node parser.Node,
+ moduleName, modulePath string,
+ src []byte,
+) (*CompiledFunction, error) {
+ if err := c.checkCyclicImports(node, modulePath); err != nil {
+ return nil, err
+ }
+
+ compiledModule, exists := c.loadCompiledModule(modulePath)
+ if exists {
+ return compiledModule, nil
+ }
+
+ modFile := c.file.Set().AddFile(moduleName, -1, len(src))
+ p := parser.NewParser(modFile, src, nil)
+ file, err := p.ParseFile()
+ if err != nil {
+ return nil, err
+ }
+
+ // inherit builtin functions
+ symbolTable := NewSymbolTable()
+ for _, sym := range c.symbolTable.BuiltinSymbols() {
+ symbolTable.DefineBuiltin(sym.Index, sym.Name)
+ }
+
+ // no global scope for the module
+ symbolTable = symbolTable.Fork(false)
+
+ // compile module
+ moduleCompiler := c.fork(modFile, modulePath, symbolTable)
+ if err := moduleCompiler.Compile(file); err != nil {
+ return nil, err
+ }
+
+ // code optimization
+ moduleCompiler.optimizeFunc(node)
+ compiledFunc := moduleCompiler.Bytecode().MainFunction
+ compiledFunc.NumLocals = symbolTable.MaxSymbols()
+ c.storeCompiledModule(modulePath, compiledFunc)
+ return compiledFunc, nil
+}
+
+func (c *Compiler) loadCompiledModule(
+ modulePath string,
+) (mod *CompiledFunction, ok bool) {
+ if c.parent != nil {
+ return c.parent.loadCompiledModule(modulePath)
+ }
+ mod, ok = c.compiledModules[modulePath]
+ return
+}
+
+func (c *Compiler) storeCompiledModule(
+ modulePath string,
+ module *CompiledFunction,
+) {
+ if c.parent != nil {
+ c.parent.storeCompiledModule(modulePath, module)
+ }
+ c.compiledModules[modulePath] = module
+}
+
+func (c *Compiler) enterLoop() *loop {
+ loop := &loop{}
+ c.loops = append(c.loops, loop)
+ c.loopIndex++
+ if c.trace != nil {
+ c.printTrace("LOOPE", c.loopIndex)
+ }
+ return loop
+}
+
+func (c *Compiler) leaveLoop() {
+ if c.trace != nil {
+ c.printTrace("LOOPL", c.loopIndex)
+ }
+ c.loops = c.loops[:len(c.loops)-1]
+ c.loopIndex--
+}
+
+func (c *Compiler) currentLoop() *loop {
+ if c.loopIndex >= 0 {
+ return c.loops[c.loopIndex]
+ }
+ return nil
+}
+
+func (c *Compiler) currentInstructions() []byte {
+ return c.scopes[c.scopeIndex].Instructions
+}
+
+func (c *Compiler) currentSourceMap() map[int]parser.Pos {
+ return c.scopes[c.scopeIndex].SourceMap
+}
+
+func (c *Compiler) enterScope() {
+ scope := compilationScope{
+ SymbolInit: make(map[string]bool),
+ SourceMap: make(map[int]parser.Pos),
+ }
+ c.scopes = append(c.scopes, scope)
+ c.scopeIndex++
+ c.symbolTable = c.symbolTable.Fork(false)
+ if c.trace != nil {
+ c.printTrace("SCOPE", c.scopeIndex)
+ }
+}
+
+func (c *Compiler) leaveScope() (
+ instructions []byte,
+ sourceMap map[int]parser.Pos,
+) {
+ instructions = c.currentInstructions()
+ sourceMap = c.currentSourceMap()
+ c.scopes = c.scopes[:len(c.scopes)-1]
+ c.scopeIndex--
+ c.symbolTable = c.symbolTable.Parent(true)
+ if c.trace != nil {
+ c.printTrace("SCOPL", c.scopeIndex)
+ }
+ return
+}
+
+func (c *Compiler) fork(
+ file *parser.SourceFile,
+ modulePath string,
+ symbolTable *SymbolTable,
+) *Compiler {
+ child := NewCompiler(file, symbolTable, nil, c.modules, c.trace)
+ child.modulePath = modulePath // module file path
+ child.parent = c // parent to set to current compiler
+ return child
+}
+
+func (c *Compiler) error(node parser.Node, err error) error {
+ return &CompilerError{
+ FileSet: c.file.Set(),
+ Node: node,
+ Err: err,
+ }
+}
+
+func (c *Compiler) errorf(
+ node parser.Node,
+ format string,
+ args ...interface{},
+) error {
+ return &CompilerError{
+ FileSet: c.file.Set(),
+ Node: node,
+ Err: fmt.Errorf(format, args...),
+ }
+}
+
+func (c *Compiler) addConstant(o Object) int {
+ if c.parent != nil {
+ // module compilers will use their parent's constants array
+ return c.parent.addConstant(o)
+ }
+ c.constants = append(c.constants, o)
+ if c.trace != nil {
+ c.printTrace(fmt.Sprintf("CONST %04d %s", len(c.constants)-1, o))
+ }
+ return len(c.constants) - 1
+}
+
+func (c *Compiler) addInstruction(b []byte) int {
+ posNewIns := len(c.currentInstructions())
+ c.scopes[c.scopeIndex].Instructions = append(
+ c.currentInstructions(), b...)
+ return posNewIns
+}
+
+func (c *Compiler) replaceInstruction(pos int, inst []byte) {
+ copy(c.currentInstructions()[pos:], inst)
+ if c.trace != nil {
+ c.printTrace(fmt.Sprintf("REPLC %s",
+ FormatInstructions(
+ c.scopes[c.scopeIndex].Instructions[pos:], pos)[0]))
+ }
+}
+
+func (c *Compiler) changeOperand(opPos int, operand ...int) {
+ op := c.currentInstructions()[opPos]
+ inst := MakeInstruction(op, operand...)
+ c.replaceInstruction(opPos, inst)
+}
+
+// optimizeFunc performs some code-level optimization for the current function
+// instructions. It also removes unreachable (dead code) instructions and adds
+// "returns" instruction if needed.
+func (c *Compiler) optimizeFunc(node parser.Node) {
+ // any instructions between RETURN and the function end
+ // or instructions between RETURN and jump target position
+ // are considered as unreachable.
+
+ // pass 1. identify all jump destinations
+ dsts := make(map[int]bool)
+ iterateInstructions(c.scopes[c.scopeIndex].Instructions,
+ func(pos int, opcode parser.Opcode, operands []int) bool {
+ switch opcode {
+ case parser.OpJump, parser.OpJumpFalsy,
+ parser.OpAndJump, parser.OpOrJump:
+ dsts[operands[0]] = true
+ }
+ return true
+ })
+
+ // pass 2. eliminate dead code
+ var newInsts []byte
+ posMap := make(map[int]int) // old position to new position
+ var dstIdx int
+ var deadCode bool
+ iterateInstructions(c.scopes[c.scopeIndex].Instructions,
+ func(pos int, opcode parser.Opcode, operands []int) bool {
+ switch {
+ case opcode == parser.OpReturn:
+ if deadCode {
+ return true
+ }
+ deadCode = true
+ case dsts[pos]:
+ dstIdx++
+ deadCode = false
+ case deadCode:
+ return true
+ }
+ posMap[pos] = len(newInsts)
+ newInsts = append(newInsts,
+ MakeInstruction(opcode, operands...)...)
+ return true
+ })
+
+ // pass 3. update jump positions
+ var lastOp parser.Opcode
+ var appendReturn bool
+ endPos := len(c.scopes[c.scopeIndex].Instructions)
+ iterateInstructions(newInsts,
+ func(pos int, opcode parser.Opcode, operands []int) bool {
+ switch opcode {
+ case parser.OpJump, parser.OpJumpFalsy, parser.OpAndJump,
+ parser.OpOrJump:
+ newDst, ok := posMap[operands[0]]
+ if ok {
+ copy(newInsts[pos:],
+ MakeInstruction(opcode, newDst))
+ } else if endPos == operands[0] {
+ // there's a jump instruction that jumps to the end of
+ // function compiler should append "return".
+ appendReturn = true
+ } else {
+ panic(fmt.Errorf("invalid jump position: %d", newDst))
+ }
+ }
+ lastOp = opcode
+ return true
+ })
+ if lastOp != parser.OpReturn {
+ appendReturn = true
+ }
+
+ // pass 4. update source map
+ newSourceMap := make(map[int]parser.Pos)
+ for pos, srcPos := range c.scopes[c.scopeIndex].SourceMap {
+ newPos, ok := posMap[pos]
+ if ok {
+ newSourceMap[newPos] = srcPos
+ }
+ }
+ c.scopes[c.scopeIndex].Instructions = newInsts
+ c.scopes[c.scopeIndex].SourceMap = newSourceMap
+
+ // append "return"
+ if appendReturn {
+ c.emit(node, parser.OpReturn, 0)
+ }
+}
+
+func (c *Compiler) emit(
+ node parser.Node,
+ opcode parser.Opcode,
+ operands ...int,
+) int {
+ filePos := parser.NoPos
+ if node != nil {
+ filePos = node.Pos()
+ }
+
+ inst := MakeInstruction(opcode, operands...)
+ pos := c.addInstruction(inst)
+ c.scopes[c.scopeIndex].SourceMap[pos] = filePos
+ if c.trace != nil {
+ c.printTrace(fmt.Sprintf("EMIT %s",
+ FormatInstructions(
+ c.scopes[c.scopeIndex].Instructions[pos:], pos)[0]))
+ }
+ return pos
+}
+
+func (c *Compiler) printTrace(a ...interface{}) {
+ const (
+ dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+ n = len(dots)
+ )
+
+ i := 2 * c.indent
+ for i > n {
+ _, _ = fmt.Fprint(c.trace, dots)
+ i -= n
+ }
+ _, _ = fmt.Fprint(c.trace, dots[0:i])
+ _, _ = fmt.Fprintln(c.trace, a...)
+}
+
+func resolveAssignLHS(
+ expr parser.Expr,
+) (name string, selectors []parser.Expr) {
+ switch term := expr.(type) {
+ case *parser.SelectorExpr:
+ name, selectors = resolveAssignLHS(term.Expr)
+ selectors = append(selectors, term.Sel)
+ return
+ case *parser.IndexExpr:
+ name, selectors = resolveAssignLHS(term.Expr)
+ selectors = append(selectors, term.Index)
+ case *parser.Ident:
+ name = term.Name
+ }
+ return
+}
+
+func iterateInstructions(
+ b []byte,
+ fn func(pos int, opcode parser.Opcode, operands []int) bool,
+) {
+ for i := 0; i < len(b); i++ {
+ numOperands := parser.OpcodeOperands[b[i]]
+ operands, read := parser.ReadOperands(numOperands, b[i+1:])
+ if !fn(i, b[i], operands) {
+ break
+ }
+ i += read
+ }
+}
+
+func tracec(c *Compiler, msg string) *Compiler {
+ c.printTrace(msg, "{")
+ c.indent++
+ return c
+}
+
+func untracec(c *Compiler) {
+ c.indent--
+ c.printTrace("}")
+}
diff --git a/vendor/github.com/d5/tengo/v2/doc.go b/vendor/github.com/d5/tengo/v2/doc.go
new file mode 100644
index 00000000..05b47de1
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/doc.go
@@ -0,0 +1,3 @@
+// tengo is a small, dynamic, fast, secure script language for Go.
+
+package tengo
diff --git a/vendor/github.com/d5/tengo/v2/errors.go b/vendor/github.com/d5/tengo/v2/errors.go
new file mode 100644
index 00000000..a3fd1f3b
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/errors.go
@@ -0,0 +1,64 @@
+package tengo
+
+import (
+ "errors"
+ "fmt"
+)
+
+var (
+ // ErrStackOverflow is a stack overflow error.
+ ErrStackOverflow = errors.New("stack overflow")
+
+ // ErrObjectAllocLimit is an objects allocation limit error.
+ ErrObjectAllocLimit = errors.New("object allocation limit exceeded")
+
+ // ErrIndexOutOfBounds is an error where a given index is out of the
+ // bounds.
+ ErrIndexOutOfBounds = errors.New("index out of bounds")
+
+ // ErrInvalidIndexType represents an invalid index type.
+ ErrInvalidIndexType = errors.New("invalid index type")
+
+ // ErrInvalidIndexValueType represents an invalid index value type.
+ ErrInvalidIndexValueType = errors.New("invalid index value type")
+
+ // ErrInvalidIndexOnError represents an invalid index on error.
+ ErrInvalidIndexOnError = errors.New("invalid index on error")
+
+ // ErrInvalidOperator represents an error for invalid operator usage.
+ ErrInvalidOperator = errors.New("invalid operator")
+
+ // ErrWrongNumArguments represents a wrong number of arguments error.
+ ErrWrongNumArguments = errors.New("wrong number of arguments")
+
+ // ErrBytesLimit represents an error where the size of bytes value exceeds
+ // the limit.
+ ErrBytesLimit = errors.New("exceeding bytes size limit")
+
+ // ErrStringLimit represents an error where the size of string value
+ // exceeds the limit.
+ ErrStringLimit = errors.New("exceeding string size limit")
+
+ // ErrNotIndexable is an error where an Object is not indexable.
+ ErrNotIndexable = errors.New("not indexable")
+
+ // ErrNotIndexAssignable is an error where an Object is not index
+ // assignable.
+ ErrNotIndexAssignable = errors.New("not index-assignable")
+
+ // ErrNotImplemented is an error where an Object has not implemented a
+ // required method.
+ ErrNotImplemented = errors.New("not implemented")
+)
+
+// ErrInvalidArgumentType represents an invalid argument value type error.
+type ErrInvalidArgumentType struct {
+ Name string
+ Expected string
+ Found string
+}
+
+func (e ErrInvalidArgumentType) Error() string {
+ return fmt.Sprintf("invalid type for argument '%s': expected %s, found %s",
+ e.Name, e.Expected, e.Found)
+}
diff --git a/vendor/github.com/d5/tengo/objects/formatter.go b/vendor/github.com/d5/tengo/v2/formatter.go
index 95d7f6b1..0dbf71c6 100644
--- a/vendor/github.com/d5/tengo/objects/formatter.go
+++ b/vendor/github.com/d5/tengo/v2/formatter.go
@@ -1,15 +1,13 @@
-package objects
+package tengo
import (
"strconv"
"sync"
"unicode/utf8"
-
- "github.com/d5/tengo"
)
-// Strings for use with buffer.WriteString.
-// This is less overhead than using buffer.Write with byte arrays.
+// Strings for use with fmtbuf.WriteString. This is less overhead than using
+// fmtbuf.Write with byte arrays.
const (
commaSpaceString = ", "
nilParenString = "(nil)"
@@ -55,9 +53,9 @@ type fmtFlags struct {
}
// A formatter is the raw formatter used by Printf etc.
-// It prints into a buffer that must be set up separately.
+// It prints into a fmtbuf that must be set up separately.
type formatter struct {
- buf *buffer
+ buf *fmtbuf
fmtFlags
@@ -69,13 +67,13 @@ type formatter struct {
intbuf [68]byte
}
-func (f *formatter) clearflags() {
+func (f *formatter) clearFlags() {
f.fmtFlags = fmtFlags{}
}
-func (f *formatter) init(buf *buffer) {
+func (f *formatter) init(buf *fmtbuf) {
f.buf = buf
- f.clearflags()
+ f.clearFlags()
}
// writePadding generates n bytes of padding.
@@ -87,13 +85,13 @@ func (f *formatter) writePadding(n int) {
oldLen := len(buf)
newLen := oldLen + n
- if newLen > tengo.MaxStringLen {
+ if newLen > MaxStringLen {
panic(ErrStringLimit)
}
// Make enough room for padding.
if newLen > cap(buf) {
- buf = make(buffer, cap(buf)*2+n)
+ buf = make(fmtbuf, cap(buf)*2+n)
copy(buf, *f.buf)
}
// Decide which byte the padding should be filled with.
@@ -171,10 +169,12 @@ func (f *formatter) fmtUnicode(u uint64) {
}
}
- // Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left.
+ // Format into buf, ending at buf[i]. Formatting numbers is easier
+ // right-to-left.
i := len(buf)
- // For %#U we want to add a space and a quoted character at the end of the buffer.
+ // For %#U we want to add a space and a quoted character at the end of
+ // the fmtbuf.
if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) {
i--
buf[i] = '\''
@@ -214,7 +214,13 @@ func (f *formatter) fmtUnicode(u uint64) {
}
// fmtInteger formats signed and unsigned integers.
-func (f *formatter) fmtInteger(u uint64, base int, isSigned bool, verb rune, digits string) {
+func (f *formatter) fmtInteger(
+ u uint64,
+ base int,
+ isSigned bool,
+ verb rune,
+ digits string,
+) {
negative := isSigned && int64(u) < 0
if negative {
u = -u
@@ -253,9 +259,10 @@ func (f *formatter) fmtInteger(u uint64, base int, isSigned bool, verb rune, dig
}
}
- // Because printing is easier right-to-left: format u into buf, ending at buf[i].
- // We could make things marginally faster by splitting the 32-bit case out
- // into a separate block but it's not worth the duplication, so u has 64 bits.
+ // Because printing is easier right-to-left: format u into buf, ending at
+ // buf[i]. We could make things marginally faster by splitting the 32-bit
+ // case out into a separate block but it's not worth the duplication, so
+ // u has 64 bits.
i := len(buf)
// Use constants for the division and modulo for more efficient code.
// Switch cases ordered by popularity.
@@ -357,7 +364,8 @@ func (f *formatter) truncateString(s string) string {
return s
}
-// truncate truncates the byte slice b as a string of the specified precision, if present.
+// truncate truncates the byte slice b as a string of the specified precision,
+// if present.
func (f *formatter) truncate(b []byte) []byte {
if f.precPresent {
n := f.prec
@@ -399,11 +407,13 @@ func (f *formatter) fmtSbx(s string, b []byte, digits string) {
if f.precPresent && f.prec < length {
length = f.prec
}
- // Compute width of the encoding taking into account the f.sharp and f.space flag.
+ // Compute width of the encoding taking into account the f.sharp and
+ // f.space flag.
width := 2 * length
if width > 0 {
if f.space {
- // Each element encoded by two hexadecimals will get a leading 0x or 0X.
+ // Each element encoded by two hexadecimals will get a leading
+ // 0x or 0X.
if f.sharp {
width *= 2
}
@@ -423,7 +433,7 @@ func (f *formatter) fmtSbx(s string, b []byte, digits string) {
if f.widPresent && f.wid > width && !f.minus {
f.writePadding(f.wid - width)
}
- // Write the encoding directly into the output buffer.
+ // Write the encoding directly into the output fmtbuf.
buf := *f.buf
if f.sharp {
// Add leading 0x or 0X.
@@ -589,8 +599,9 @@ func (f *formatter) fmtFloat(v float64, size int, verb rune, prec int) {
}
// We want a sign if asked for and if the sign is not positive.
if f.plus || num[0] != '+' {
- // If we're zero padding to the left we want the sign before the leading zeros.
- // Achieve this by writing the sign out and then padding the unsigned number.
+ // If we're zero padding to the left we want the sign before the
+ // leading zeros. Achieve this by writing the sign out and then padding
+ // the unsigned number.
if f.zero && f.widPresent && f.wid > len(num) {
f.buf.WriteSingleByte(num[0])
f.writePadding(f.wid - len(num))
@@ -600,39 +611,40 @@ func (f *formatter) fmtFloat(v float64, size int, verb rune, prec int) {
f.pad(num)
return
}
- // No sign to show and the number is positive; just print the unsigned number.
+ // No sign to show and the number is positive; just print the unsigned
+ // number.
f.pad(num[1:])
}
// Use simple []byte instead of bytes.Buffer to avoid large dependency.
-type buffer []byte
+type fmtbuf []byte
-func (b *buffer) Write(p []byte) {
- if len(*b)+len(p) > tengo.MaxStringLen {
+func (b *fmtbuf) Write(p []byte) {
+ if len(*b)+len(p) > MaxStringLen {
panic(ErrStringLimit)
}
*b = append(*b, p...)
}
-func (b *buffer) WriteString(s string) {
- if len(*b)+len(s) > tengo.MaxStringLen {
+func (b *fmtbuf) WriteString(s string) {
+ if len(*b)+len(s) > MaxStringLen {
panic(ErrStringLimit)
}
*b = append(*b, s...)
}
-func (b *buffer) WriteSingleByte(c byte) {
- if len(*b) >= tengo.MaxStringLen {
+func (b *fmtbuf) WriteSingleByte(c byte) {
+ if len(*b) >= MaxStringLen {
panic(ErrStringLimit)
}
*b = append(*b, c)
}
-func (b *buffer) WriteRune(r rune) {
- if len(*b)+utf8.RuneLen(r) > tengo.MaxStringLen {
+func (b *fmtbuf) WriteRune(r rune) {
+ if len(*b)+utf8.RuneLen(r) > MaxStringLen {
panic(ErrStringLimit)
}
@@ -650,9 +662,10 @@ func (b *buffer) WriteRune(r rune) {
*b = b2[:n+w]
}
-// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations.
+// pp is used to store a printer's state and is reused with sync.Pool to avoid
+// allocations.
type pp struct {
- buf buffer
+ buf fmtbuf
// arg holds the current item.
arg Object
@@ -663,10 +676,12 @@ type pp struct {
// reordered records whether the format string used argument reordering.
reordered bool
- // goodArgNum records whether the most recent reordering directive was valid.
+ // goodArgNum records whether the most recent reordering directive was
+ // valid.
goodArgNum bool
- // erroring is set when printing an error string to guard against calling handleMethods.
+ // erroring is set when printing an error string to guard against calling
+ // handleMethods.
erroring bool
}
@@ -686,8 +701,8 @@ func newPrinter() *pp {
func (p *pp) free() {
// Proper usage of a sync.Pool requires each entry to have approximately
// the same memory cost. To obtain this property when the stored type
- // contains a variably-sized buffer, we add a hard limit on the maximum buffer
- // to place back in the pool.
+ // contains a variably-sized fmtbuf, we add a hard limit on the maximum
+ // fmtbuf to place back in the pool.
//
// See https://golang.org/issue/23199
if cap(p.buf) > 64<<10 {
@@ -699,9 +714,13 @@ func (p *pp) free() {
ppFree.Put(p)
}
-func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
+func (p *pp) Width() (wid int, ok bool) {
+ return p.fmt.wid, p.fmt.widPresent
+}
-func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent }
+func (p *pp) Precision() (prec int, ok bool) {
+ return p.fmt.prec, p.fmt.precPresent
+}
func (p *pp) Flag(b int) bool {
switch b {
@@ -750,7 +769,8 @@ func tooLarge(x int) bool {
return x > max || x < -max
}
-// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
+// parsenum converts ASCII to integer. num is 0 (and isnum is false) if no
+// number present.
func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
if start >= end {
return 0, false, end
@@ -918,7 +938,8 @@ func (p *pp) printArg(arg Object, verb rune) {
}
// Special processing considerations.
- // %T (the value's type) and %p (its address) are special; we always do them first.
+ // %T (the value's type) and %p (its address) are special; we always do
+ // them first.
switch verb {
case 'T':
p.fmt.fmtS(arg.TypeName())
@@ -945,7 +966,8 @@ func (p *pp) printArg(arg Object, verb rune) {
}
}
-// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has integer type.
+// intFromArg gets the argNumth element of a. On return, isInt reports whether
+// the argument has integer type.
func intFromArg(a []Object, argNum int) (num int, isInt bool, newArgNum int) {
newArgNum = argNum
if argNum < len(a) {
@@ -980,16 +1002,23 @@ func parseArgNumber(format string) (index int, wid int, ok bool) {
if !ok || newi != i {
return 0, i + 1, false
}
- return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
+ // arg numbers are one-indexed andskip paren.
+ return width - 1, i + 1, true
}
}
return 0, 1, false
}
-// argNumber returns the next argument to evaluate, which is either the value of the passed-in
-// argNum or the value of the bracketed integer that begins format[i:]. It also returns
-// the new value of i, that is, the index of the next byte of the format to process.
-func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
+// argNumber returns the next argument to evaluate, which is either the value
+// of the passed-in argNum or the value of the bracketed integer that begins
+// format[i:]. It also returns the new value of i, that is, the index of the
+// next byte of the format to process.
+func (p *pp) argNumber(
+ argNum int,
+ format string,
+ i int,
+ numArgs int,
+) (newArgNum, newi int, found bool) {
if len(format) <= i || format[i] != '[' {
return argNum, i, false
}
@@ -1048,7 +1077,7 @@ formatLoop:
i++
// Do we have flags?
- p.fmt.clearflags()
+ p.fmt.clearFlags()
simpleFormat:
for ; i < end; i++ {
c := format[i]
@@ -1056,7 +1085,8 @@ formatLoop:
case '#':
p.fmt.sharp = true
case '0':
- p.fmt.zero = !p.fmt.minus // Only allow zero padding to the left.
+ // Only allow zero padding to the left.
+ p.fmt.zero = !p.fmt.minus
case '+':
p.fmt.plus = true
case '-':
@@ -1081,7 +1111,8 @@ formatLoop:
i++
continue formatLoop
}
- // Format is more complex than simple flags and a verb or is malformed.
+ // Format is more complex than simple flags and a verb or is
+ // malformed.
break simpleFormat
}
}
@@ -1157,11 +1188,13 @@ formatLoop:
i += size
switch {
- case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
+ case verb == '%':
+ // Percent does not absorb operands and ignores f.wid and f.prec.
_, _ = p.WriteSingleByte('%')
case !p.goodArgNum:
p.badArgNum(verb)
- case argNum >= len(a): // No argument left over to print for the current verb.
+ case argNum >= len(a):
+ // No argument left over to print for the current verb.
p.missingArg(verb)
case verb == 'v':
// Go syntax
@@ -1181,7 +1214,7 @@ formatLoop:
// out of order, in which case it's too expensive to detect if they've all
// been used and arguably OK if they're not.
if !p.reordered && argNum < len(a) {
- p.fmt.clearflags()
+ p.fmt.clearFlags()
_, _ = p.WriteString(extraString)
for i, arg := range a[argNum:] {
if i > 0 {
@@ -1201,7 +1234,7 @@ formatLoop:
return nil
}
-// Format formats according to a format specifier and returns the resulting string.
+// Format is like fmt.Sprintf but using Objects.
func Format(format string, a ...Object) (string, error) {
p := newPrinter()
err := p.doFormat(format, a)
diff --git a/vendor/github.com/d5/tengo/v2/go.mod b/vendor/github.com/d5/tengo/v2/go.mod
new file mode 100644
index 00000000..732ff142
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/go.mod
@@ -0,0 +1,3 @@
+module github.com/d5/tengo/v2
+
+go 1.13
diff --git a/vendor/github.com/d5/tengo/go.sum b/vendor/github.com/d5/tengo/v2/go.sum
index e69de29b..e69de29b 100644
--- a/vendor/github.com/d5/tengo/go.sum
+++ b/vendor/github.com/d5/tengo/v2/go.sum
diff --git a/vendor/github.com/d5/tengo/v2/instructions.go b/vendor/github.com/d5/tengo/v2/instructions.go
new file mode 100644
index 00000000..eb1fbf27
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/instructions.go
@@ -0,0 +1,61 @@
+package tengo
+
+import (
+ "fmt"
+
+ "github.com/d5/tengo/v2/parser"
+)
+
+// MakeInstruction returns a bytecode for an opcode and the operands.
+func MakeInstruction(opcode parser.Opcode, operands ...int) []byte {
+ numOperands := parser.OpcodeOperands[opcode]
+
+ totalLen := 1
+ for _, w := range numOperands {
+ totalLen += w
+ }
+
+ instruction := make([]byte, totalLen)
+ instruction[0] = opcode
+
+ offset := 1
+ for i, o := range operands {
+ width := numOperands[i]
+ switch width {
+ case 1:
+ instruction[offset] = byte(o)
+ case 2:
+ n := uint16(o)
+ instruction[offset] = byte(n >> 8)
+ instruction[offset+1] = byte(n)
+ }
+ offset += width
+ }
+ return instruction
+}
+
+// FormatInstructions returns string representation of bytecode instructions.
+func FormatInstructions(b []byte, posOffset int) []string {
+ var out []string
+
+ i := 0
+ for i < len(b) {
+ numOperands := parser.OpcodeOperands[b[i]]
+ operands, read := parser.ReadOperands(numOperands, b[i+1:])
+
+ switch len(numOperands) {
+ case 0:
+ out = append(out, fmt.Sprintf("%04d %-7s",
+ posOffset+i, parser.OpcodeNames[b[i]]))
+ case 1:
+ out = append(out, fmt.Sprintf("%04d %-7s %-5d",
+ posOffset+i, parser.OpcodeNames[b[i]], operands[0]))
+ case 2:
+ out = append(out, fmt.Sprintf("%04d %-7s %-5d %-5d",
+ posOffset+i, parser.OpcodeNames[b[i]],
+ operands[0], operands[1]))
+ }
+ i += 1 + read
+ }
+ return out
+}
diff --git a/vendor/github.com/d5/tengo/v2/iterator.go b/vendor/github.com/d5/tengo/v2/iterator.go
new file mode 100644
index 00000000..13adbbab
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/iterator.go
@@ -0,0 +1,209 @@
+package tengo
+
+// Iterator represents an iterator for underlying data type.
+type Iterator interface {
+ Object
+
+ // Next returns true if there are more elements to iterate.
+ Next() bool
+
+ // Key returns the key or index value of the current element.
+ Key() Object
+
+ // Value returns the value of the current element.
+ Value() Object
+}
+
+// ArrayIterator is an iterator for an array.
+type ArrayIterator struct {
+ ObjectImpl
+ v []Object
+ i int
+ l int
+}
+
+// TypeName returns the name of the type.
+func (i *ArrayIterator) TypeName() string {
+ return "array-iterator"
+}
+
+func (i *ArrayIterator) String() string {
+ return "<array-iterator>"
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (i *ArrayIterator) IsFalsy() bool {
+ return true
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (i *ArrayIterator) Equals(Object) bool {
+ return false
+}
+
+// Copy returns a copy of the type.
+func (i *ArrayIterator) Copy() Object {
+ return &ArrayIterator{v: i.v, i: i.i, l: i.l}
+}
+
+// Next returns true if there are more elements to iterate.
+func (i *ArrayIterator) Next() bool {
+ i.i++
+ return i.i <= i.l
+}
+
+// Key returns the key or index value of the current element.
+func (i *ArrayIterator) Key() Object {
+ return &Int{Value: int64(i.i - 1)}
+}
+
+// Value returns the value of the current element.
+func (i *ArrayIterator) Value() Object {
+ return i.v[i.i-1]
+}
+
+// BytesIterator represents an iterator for a string.
+type BytesIterator struct {
+ ObjectImpl
+ v []byte
+ i int
+ l int
+}
+
+// TypeName returns the name of the type.
+func (i *BytesIterator) TypeName() string {
+ return "bytes-iterator"
+}
+
+func (i *BytesIterator) String() string {
+ return "<bytes-iterator>"
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (i *BytesIterator) Equals(Object) bool {
+ return false
+}
+
+// Copy returns a copy of the type.
+func (i *BytesIterator) Copy() Object {
+ return &BytesIterator{v: i.v, i: i.i, l: i.l}
+}
+
+// Next returns true if there are more elements to iterate.
+func (i *BytesIterator) Next() bool {
+ i.i++
+ return i.i <= i.l
+}
+
+// Key returns the key or index value of the current element.
+func (i *BytesIterator) Key() Object {
+ return &Int{Value: int64(i.i - 1)}
+}
+
+// Value returns the value of the current element.
+func (i *BytesIterator) Value() Object {
+ return &Int{Value: int64(i.v[i.i-1])}
+}
+
+// MapIterator represents an iterator for the map.
+type MapIterator struct {
+ ObjectImpl
+ v map[string]Object
+ k []string
+ i int
+ l int
+}
+
+// TypeName returns the name of the type.
+func (i *MapIterator) TypeName() string {
+ return "map-iterator"
+}
+
+func (i *MapIterator) String() string {
+ return "<map-iterator>"
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (i *MapIterator) IsFalsy() bool {
+ return true
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (i *MapIterator) Equals(Object) bool {
+ return false
+}
+
+// Copy returns a copy of the type.
+func (i *MapIterator) Copy() Object {
+ return &MapIterator{v: i.v, k: i.k, i: i.i, l: i.l}
+}
+
+// Next returns true if there are more elements to iterate.
+func (i *MapIterator) Next() bool {
+ i.i++
+ return i.i <= i.l
+}
+
+// Key returns the key or index value of the current element.
+func (i *MapIterator) Key() Object {
+ k := i.k[i.i-1]
+ return &String{Value: k}
+}
+
+// Value returns the value of the current element.
+func (i *MapIterator) Value() Object {
+ k := i.k[i.i-1]
+ return i.v[k]
+}
+
+// StringIterator represents an iterator for a string.
+type StringIterator struct {
+ ObjectImpl
+ v []rune
+ i int
+ l int
+}
+
+// TypeName returns the name of the type.
+func (i *StringIterator) TypeName() string {
+ return "string-iterator"
+}
+
+func (i *StringIterator) String() string {
+ return "<string-iterator>"
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (i *StringIterator) IsFalsy() bool {
+ return true
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (i *StringIterator) Equals(Object) bool {
+ return false
+}
+
+// Copy returns a copy of the type.
+func (i *StringIterator) Copy() Object {
+ return &StringIterator{v: i.v, i: i.i, l: i.l}
+}
+
+// Next returns true if there are more elements to iterate.
+func (i *StringIterator) Next() bool {
+ i.i++
+ return i.i <= i.l
+}
+
+// Key returns the key or index value of the current element.
+func (i *StringIterator) Key() Object {
+ return &Int{Value: int64(i.i - 1)}
+}
+
+// Value returns the value of the current element.
+func (i *StringIterator) Value() Object {
+ return &Char{Value: i.v[i.i-1]}
+}
diff --git a/vendor/github.com/d5/tengo/objects/module_map.go b/vendor/github.com/d5/tengo/v2/modules.go
index 874b8a2b..c8fcde7f 100644
--- a/vendor/github.com/d5/tengo/objects/module_map.go
+++ b/vendor/github.com/d5/tengo/v2/modules.go
@@ -1,7 +1,13 @@
-package objects
+package tengo
-// ModuleMap represents a set of named modules.
-// Use NewModuleMap to create a new module map.
+// Importable interface represents importable module instance.
+type Importable interface {
+ // Import should return either an Object or module source code ([]byte).
+ Import(moduleName string) (interface{}, error)
+}
+
+// ModuleMap represents a set of named modules. Use NewModuleMap to create a
+// new module map.
type ModuleMap struct {
m map[string]Importable
}
@@ -33,21 +39,21 @@ func (m *ModuleMap) Remove(name string) {
delete(m.m, name)
}
-// Get returns an import module identified by name.
-// It returns if the name is not found.
+// Get returns an import module identified by name. It returns if the name is
+// not found.
func (m *ModuleMap) Get(name string) Importable {
return m.m[name]
}
-// GetBuiltinModule returns a builtin module identified by name.
-// It returns if the name is not found or the module is not a builtin module.
+// GetBuiltinModule returns a builtin module identified by name. It returns
+// if the name is not found or the module is not a builtin module.
func (m *ModuleMap) GetBuiltinModule(name string) *BuiltinModule {
mod, _ := m.m[name].(*BuiltinModule)
return mod
}
-// GetSourceModule returns a source module identified by name.
-// It returns if the name is not found or the module is not a source module.
+// GetSourceModule returns a source module identified by name. It returns if
+// the name is not found or the module is not a source module.
func (m *ModuleMap) GetSourceModule(name string) *SourceModule {
mod, _ := m.m[name].(*SourceModule)
return mod
@@ -75,3 +81,13 @@ func (m *ModuleMap) AddMap(o *ModuleMap) {
m.m[name] = mod
}
}
+
+// SourceModule is an importable module that's written in Tengo.
+type SourceModule struct {
+ Src []byte
+}
+
+// Import returns a module source code.
+func (m *SourceModule) Import(_ string) (interface{}, error) {
+ return m.Src, nil
+}
diff --git a/vendor/github.com/d5/tengo/v2/objects.go b/vendor/github.com/d5/tengo/v2/objects.go
new file mode 100644
index 00000000..27c1d493
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/objects.go
@@ -0,0 +1,1581 @@
+package tengo
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/d5/tengo/v2/parser"
+ "github.com/d5/tengo/v2/token"
+)
+
+var (
+ // TrueValue represents a true value.
+ TrueValue Object = &Bool{value: true}
+
+ // FalseValue represents a false value.
+ FalseValue Object = &Bool{value: false}
+
+ // UndefinedValue represents an undefined value.
+ UndefinedValue Object = &Undefined{}
+)
+
+// Object represents an object in the VM.
+type Object interface {
+ // TypeName should return the name of the type.
+ TypeName() string
+
+ // String should return a string representation of the type's value.
+ String() string
+
+ // BinaryOp should return another object that is the result of a given
+ // binary operator and a right-hand side object. If BinaryOp returns an
+ // error, the VM will treat it as a run-time error.
+ BinaryOp(op token.Token, rhs Object) (Object, error)
+
+ // IsFalsy should return true if the value of the type should be considered
+ // as falsy.
+ IsFalsy() bool
+
+ // Equals should return true if the value of the type should be considered
+ // as equal to the value of another object.
+ Equals(another Object) bool
+
+ // Copy should return a copy of the type (and its value). Copy function
+ // will be used for copy() builtin function which is expected to deep-copy
+ // the values generally.
+ Copy() Object
+
+ // IndexGet should take an index Object and return a result Object or an
+ // error for indexable objects. Indexable is an object that can take an
+ // index and return an object. If error is returned, the runtime will treat
+ // it as a run-time error and ignore returned value. If Object is not
+ // indexable, ErrNotIndexable should be returned as error. If nil is
+ // returned as value, it will be converted to UndefinedToken value by the
+ // runtime.
+ IndexGet(index Object) (value Object, err error)
+
+ // IndexSet should take an index Object and a value Object for index
+ // assignable objects. Index assignable is an object that can take an index
+ // and a value on the left-hand side of the assignment statement. If Object
+ // is not index assignable, ErrNotIndexAssignable should be returned as
+ // error. If an error is returned, it will be treated as a run-time error.
+ IndexSet(index, value Object) error
+
+ // Iterate should return an Iterator for the type.
+ Iterate() Iterator
+
+ // CanIterate should return whether the Object can be Iterated.
+ CanIterate() bool
+
+ // Call should take an arbitrary number of arguments and returns a return
+ // value and/or an error, which the VM will consider as a run-time error.
+ Call(args ...Object) (ret Object, err error)
+
+ // CanCall should return whether the Object can be Called.
+ CanCall() bool
+}
+
+// ObjectImpl represents a default Object Implementation. To defined a new
+// value type, one can embed ObjectImpl in their type declarations to avoid
+// implementing all non-significant methods. TypeName() and String() methods
+// still need to be implemented.
+type ObjectImpl struct {
+}
+
+// TypeName returns the name of the type.
+func (o *ObjectImpl) TypeName() string {
+ panic(ErrNotImplemented)
+}
+
+func (o *ObjectImpl) String() string {
+ panic(ErrNotImplemented)
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *ObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *ObjectImpl) Copy() Object {
+ return nil
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *ObjectImpl) IsFalsy() bool {
+ return false
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *ObjectImpl) Equals(x Object) bool {
+ return o == x
+}
+
+// IndexGet returns an element at a given index.
+func (o *ObjectImpl) IndexGet(_ Object) (res Object, err error) {
+ return nil, ErrNotIndexable
+}
+
+// IndexSet sets an element at a given index.
+func (o *ObjectImpl) IndexSet(_, _ Object) (err error) {
+ return ErrNotIndexAssignable
+}
+
+// Iterate returns an iterator.
+func (o *ObjectImpl) Iterate() Iterator {
+ return nil
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *ObjectImpl) CanIterate() bool {
+ return false
+}
+
+// Call takes an arbitrary number of arguments and returns a return value
+// and/or an error.
+func (o *ObjectImpl) Call(_ ...Object) (ret Object, err error) {
+ return nil, nil
+}
+
+// CanCall returns whether the Object can be Called.
+func (o *ObjectImpl) CanCall() bool {
+ return false
+}
+
+// Array represents an array of objects.
+type Array struct {
+ ObjectImpl
+ Value []Object
+}
+
+// TypeName returns the name of the type.
+func (o *Array) TypeName() string {
+ return "array"
+}
+
+func (o *Array) String() string {
+ var elements []string
+ for _, e := range o.Value {
+ elements = append(elements, e.String())
+ }
+ return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Array) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ if rhs, ok := rhs.(*Array); ok {
+ switch op {
+ case token.Add:
+ if len(rhs.Value) == 0 {
+ return o, nil
+ }
+ return &Array{Value: append(o.Value, rhs.Value...)}, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Array) Copy() Object {
+ var c []Object
+ for _, elem := range o.Value {
+ c = append(c, elem.Copy())
+ }
+ return &Array{Value: c}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Array) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Array) Equals(x Object) bool {
+ var xVal []Object
+ switch x := x.(type) {
+ case *Array:
+ xVal = x.Value
+ case *ImmutableArray:
+ xVal = x.Value
+ default:
+ return false
+ }
+ if len(o.Value) != len(xVal) {
+ return false
+ }
+ for i, e := range o.Value {
+ if !e.Equals(xVal[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// IndexGet returns an element at a given index.
+func (o *Array) IndexGet(index Object) (res Object, err error) {
+ intIdx, ok := index.(*Int)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ idxVal := int(intIdx.Value)
+ if idxVal < 0 || idxVal >= len(o.Value) {
+ res = UndefinedValue
+ return
+ }
+ res = o.Value[idxVal]
+ return
+}
+
+// IndexSet sets an element at a given index.
+func (o *Array) IndexSet(index, value Object) (err error) {
+ intIdx, ok := ToInt(index)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ if intIdx < 0 || intIdx >= len(o.Value) {
+ err = ErrIndexOutOfBounds
+ return
+ }
+ o.Value[intIdx] = value
+ return nil
+}
+
+// Iterate creates an array iterator.
+func (o *Array) Iterate() Iterator {
+ return &ArrayIterator{
+ v: o.Value,
+ l: len(o.Value),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *Array) CanIterate() bool {
+ return true
+}
+
+// Bool represents a boolean value.
+type Bool struct {
+ ObjectImpl
+
+ // this is intentionally non-public to force using objects.TrueValue and
+ // FalseValue always
+ value bool
+}
+
+func (o *Bool) String() string {
+ if o.value {
+ return "true"
+ }
+
+ return "false"
+}
+
+// TypeName returns the name of the type.
+func (o *Bool) TypeName() string {
+ return "bool"
+}
+
+// Copy returns a copy of the type.
+func (o *Bool) Copy() Object {
+ return o
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Bool) IsFalsy() bool {
+ return !o.value
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Bool) Equals(x Object) bool {
+ return o == x
+}
+
+// GobDecode decodes bool value from input bytes.
+func (o *Bool) GobDecode(b []byte) (err error) {
+ o.value = b[0] == 1
+ return
+}
+
+// GobEncode encodes bool values into bytes.
+func (o *Bool) GobEncode() (b []byte, err error) {
+ if o.value {
+ b = []byte{1}
+ } else {
+ b = []byte{0}
+ }
+ return
+}
+
+// BuiltinFunction represents a builtin function.
+type BuiltinFunction struct {
+ ObjectImpl
+ Name string
+ Value CallableFunc
+}
+
+// TypeName returns the name of the type.
+func (o *BuiltinFunction) TypeName() string {
+ return "builtin-function:" + o.Name
+}
+
+func (o *BuiltinFunction) String() string {
+ return "<builtin-function>"
+}
+
+// Copy returns a copy of the type.
+func (o *BuiltinFunction) Copy() Object {
+ return &BuiltinFunction{Value: o.Value}
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *BuiltinFunction) Equals(_ Object) bool {
+ return false
+}
+
+// Call executes a builtin function.
+func (o *BuiltinFunction) Call(args ...Object) (Object, error) {
+ return o.Value(args...)
+}
+
+// CanCall returns whether the Object can be Called.
+func (o *BuiltinFunction) CanCall() bool {
+ return true
+}
+
+// BuiltinModule is an importable module that's written in Go.
+type BuiltinModule struct {
+ Attrs map[string]Object
+}
+
+// Import returns an immutable map for the module.
+func (m *BuiltinModule) Import(moduleName string) (interface{}, error) {
+ return m.AsImmutableMap(moduleName), nil
+}
+
+// AsImmutableMap converts builtin module into an immutable map.
+func (m *BuiltinModule) AsImmutableMap(moduleName string) *ImmutableMap {
+ attrs := make(map[string]Object, len(m.Attrs))
+ for k, v := range m.Attrs {
+ attrs[k] = v.Copy()
+ }
+ attrs["__module_name__"] = &String{Value: moduleName}
+ return &ImmutableMap{Value: attrs}
+}
+
+// Bytes represents a byte array.
+type Bytes struct {
+ ObjectImpl
+ Value []byte
+}
+
+func (o *Bytes) String() string {
+ return string(o.Value)
+}
+
+// TypeName returns the name of the type.
+func (o *Bytes) TypeName() string {
+ return "bytes"
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Bytes) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch op {
+ case token.Add:
+ switch rhs := rhs.(type) {
+ case *Bytes:
+ if len(o.Value)+len(rhs.Value) > MaxBytesLen {
+ return nil, ErrBytesLimit
+ }
+ return &Bytes{Value: append(o.Value, rhs.Value...)}, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Bytes) Copy() Object {
+ return &Bytes{Value: append([]byte{}, o.Value...)}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Bytes) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Bytes) Equals(x Object) bool {
+ t, ok := x.(*Bytes)
+ if !ok {
+ return false
+ }
+ return bytes.Equal(o.Value, t.Value)
+}
+
+// IndexGet returns an element (as Int) at a given index.
+func (o *Bytes) IndexGet(index Object) (res Object, err error) {
+ intIdx, ok := index.(*Int)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ idxVal := int(intIdx.Value)
+ if idxVal < 0 || idxVal >= len(o.Value) {
+ res = UndefinedValue
+ return
+ }
+ res = &Int{Value: int64(o.Value[idxVal])}
+ return
+}
+
+// Iterate creates a bytes iterator.
+func (o *Bytes) Iterate() Iterator {
+ return &BytesIterator{
+ v: o.Value,
+ l: len(o.Value),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *Bytes) CanIterate() bool {
+ return true
+}
+
+// Char represents a character value.
+type Char struct {
+ ObjectImpl
+ Value rune
+}
+
+func (o *Char) String() string {
+ return string(o.Value)
+}
+
+// TypeName returns the name of the type.
+func (o *Char) TypeName() string {
+ return "char"
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch rhs := rhs.(type) {
+ case *Char:
+ switch op {
+ case token.Add:
+ r := o.Value + rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Char{Value: r}, nil
+ case token.Sub:
+ r := o.Value - rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Char{Value: r}, nil
+ case token.Less:
+ if o.Value < rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value > rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value <= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value >= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ case *Int:
+ switch op {
+ case token.Add:
+ r := o.Value + rune(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Char{Value: r}, nil
+ case token.Sub:
+ r := o.Value - rune(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Char{Value: r}, nil
+ case token.Less:
+ if int64(o.Value) < rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if int64(o.Value) > rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if int64(o.Value) <= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if int64(o.Value) >= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Char) Copy() Object {
+ return &Char{Value: o.Value}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Char) IsFalsy() bool {
+ return o.Value == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Char) Equals(x Object) bool {
+ t, ok := x.(*Char)
+ if !ok {
+ return false
+ }
+ return o.Value == t.Value
+}
+
+// CompiledFunction represents a compiled function.
+type CompiledFunction struct {
+ ObjectImpl
+ Instructions []byte
+ NumLocals int // number of local variables (including function parameters)
+ NumParameters int
+ VarArgs bool
+ SourceMap map[int]parser.Pos
+ Free []*ObjectPtr
+}
+
+// TypeName returns the name of the type.
+func (o *CompiledFunction) TypeName() string {
+ return "compiled-function"
+}
+
+func (o *CompiledFunction) String() string {
+ return "<compiled-function>"
+}
+
+// Copy returns a copy of the type.
+func (o *CompiledFunction) Copy() Object {
+ return &CompiledFunction{
+ Instructions: append([]byte{}, o.Instructions...),
+ NumLocals: o.NumLocals,
+ NumParameters: o.NumParameters,
+ VarArgs: o.VarArgs,
+ Free: append([]*ObjectPtr{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
+ }
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *CompiledFunction) Equals(_ Object) bool {
+ return false
+}
+
+// SourcePos returns the source position of the instruction at ip.
+func (o *CompiledFunction) SourcePos(ip int) parser.Pos {
+ for ip >= 0 {
+ if p, ok := o.SourceMap[ip]; ok {
+ return p
+ }
+ ip--
+ }
+ return parser.NoPos
+}
+
+// CanCall returns whether the Object can be Called.
+func (o *CompiledFunction) CanCall() bool {
+ return true
+}
+
+// Error represents an error value.
+type Error struct {
+ ObjectImpl
+ Value Object
+}
+
+// TypeName returns the name of the type.
+func (o *Error) TypeName() string {
+ return "error"
+}
+
+func (o *Error) String() string {
+ if o.Value != nil {
+ return fmt.Sprintf("error: %s", o.Value.String())
+ }
+ return "error"
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Error) IsFalsy() bool {
+ return true // error is always false.
+}
+
+// Copy returns a copy of the type.
+func (o *Error) Copy() Object {
+ return &Error{Value: o.Value.Copy()}
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Error) Equals(x Object) bool {
+ return o == x // pointer equality
+}
+
+// IndexGet returns an element at a given index.
+func (o *Error) IndexGet(index Object) (res Object, err error) {
+ if strIdx, _ := ToString(index); strIdx != "value" {
+ err = ErrInvalidIndexOnError
+ return
+ }
+ res = o.Value
+ return
+}
+
+// Float represents a floating point number value.
+type Float struct {
+ ObjectImpl
+ Value float64
+}
+
+func (o *Float) String() string {
+ return strconv.FormatFloat(o.Value, 'f', -1, 64)
+}
+
+// TypeName returns the name of the type.
+func (o *Float) TypeName() string {
+ return "float"
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Float) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch rhs := rhs.(type) {
+ case *Float:
+ switch op {
+ case token.Add:
+ r := o.Value + rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Sub:
+ r := o.Value - rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Mul:
+ r := o.Value * rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Quo:
+ r := o.Value / rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Less:
+ if o.Value < rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value > rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value <= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value >= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ case *Int:
+ switch op {
+ case token.Add:
+ r := o.Value + float64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Sub:
+ r := o.Value - float64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Mul:
+ r := o.Value * float64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Quo:
+ r := o.Value / float64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Float{Value: r}, nil
+ case token.Less:
+ if o.Value < float64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value > float64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value <= float64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value >= float64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Float) Copy() Object {
+ return &Float{Value: o.Value}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Float) IsFalsy() bool {
+ return math.IsNaN(o.Value)
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Float) Equals(x Object) bool {
+ t, ok := x.(*Float)
+ if !ok {
+ return false
+ }
+ return o.Value == t.Value
+}
+
+// ImmutableArray represents an immutable array of objects.
+type ImmutableArray struct {
+ ObjectImpl
+ Value []Object
+}
+
+// TypeName returns the name of the type.
+func (o *ImmutableArray) TypeName() string {
+ return "immutable-array"
+}
+
+func (o *ImmutableArray) String() string {
+ var elements []string
+ for _, e := range o.Value {
+ elements = append(elements, e.String())
+ }
+ return fmt.Sprintf("[%s]", strings.Join(elements, ", "))
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *ImmutableArray) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ if rhs, ok := rhs.(*ImmutableArray); ok {
+ switch op {
+ case token.Add:
+ return &Array{Value: append(o.Value, rhs.Value...)}, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *ImmutableArray) Copy() Object {
+ var c []Object
+ for _, elem := range o.Value {
+ c = append(c, elem.Copy())
+ }
+ return &Array{Value: c}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *ImmutableArray) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *ImmutableArray) Equals(x Object) bool {
+ var xVal []Object
+ switch x := x.(type) {
+ case *Array:
+ xVal = x.Value
+ case *ImmutableArray:
+ xVal = x.Value
+ default:
+ return false
+ }
+ if len(o.Value) != len(xVal) {
+ return false
+ }
+ for i, e := range o.Value {
+ if !e.Equals(xVal[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// IndexGet returns an element at a given index.
+func (o *ImmutableArray) IndexGet(index Object) (res Object, err error) {
+ intIdx, ok := index.(*Int)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ idxVal := int(intIdx.Value)
+ if idxVal < 0 || idxVal >= len(o.Value) {
+ res = UndefinedValue
+ return
+ }
+ res = o.Value[idxVal]
+ return
+}
+
+// Iterate creates an array iterator.
+func (o *ImmutableArray) Iterate() Iterator {
+ return &ArrayIterator{
+ v: o.Value,
+ l: len(o.Value),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *ImmutableArray) CanIterate() bool {
+ return true
+}
+
+// ImmutableMap represents an immutable map object.
+type ImmutableMap struct {
+ ObjectImpl
+ Value map[string]Object
+}
+
+// TypeName returns the name of the type.
+func (o *ImmutableMap) TypeName() string {
+ return "immutable-map"
+}
+
+func (o *ImmutableMap) String() string {
+ var pairs []string
+ for k, v := range o.Value {
+ pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
+ }
+ return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
+}
+
+// Copy returns a copy of the type.
+func (o *ImmutableMap) Copy() Object {
+ c := make(map[string]Object)
+ for k, v := range o.Value {
+ c[k] = v.Copy()
+ }
+ return &Map{Value: c}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *ImmutableMap) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// IndexGet returns the value for the given key.
+func (o *ImmutableMap) IndexGet(index Object) (res Object, err error) {
+ strIdx, ok := ToString(index)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ res, ok = o.Value[strIdx]
+ if !ok {
+ res = UndefinedValue
+ }
+ return
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *ImmutableMap) Equals(x Object) bool {
+ var xVal map[string]Object
+ switch x := x.(type) {
+ case *Map:
+ xVal = x.Value
+ case *ImmutableMap:
+ xVal = x.Value
+ default:
+ return false
+ }
+ if len(o.Value) != len(xVal) {
+ return false
+ }
+ for k, v := range o.Value {
+ tv := xVal[k]
+ if !v.Equals(tv) {
+ return false
+ }
+ }
+ return true
+}
+
+// Iterate creates an immutable map iterator.
+func (o *ImmutableMap) Iterate() Iterator {
+ var keys []string
+ for k := range o.Value {
+ keys = append(keys, k)
+ }
+ return &MapIterator{
+ v: o.Value,
+ k: keys,
+ l: len(keys),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *ImmutableMap) CanIterate() bool {
+ return true
+}
+
+// Int represents an integer value.
+type Int struct {
+ ObjectImpl
+ Value int64
+}
+
+func (o *Int) String() string {
+ return strconv.FormatInt(o.Value, 10)
+}
+
+// TypeName returns the name of the type.
+func (o *Int) TypeName() string {
+ return "int"
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch rhs := rhs.(type) {
+ case *Int:
+ switch op {
+ case token.Add:
+ r := o.Value + rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Sub:
+ r := o.Value - rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Mul:
+ r := o.Value * rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Quo:
+ r := o.Value / rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Rem:
+ r := o.Value % rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.And:
+ r := o.Value & rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Or:
+ r := o.Value | rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Xor:
+ r := o.Value ^ rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.AndNot:
+ r := o.Value &^ rhs.Value
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Shl:
+ r := o.Value << uint64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Shr:
+ r := o.Value >> uint64(rhs.Value)
+ if r == o.Value {
+ return o, nil
+ }
+ return &Int{Value: r}, nil
+ case token.Less:
+ if o.Value < rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value > rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value <= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value >= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ case *Float:
+ switch op {
+ case token.Add:
+ return &Float{Value: float64(o.Value) + rhs.Value}, nil
+ case token.Sub:
+ return &Float{Value: float64(o.Value) - rhs.Value}, nil
+ case token.Mul:
+ return &Float{Value: float64(o.Value) * rhs.Value}, nil
+ case token.Quo:
+ return &Float{Value: float64(o.Value) / rhs.Value}, nil
+ case token.Less:
+ if float64(o.Value) < rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if float64(o.Value) > rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if float64(o.Value) <= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if float64(o.Value) >= rhs.Value {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ case *Char:
+ switch op {
+ case token.Add:
+ return &Char{Value: rune(o.Value) + rhs.Value}, nil
+ case token.Sub:
+ return &Char{Value: rune(o.Value) - rhs.Value}, nil
+ case token.Less:
+ if o.Value < int64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value > int64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value <= int64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value >= int64(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Int) Copy() Object {
+ return &Int{Value: o.Value}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Int) IsFalsy() bool {
+ return o.Value == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Int) Equals(x Object) bool {
+ t, ok := x.(*Int)
+ if !ok {
+ return false
+ }
+ return o.Value == t.Value
+}
+
+// Map represents a map of objects.
+type Map struct {
+ ObjectImpl
+ Value map[string]Object
+}
+
+// TypeName returns the name of the type.
+func (o *Map) TypeName() string {
+ return "map"
+}
+
+func (o *Map) String() string {
+ var pairs []string
+ for k, v := range o.Value {
+ pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
+ }
+ return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
+}
+
+// Copy returns a copy of the type.
+func (o *Map) Copy() Object {
+ c := make(map[string]Object)
+ for k, v := range o.Value {
+ c[k] = v.Copy()
+ }
+ return &Map{Value: c}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Map) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Map) Equals(x Object) bool {
+ var xVal map[string]Object
+ switch x := x.(type) {
+ case *Map:
+ xVal = x.Value
+ case *ImmutableMap:
+ xVal = x.Value
+ default:
+ return false
+ }
+ if len(o.Value) != len(xVal) {
+ return false
+ }
+ for k, v := range o.Value {
+ tv := xVal[k]
+ if !v.Equals(tv) {
+ return false
+ }
+ }
+ return true
+}
+
+// IndexGet returns the value for the given key.
+func (o *Map) IndexGet(index Object) (res Object, err error) {
+ strIdx, ok := ToString(index)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ res, ok = o.Value[strIdx]
+ if !ok {
+ res = UndefinedValue
+ }
+ return
+}
+
+// IndexSet sets the value for the given key.
+func (o *Map) IndexSet(index, value Object) (err error) {
+ strIdx, ok := ToString(index)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ o.Value[strIdx] = value
+ return nil
+}
+
+// Iterate creates a map iterator.
+func (o *Map) Iterate() Iterator {
+ var keys []string
+ for k := range o.Value {
+ keys = append(keys, k)
+ }
+ return &MapIterator{
+ v: o.Value,
+ k: keys,
+ l: len(keys),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *Map) CanIterate() bool {
+ return true
+}
+
+// ObjectPtr represents a free variable.
+type ObjectPtr struct {
+ ObjectImpl
+ Value *Object
+}
+
+func (o *ObjectPtr) String() string {
+ return "free-var"
+}
+
+// TypeName returns the name of the type.
+func (o *ObjectPtr) TypeName() string {
+ return "<free-var>"
+}
+
+// Copy returns a copy of the type.
+func (o *ObjectPtr) Copy() Object {
+ return o
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *ObjectPtr) IsFalsy() bool {
+ return o.Value == nil
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *ObjectPtr) Equals(x Object) bool {
+ return o == x
+}
+
+// String represents a string value.
+type String struct {
+ ObjectImpl
+ Value string
+ runeStr []rune
+}
+
+// TypeName returns the name of the type.
+func (o *String) TypeName() string {
+ return "string"
+}
+
+func (o *String) String() string {
+ return strconv.Quote(o.Value)
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *String) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch op {
+ case token.Add:
+ switch rhs := rhs.(type) {
+ case *String:
+ if len(o.Value)+len(rhs.Value) > MaxStringLen {
+ return nil, ErrStringLimit
+ }
+ return &String{Value: o.Value + rhs.Value}, nil
+ default:
+ rhsStr := rhs.String()
+ if len(o.Value)+len(rhsStr) > MaxStringLen {
+ return nil, ErrStringLimit
+ }
+ return &String{Value: o.Value + rhsStr}, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *String) IsFalsy() bool {
+ return len(o.Value) == 0
+}
+
+// Copy returns a copy of the type.
+func (o *String) Copy() Object {
+ return &String{Value: o.Value}
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *String) Equals(x Object) bool {
+ t, ok := x.(*String)
+ if !ok {
+ return false
+ }
+ return o.Value == t.Value
+}
+
+// IndexGet returns a character at a given index.
+func (o *String) IndexGet(index Object) (res Object, err error) {
+ intIdx, ok := index.(*Int)
+ if !ok {
+ err = ErrInvalidIndexType
+ return
+ }
+ idxVal := int(intIdx.Value)
+ if o.runeStr == nil {
+ o.runeStr = []rune(o.Value)
+ }
+ if idxVal < 0 || idxVal >= len(o.runeStr) {
+ res = UndefinedValue
+ return
+ }
+ res = &Char{Value: o.runeStr[idxVal]}
+ return
+}
+
+// Iterate creates a string iterator.
+func (o *String) Iterate() Iterator {
+ if o.runeStr == nil {
+ o.runeStr = []rune(o.Value)
+ }
+ return &StringIterator{
+ v: o.runeStr,
+ l: len(o.runeStr),
+ }
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *String) CanIterate() bool {
+ return true
+}
+
+// Time represents a time value.
+type Time struct {
+ ObjectImpl
+ Value time.Time
+}
+
+func (o *Time) String() string {
+ return o.Value.String()
+}
+
+// TypeName returns the name of the type.
+func (o *Time) TypeName() string {
+ return "time"
+}
+
+// BinaryOp returns another object that is the result of a given binary
+// operator and a right-hand side object.
+func (o *Time) BinaryOp(op token.Token, rhs Object) (Object, error) {
+ switch rhs := rhs.(type) {
+ case *Int:
+ switch op {
+ case token.Add: // time + int => time
+ if rhs.Value == 0 {
+ return o, nil
+ }
+ return &Time{Value: o.Value.Add(time.Duration(rhs.Value))}, nil
+ case token.Sub: // time - int => time
+ if rhs.Value == 0 {
+ return o, nil
+ }
+ return &Time{Value: o.Value.Add(time.Duration(-rhs.Value))}, nil
+ }
+ case *Time:
+ switch op {
+ case token.Sub: // time - time => int (duration)
+ return &Int{Value: int64(o.Value.Sub(rhs.Value))}, nil
+ case token.Less: // time < time => bool
+ if o.Value.Before(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.Greater:
+ if o.Value.After(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.LessEq:
+ if o.Value.Equal(rhs.Value) || o.Value.Before(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ case token.GreaterEq:
+ if o.Value.Equal(rhs.Value) || o.Value.After(rhs.Value) {
+ return TrueValue, nil
+ }
+ return FalseValue, nil
+ }
+ }
+ return nil, ErrInvalidOperator
+}
+
+// Copy returns a copy of the type.
+func (o *Time) Copy() Object {
+ return &Time{Value: o.Value}
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Time) IsFalsy() bool {
+ return o.Value.IsZero()
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Time) Equals(x Object) bool {
+ t, ok := x.(*Time)
+ if !ok {
+ return false
+ }
+ return o.Value.Equal(t.Value)
+}
+
+// Undefined represents an undefined value.
+type Undefined struct {
+ ObjectImpl
+}
+
+// TypeName returns the name of the type.
+func (o *Undefined) TypeName() string {
+ return "undefined"
+}
+
+func (o *Undefined) String() string {
+ return "<undefined>"
+}
+
+// Copy returns a copy of the type.
+func (o *Undefined) Copy() Object {
+ return o
+}
+
+// IsFalsy returns true if the value of the type is falsy.
+func (o *Undefined) IsFalsy() bool {
+ return true
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *Undefined) Equals(x Object) bool {
+ return o == x
+}
+
+// IndexGet returns an element at a given index.
+func (o *Undefined) IndexGet(_ Object) (Object, error) {
+ return UndefinedValue, nil
+}
+
+// Iterate creates a map iterator.
+func (o *Undefined) Iterate() Iterator {
+ return o
+}
+
+// CanIterate returns whether the Object can be Iterated.
+func (o *Undefined) CanIterate() bool {
+ return true
+}
+
+// Next returns true if there are more elements to iterate.
+func (o *Undefined) Next() bool {
+ return false
+}
+
+// Key returns the key or index value of the current element.
+func (o *Undefined) Key() Object {
+ return o
+}
+
+// Value returns the value of the current element.
+func (o *Undefined) Value() Object {
+ return o
+}
+
+// UserFunction represents a user function.
+type UserFunction struct {
+ ObjectImpl
+ Name string
+ Value CallableFunc
+ EncodingID string
+}
+
+// TypeName returns the name of the type.
+func (o *UserFunction) TypeName() string {
+ return "user-function:" + o.Name
+}
+
+func (o *UserFunction) String() string {
+ return "<user-function>"
+}
+
+// Copy returns a copy of the type.
+func (o *UserFunction) Copy() Object {
+ return &UserFunction{Value: o.Value}
+}
+
+// Equals returns true if the value of the type is equal to the value of
+// another object.
+func (o *UserFunction) Equals(_ Object) bool {
+ return false
+}
+
+// Call invokes a user function.
+func (o *UserFunction) Call(args ...Object) (Object, error) {
+ return o.Value(args...)
+}
+
+// CanCall returns whether the Object can be Called.
+func (o *UserFunction) CanCall() bool {
+ return true
+}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/ident_list.go b/vendor/github.com/d5/tengo/v2/parser/ast.go
index 8dd6d307..8c2f7c07 100644
--- a/vendor/github.com/d5/tengo/compiler/ast/ident_list.go
+++ b/vendor/github.com/d5/tengo/v2/parser/ast.go
@@ -1,43 +1,51 @@
-package ast
+package parser
import (
"strings"
+)
- "github.com/d5/tengo/compiler/source"
+const (
+ nullRep = "<null>"
)
+// Node represents a node in the AST.
+type Node interface {
+ // Pos returns the position of first character belonging to the node.
+ Pos() Pos
+ // End returns the position of first character immediately after the node.
+ End() Pos
+ // String returns a string representation of the node.
+ String() string
+}
+
// IdentList represents a list of identifiers.
type IdentList struct {
- LParen source.Pos
+ LParen Pos
VarArgs bool
List []*Ident
- RParen source.Pos
+ RParen Pos
}
// Pos returns the position of first character belonging to the node.
-func (n *IdentList) Pos() source.Pos {
+func (n *IdentList) Pos() Pos {
if n.LParen.IsValid() {
return n.LParen
}
-
if len(n.List) > 0 {
return n.List[0].Pos()
}
-
- return source.NoPos
+ return NoPos
}
// End returns the position of first character immediately after the node.
-func (n *IdentList) End() source.Pos {
+func (n *IdentList) End() Pos {
if n.RParen.IsValid() {
return n.RParen + 1
}
-
if l := len(n.List); l > 0 {
return n.List[l-1].End()
}
-
- return source.NoPos
+ return NoPos
}
// NumFields returns the number of fields.
@@ -45,7 +53,6 @@ func (n *IdentList) NumFields() int {
if n == nil {
return 0
}
-
return len(n.List)
}
@@ -58,6 +65,5 @@ func (n *IdentList) String() string {
list = append(list, e.String())
}
}
-
return "(" + strings.Join(list, ", ") + ")"
}
diff --git a/vendor/github.com/d5/tengo/v2/parser/expr.go b/vendor/github.com/d5/tengo/v2/parser/expr.go
new file mode 100644
index 00000000..71e5155b
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/parser/expr.go
@@ -0,0 +1,597 @@
+package parser
+
+import (
+ "strings"
+
+ "github.com/d5/tengo/v2/token"
+)
+
+// Expr represents an expression node in the AST.
+type Expr interface {
+ Node
+ exprNode()
+}
+
+// ArrayLit represents an array literal.
+type ArrayLit struct {
+ Elements []Expr
+ LBrack Pos
+ RBrack Pos
+}
+
+func (e *ArrayLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *ArrayLit) Pos() Pos {
+ return e.LBrack
+}
+
+// End returns the position of first character immediately after the node.
+func (e *ArrayLit) End() Pos {
+ return e.RBrack + 1
+}
+
+func (e *ArrayLit) String() string {
+ var elements []string
+ for _, m := range e.Elements {
+ elements = append(elements, m.String())
+ }
+ return "[" + strings.Join(elements, ", ") + "]"
+}
+
+// BadExpr represents a bad expression.
+type BadExpr struct {
+ From Pos
+ To Pos
+}
+
+func (e *BadExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *BadExpr) Pos() Pos {
+ return e.From
+}
+
+// End returns the position of first character immediately after the node.
+func (e *BadExpr) End() Pos {
+ return e.To
+}
+
+func (e *BadExpr) String() string {
+ return "<bad expression>"
+}
+
+// BinaryExpr represents a binary operator expression.
+type BinaryExpr struct {
+ LHS Expr
+ RHS Expr
+ Token token.Token
+ TokenPos Pos
+}
+
+func (e *BinaryExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *BinaryExpr) Pos() Pos {
+ return e.LHS.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *BinaryExpr) End() Pos {
+ return e.RHS.End()
+}
+
+func (e *BinaryExpr) String() string {
+ return "(" + e.LHS.String() + " " + e.Token.String() +
+ " " + e.RHS.String() + ")"
+}
+
+// BoolLit represents a boolean literal.
+type BoolLit struct {
+ Value bool
+ ValuePos Pos
+ Literal string
+}
+
+func (e *BoolLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *BoolLit) Pos() Pos {
+ return e.ValuePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *BoolLit) End() Pos {
+ return Pos(int(e.ValuePos) + len(e.Literal))
+}
+
+func (e *BoolLit) String() string {
+ return e.Literal
+}
+
+// CallExpr represents a function call expression.
+type CallExpr struct {
+ Func Expr
+ LParen Pos
+ Args []Expr
+ RParen Pos
+}
+
+func (e *CallExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *CallExpr) Pos() Pos {
+ return e.Func.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *CallExpr) End() Pos {
+ return e.RParen + 1
+}
+
+func (e *CallExpr) String() string {
+ var args []string
+ for _, e := range e.Args {
+ args = append(args, e.String())
+ }
+ return e.Func.String() + "(" + strings.Join(args, ", ") + ")"
+}
+
+// CharLit represents a character literal.
+type CharLit struct {
+ Value rune
+ ValuePos Pos
+ Literal string
+}
+
+func (e *CharLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *CharLit) Pos() Pos {
+ return e.ValuePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *CharLit) End() Pos {
+ return Pos(int(e.ValuePos) + len(e.Literal))
+}
+
+func (e *CharLit) String() string {
+ return e.Literal
+}
+
+// CondExpr represents a ternary conditional expression.
+type CondExpr struct {
+ Cond Expr
+ True Expr
+ False Expr
+ QuestionPos Pos
+ ColonPos Pos
+}
+
+func (e *CondExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *CondExpr) Pos() Pos {
+ return e.Cond.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *CondExpr) End() Pos {
+ return e.False.End()
+}
+
+func (e *CondExpr) String() string {
+ return "(" + e.Cond.String() + " ? " + e.True.String() +
+ " : " + e.False.String() + ")"
+}
+
+// ErrorExpr represents an error expression
+type ErrorExpr struct {
+ Expr Expr
+ ErrorPos Pos
+ LParen Pos
+ RParen Pos
+}
+
+func (e *ErrorExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *ErrorExpr) Pos() Pos {
+ return e.ErrorPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *ErrorExpr) End() Pos {
+ return e.RParen
+}
+
+func (e *ErrorExpr) String() string {
+ return "error(" + e.Expr.String() + ")"
+}
+
+// FloatLit represents a floating point literal.
+type FloatLit struct {
+ Value float64
+ ValuePos Pos
+ Literal string
+}
+
+func (e *FloatLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *FloatLit) Pos() Pos {
+ return e.ValuePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *FloatLit) End() Pos {
+ return Pos(int(e.ValuePos) + len(e.Literal))
+}
+
+func (e *FloatLit) String() string {
+ return e.Literal
+}
+
+// FuncLit represents a function literal.
+type FuncLit struct {
+ Type *FuncType
+ Body *BlockStmt
+}
+
+func (e *FuncLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *FuncLit) Pos() Pos {
+ return e.Type.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *FuncLit) End() Pos {
+ return e.Body.End()
+}
+
+func (e *FuncLit) String() string {
+ return "func" + e.Type.Params.String() + " " + e.Body.String()
+}
+
+// FuncType represents a function type definition.
+type FuncType struct {
+ FuncPos Pos
+ Params *IdentList
+}
+
+func (e *FuncType) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *FuncType) Pos() Pos {
+ return e.FuncPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *FuncType) End() Pos {
+ return e.Params.End()
+}
+
+func (e *FuncType) String() string {
+ return "func" + e.Params.String()
+}
+
+// Ident represents an identifier.
+type Ident struct {
+ Name string
+ NamePos Pos
+}
+
+func (e *Ident) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *Ident) Pos() Pos {
+ return e.NamePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *Ident) End() Pos {
+ return Pos(int(e.NamePos) + len(e.Name))
+}
+
+func (e *Ident) String() string {
+ if e != nil {
+ return e.Name
+ }
+ return nullRep
+}
+
+// ImmutableExpr represents an immutable expression
+type ImmutableExpr struct {
+ Expr Expr
+ ErrorPos Pos
+ LParen Pos
+ RParen Pos
+}
+
+func (e *ImmutableExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *ImmutableExpr) Pos() Pos {
+ return e.ErrorPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *ImmutableExpr) End() Pos {
+ return e.RParen
+}
+
+func (e *ImmutableExpr) String() string {
+ return "immutable(" + e.Expr.String() + ")"
+}
+
+// ImportExpr represents an import expression
+type ImportExpr struct {
+ ModuleName string
+ Token token.Token
+ TokenPos Pos
+}
+
+func (e *ImportExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *ImportExpr) Pos() Pos {
+ return e.TokenPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *ImportExpr) End() Pos {
+ // import("moduleName")
+ return Pos(int(e.TokenPos) + 10 + len(e.ModuleName))
+}
+
+func (e *ImportExpr) String() string {
+ return `import("` + e.ModuleName + `")"`
+}
+
+// IndexExpr represents an index expression.
+type IndexExpr struct {
+ Expr Expr
+ LBrack Pos
+ Index Expr
+ RBrack Pos
+}
+
+func (e *IndexExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *IndexExpr) Pos() Pos {
+ return e.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *IndexExpr) End() Pos {
+ return e.RBrack + 1
+}
+
+func (e *IndexExpr) String() string {
+ var index string
+ if e.Index != nil {
+ index = e.Index.String()
+ }
+ return e.Expr.String() + "[" + index + "]"
+}
+
+// IntLit represents an integer literal.
+type IntLit struct {
+ Value int64
+ ValuePos Pos
+ Literal string
+}
+
+func (e *IntLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *IntLit) Pos() Pos {
+ return e.ValuePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *IntLit) End() Pos {
+ return Pos(int(e.ValuePos) + len(e.Literal))
+}
+
+func (e *IntLit) String() string {
+ return e.Literal
+}
+
+// MapElementLit represents a map element.
+type MapElementLit struct {
+ Key string
+ KeyPos Pos
+ ColonPos Pos
+ Value Expr
+}
+
+func (e *MapElementLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *MapElementLit) Pos() Pos {
+ return e.KeyPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *MapElementLit) End() Pos {
+ return e.Value.End()
+}
+
+func (e *MapElementLit) String() string {
+ return e.Key + ": " + e.Value.String()
+}
+
+// MapLit represents a map literal.
+type MapLit struct {
+ LBrace Pos
+ Elements []*MapElementLit
+ RBrace Pos
+}
+
+func (e *MapLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *MapLit) Pos() Pos {
+ return e.LBrace
+}
+
+// End returns the position of first character immediately after the node.
+func (e *MapLit) End() Pos {
+ return e.RBrace + 1
+}
+
+func (e *MapLit) String() string {
+ var elements []string
+ for _, m := range e.Elements {
+ elements = append(elements, m.String())
+ }
+ return "{" + strings.Join(elements, ", ") + "}"
+}
+
+// ParenExpr represents a parenthesis wrapped expression.
+type ParenExpr struct {
+ Expr Expr
+ LParen Pos
+ RParen Pos
+}
+
+func (e *ParenExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *ParenExpr) Pos() Pos {
+ return e.LParen
+}
+
+// End returns the position of first character immediately after the node.
+func (e *ParenExpr) End() Pos {
+ return e.RParen + 1
+}
+
+func (e *ParenExpr) String() string {
+ return "(" + e.Expr.String() + ")"
+}
+
+// SelectorExpr represents a selector expression.
+type SelectorExpr struct {
+ Expr Expr
+ Sel Expr
+}
+
+func (e *SelectorExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *SelectorExpr) Pos() Pos {
+ return e.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *SelectorExpr) End() Pos {
+ return e.Sel.End()
+}
+
+func (e *SelectorExpr) String() string {
+ return e.Expr.String() + "." + e.Sel.String()
+}
+
+// SliceExpr represents a slice expression.
+type SliceExpr struct {
+ Expr Expr
+ LBrack Pos
+ Low Expr
+ High Expr
+ RBrack Pos
+}
+
+func (e *SliceExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *SliceExpr) Pos() Pos {
+ return e.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *SliceExpr) End() Pos {
+ return e.RBrack + 1
+}
+
+func (e *SliceExpr) String() string {
+ var low, high string
+ if e.Low != nil {
+ low = e.Low.String()
+ }
+ if e.High != nil {
+ high = e.High.String()
+ }
+ return e.Expr.String() + "[" + low + ":" + high + "]"
+}
+
+// StringLit represents a string literal.
+type StringLit struct {
+ Value string
+ ValuePos Pos
+ Literal string
+}
+
+func (e *StringLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *StringLit) Pos() Pos {
+ return e.ValuePos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *StringLit) End() Pos {
+ return Pos(int(e.ValuePos) + len(e.Literal))
+}
+
+func (e *StringLit) String() string {
+ return e.Literal
+}
+
+// UnaryExpr represents an unary operator expression.
+type UnaryExpr struct {
+ Expr Expr
+ Token token.Token
+ TokenPos Pos
+}
+
+func (e *UnaryExpr) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *UnaryExpr) Pos() Pos {
+ return e.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (e *UnaryExpr) End() Pos {
+ return e.Expr.End()
+}
+
+func (e *UnaryExpr) String() string {
+ return "(" + e.Token.String() + e.Expr.String() + ")"
+}
+
+// UndefinedLit represents an undefined literal.
+type UndefinedLit struct {
+ TokenPos Pos
+}
+
+func (e *UndefinedLit) exprNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (e *UndefinedLit) Pos() Pos {
+ return e.TokenPos
+}
+
+// End returns the position of first character immediately after the node.
+func (e *UndefinedLit) End() Pos {
+ return e.TokenPos + 9 // len(undefined) == 9
+}
+
+func (e *UndefinedLit) String() string {
+ return "undefined"
+}
diff --git a/vendor/github.com/d5/tengo/compiler/ast/file.go b/vendor/github.com/d5/tengo/v2/parser/file.go
index fc18b2d7..7cf50fea 100644
--- a/vendor/github.com/d5/tengo/compiler/ast/file.go
+++ b/vendor/github.com/d5/tengo/v2/parser/file.go
@@ -1,25 +1,23 @@
-package ast
+package parser
import (
"strings"
-
- "github.com/d5/tengo/compiler/source"
)
// File represents a file unit.
type File struct {
- InputFile *source.File
+ InputFile *SourceFile
Stmts []Stmt
}
// Pos returns the position of first character belonging to the node.
-func (n *File) Pos() source.Pos {
- return source.Pos(n.InputFile.Base)
+func (n *File) Pos() Pos {
+ return Pos(n.InputFile.Base)
}
// End returns the position of first character immediately after the node.
-func (n *File) End() source.Pos {
- return source.Pos(n.InputFile.Base + n.InputFile.Size)
+func (n *File) End() Pos {
+ return Pos(n.InputFile.Base + n.InputFile.Size)
}
func (n *File) String() string {
@@ -27,6 +25,5 @@ func (n *File) String() string {
for _, e := range n.Stmts {
stmts = append(stmts, e.String())
}
-
return strings.Join(stmts, "; ")
}
diff --git a/vendor/github.com/d5/tengo/compiler/opcodes.go b/vendor/github.com/d5/tengo/v2/parser/opcodes.go
index d832ee17..a4fbfbaf 100644
--- a/vendor/github.com/d5/tengo/compiler/opcodes.go
+++ b/vendor/github.com/d5/tengo/v2/parser/opcodes.go
@@ -1,4 +1,4 @@
-package compiler
+package parser
// Opcode represents a single byte operation code.
type Opcode = byte
@@ -45,10 +45,11 @@ const (
OpIteratorNext // Iterator next
OpIteratorKey // Iterator key
OpIteratorValue // Iterator value
- OpBinaryOp // Binary Operation
+ OpBinaryOp // Binary operation
+ OpSuspend // Suspend VM
)
-// OpcodeNames is opcode names.
+// OpcodeNames are string representation of opcodes.
var OpcodeNames = [...]string{
OpConstant: "CONST",
OpPop: "POP",
@@ -91,6 +92,7 @@ var OpcodeNames = [...]string{
OpIteratorKey: "ITKEY",
OpIteratorValue: "ITVAL",
OpBinaryOp: "BINARYOP",
+ OpSuspend: "SUSPEND",
}
// OpcodeOperands is the number of operands.
@@ -136,6 +138,7 @@ var OpcodeOperands = [...][]int{
OpIteratorKey: {},
OpIteratorValue: {},
OpBinaryOp: {1},
+ OpSuspend: {},
}
// ReadOperands reads operands from the bytecode.
@@ -147,9 +150,7 @@ func ReadOperands(numOperands []int, ins []byte) (operands []int, offset int) {
case 2:
operands = append(operands, int(ins[offset+1])|int(ins[offset])<<8)
}
-
offset += width
}
-
return
}
diff --git a/vendor/github.com/d5/tengo/compiler/parser/parser.go b/vendor/github.com/d5/tengo/v2/parser/parser.go
index 27dd48f0..501a9106 100644
--- a/vendor/github.com/d5/tengo/compiler/parser/parser.go
+++ b/vendor/github.com/d5/tengo/v2/parser/parser.go
@@ -1,63 +1,128 @@
-/*
- Parser parses the Tengo source files.
-
- Parser is a modified version of Go's parser implementation.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file.
-*/
-
package parser
import (
"fmt"
"io"
+ "sort"
"strconv"
- "github.com/d5/tengo/compiler/ast"
- "github.com/d5/tengo/compiler/scanner"
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
+ "github.com/d5/tengo/v2/token"
)
type bailout struct{}
-// Parser parses the Tengo source files.
+var stmtStart = map[token.Token]bool{
+ token.Break: true,
+ token.Continue: true,
+ token.For: true,
+ token.If: true,
+ token.Return: true,
+ token.Export: true,
+}
+
+// Error represents a parser error.
+type Error struct {
+ Pos SourceFilePos
+ Msg string
+}
+
+func (e Error) Error() string {
+ if e.Pos.Filename != "" || e.Pos.IsValid() {
+ return fmt.Sprintf("Parse Error: %s\n\tat %s", e.Msg, e.Pos)
+ }
+ return fmt.Sprintf("Parse Error: %s", e.Msg)
+}
+
+// ErrorList is a collection of parser errors.
+type ErrorList []*Error
+
+// Add adds a new parser error to the collection.
+func (p *ErrorList) Add(pos SourceFilePos, msg string) {
+ *p = append(*p, &Error{pos, msg})
+}
+
+// Len returns the number of elements in the collection.
+func (p ErrorList) Len() int {
+ return len(p)
+}
+
+func (p ErrorList) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+func (p ErrorList) Less(i, j int) bool {
+ e := &p[i].Pos
+ f := &p[j].Pos
+
+ if e.Filename != f.Filename {
+ return e.Filename < f.Filename
+ }
+ if e.Line != f.Line {
+ return e.Line < f.Line
+ }
+ if e.Column != f.Column {
+ return e.Column < f.Column
+ }
+ return p[i].Msg < p[j].Msg
+}
+
+// Sort sorts the collection.
+func (p ErrorList) Sort() {
+ sort.Sort(p)
+}
+
+func (p ErrorList) Error() string {
+ switch len(p) {
+ case 0:
+ return "no errors"
+ case 1:
+ return p[0].Error()
+ }
+ return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
+}
+
+// Err returns an error.
+func (p ErrorList) Err() error {
+ if len(p) == 0 {
+ return nil
+ }
+ return p
+}
+
+// Parser parses the Tengo source files. It's based on Go's parser
+// implementation.
type Parser struct {
- file *source.File
+ file *SourceFile
errors ErrorList
- scanner *scanner.Scanner
- pos source.Pos
+ scanner *Scanner
+ pos Pos
token token.Token
tokenLit string
- exprLevel int // < 0: in control clause, >= 0: in expression
- syncPos source.Pos // last sync position
- syncCount int // number of advance calls without progress
+ exprLevel int // < 0: in control clause, >= 0: in expression
+ syncPos Pos // last sync position
+ syncCount int // number of advance calls without progress
trace bool
indent int
traceOut io.Writer
}
// NewParser creates a Parser.
-func NewParser(file *source.File, src []byte, trace io.Writer) *Parser {
+func NewParser(file *SourceFile, src []byte, trace io.Writer) *Parser {
p := &Parser{
file: file,
trace: trace != nil,
traceOut: trace,
}
-
- p.scanner = scanner.NewScanner(p.file, src, func(pos source.FilePos, msg string) {
- p.errors.Add(pos, msg)
- }, 0)
-
+ p.scanner = NewScanner(p.file, src,
+ func(pos SourceFilePos, msg string) {
+ p.errors.Add(pos, msg)
+ }, 0)
p.next()
-
return p
}
// ParseFile parses the source and returns an AST file unit.
-func (p *Parser) ParseFile() (file *ast.File, err error) {
+func (p *Parser) ParseFile() (file *File, err error) {
defer func() {
if e := recover(); e != nil {
if _, ok := e.(bailout); !ok {
@@ -70,7 +135,7 @@ func (p *Parser) ParseFile() (file *ast.File, err error) {
}()
if p.trace {
- defer un(trace(p, "File"))
+ defer untracep(tracep(p, "File"))
}
if p.errors.Len() > 0 {
@@ -82,17 +147,16 @@ func (p *Parser) ParseFile() (file *ast.File, err error) {
return nil, p.errors.Err()
}
- file = &ast.File{
+ file = &File{
InputFile: p.file,
Stmts: stmts,
}
-
return
}
-func (p *Parser) parseExpr() ast.Expr {
+func (p *Parser) parseExpr() Expr {
if p.trace {
- defer un(trace(p, "Expression"))
+ defer untracep(tracep(p, "Expression"))
}
expr := p.parseBinaryExpr(token.LowestPrec + 1)
@@ -101,13 +165,12 @@ func (p *Parser) parseExpr() ast.Expr {
if p.token == token.Question {
return p.parseCondExpr(expr)
}
-
return expr
}
-func (p *Parser) parseBinaryExpr(prec1 int) ast.Expr {
+func (p *Parser) parseBinaryExpr(prec1 int) Expr {
if p.trace {
- defer un(trace(p, "BinaryExpression"))
+ defer untracep(tracep(p, "BinaryExpression"))
}
x := p.parseUnaryExpr()
@@ -122,7 +185,7 @@ func (p *Parser) parseBinaryExpr(prec1 int) ast.Expr {
y := p.parseBinaryExpr(prec + 1)
- x = &ast.BinaryExpr{
+ x = &BinaryExpr{
LHS: x,
RHS: y,
Token: op,
@@ -131,16 +194,13 @@ func (p *Parser) parseBinaryExpr(prec1 int) ast.Expr {
}
}
-func (p *Parser) parseCondExpr(cond ast.Expr) ast.Expr {
+func (p *Parser) parseCondExpr(cond Expr) Expr {
questionPos := p.expect(token.Question)
-
trueExpr := p.parseExpr()
-
colonPos := p.expect(token.Colon)
-
falseExpr := p.parseExpr()
- return &ast.CondExpr{
+ return &CondExpr{
Cond: cond,
True: trueExpr,
False: falseExpr,
@@ -149,9 +209,9 @@ func (p *Parser) parseCondExpr(cond ast.Expr) ast.Expr {
}
}
-func (p *Parser) parseUnaryExpr() ast.Expr {
+func (p *Parser) parseUnaryExpr() Expr {
if p.trace {
- defer un(trace(p, "UnaryExpression"))
+ defer untracep(tracep(p, "UnaryExpression"))
}
switch p.token {
@@ -159,19 +219,18 @@ func (p *Parser) parseUnaryExpr() ast.Expr {
pos, op := p.pos, p.token
p.next()
x := p.parseUnaryExpr()
- return &ast.UnaryExpr{
+ return &UnaryExpr{
Token: op,
TokenPos: pos,
Expr: x,
}
}
-
return p.parsePrimaryExpr()
}
-func (p *Parser) parsePrimaryExpr() ast.Expr {
+func (p *Parser) parsePrimaryExpr() Expr {
if p.trace {
- defer un(trace(p, "PrimaryExpression"))
+ defer untracep(tracep(p, "PrimaryExpression"))
}
x := p.parseOperand()
@@ -189,7 +248,7 @@ L:
pos := p.pos
p.errorExpected(pos, "selector")
p.advance(stmtStart)
- return &ast.BadExpr{From: pos, To: p.pos}
+ return &BadExpr{From: pos, To: p.pos}
}
case token.LBrack:
x = p.parseIndexOrSlice(x)
@@ -199,19 +258,18 @@ L:
break L
}
}
-
return x
}
-func (p *Parser) parseCall(x ast.Expr) *ast.CallExpr {
+func (p *Parser) parseCall(x Expr) *CallExpr {
if p.trace {
- defer un(trace(p, "Call"))
+ defer untracep(tracep(p, "Call"))
}
lparen := p.expect(token.LParen)
p.exprLevel++
- var list []ast.Expr
+ var list []Expr
for p.token != token.RParen && p.token != token.EOF {
list = append(list, p.parseExpr())
@@ -222,8 +280,7 @@ func (p *Parser) parseCall(x ast.Expr) *ast.CallExpr {
p.exprLevel--
rparen := p.expect(token.RParen)
-
- return &ast.CallExpr{
+ return &CallExpr{
Func: x,
LParen: lparen,
RParen: rparen,
@@ -239,26 +296,24 @@ func (p *Parser) expectComma(closing token.Token, want string) bool {
p.errorExpected(p.pos, want)
return false
}
-
return true
}
if p.token == token.Semicolon && p.tokenLit == "\n" {
p.next()
}
-
return false
}
-func (p *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+func (p *Parser) parseIndexOrSlice(x Expr) Expr {
if p.trace {
- defer un(trace(p, "IndexOrSlice"))
+ defer untracep(tracep(p, "IndexOrSlice"))
}
lbrack := p.expect(token.LBrack)
p.exprLevel++
- var index [2]ast.Expr
+ var index [2]Expr
if p.token != token.Colon {
index[0] = p.parseExpr()
}
@@ -277,7 +332,7 @@ func (p *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
if numColons > 0 {
// slice expression
- return &ast.SliceExpr{
+ return &SliceExpr{
Expr: x,
LBrack: lbrack,
RBrack: rbrack,
@@ -285,8 +340,7 @@ func (p *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
High: index[1],
}
}
-
- return &ast.IndexExpr{
+ return &IndexExpr{
Expr: x,
LBrack: lbrack,
RBrack: rbrack,
@@ -294,88 +348,78 @@ func (p *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
}
}
-func (p *Parser) parseSelector(x ast.Expr) ast.Expr {
+func (p *Parser) parseSelector(x Expr) Expr {
if p.trace {
- defer un(trace(p, "Selector"))
+ defer untracep(tracep(p, "Selector"))
}
sel := p.parseIdent()
-
- return &ast.SelectorExpr{Expr: x, Sel: &ast.StringLit{
+ return &SelectorExpr{Expr: x, Sel: &StringLit{
Value: sel.Name,
ValuePos: sel.NamePos,
Literal: sel.Name,
}}
}
-func (p *Parser) parseOperand() ast.Expr {
+func (p *Parser) parseOperand() Expr {
if p.trace {
- defer un(trace(p, "Operand"))
+ defer untracep(tracep(p, "Operand"))
}
switch p.token {
case token.Ident:
return p.parseIdent()
-
case token.Int:
v, _ := strconv.ParseInt(p.tokenLit, 10, 64)
- x := &ast.IntLit{
+ x := &IntLit{
Value: v,
ValuePos: p.pos,
Literal: p.tokenLit,
}
p.next()
return x
-
case token.Float:
v, _ := strconv.ParseFloat(p.tokenLit, 64)
- x := &ast.FloatLit{
+ x := &FloatLit{
Value: v,
ValuePos: p.pos,
Literal: p.tokenLit,
}
p.next()
return x
-
case token.Char:
return p.parseCharLit()
-
case token.String:
v, _ := strconv.Unquote(p.tokenLit)
- x := &ast.StringLit{
+ x := &StringLit{
Value: v,
ValuePos: p.pos,
Literal: p.tokenLit,
}
p.next()
return x
-
case token.True:
- x := &ast.BoolLit{
+ x := &BoolLit{
Value: true,
ValuePos: p.pos,
Literal: p.tokenLit,
}
p.next()
return x
-
case token.False:
- x := &ast.BoolLit{
+ x := &BoolLit{
Value: false,
ValuePos: p.pos,
Literal: p.tokenLit,
}
p.next()
return x
-
case token.Undefined:
- x := &ast.UndefinedLit{TokenPos: p.pos}
+ x := &UndefinedLit{TokenPos: p.pos}
p.next()
return x
-
case token.Import:
return p.parseImportExpr()
-
case token.LParen:
lparen := p.pos
p.next()
@@ -383,24 +427,19 @@ func (p *Parser) parseOperand() ast.Expr {
x := p.parseExpr()
p.exprLevel--
rparen := p.expect(token.RParen)
- return &ast.ParenExpr{
+ return &ParenExpr{
LParen: lparen,
Expr: x,
RParen: rparen,
}
-
case token.LBrack: // array literal
return p.parseArrayLit()
-
case token.LBrace: // map literal
return p.parseMapLit()
-
case token.Func: // function literal
return p.parseFuncLit()
-
case token.Error: // error expression
return p.parseErrorExpr()
-
case token.Immutable: // immutable expression
return p.parseImmutableExpr()
}
@@ -408,43 +447,38 @@ func (p *Parser) parseOperand() ast.Expr {
pos := p.pos
p.errorExpected(pos, "operand")
p.advance(stmtStart)
- return &ast.BadExpr{From: pos, To: p.pos}
+ return &BadExpr{From: pos, To: p.pos}
}
-func (p *Parser) parseImportExpr() ast.Expr {
+func (p *Parser) parseImportExpr() Expr {
pos := p.pos
-
p.next()
-
p.expect(token.LParen)
-
if p.token != token.String {
p.errorExpected(p.pos, "module name")
p.advance(stmtStart)
- return &ast.BadExpr{From: pos, To: p.pos}
+ return &BadExpr{From: pos, To: p.pos}
}
// module name
moduleName, _ := strconv.Unquote(p.tokenLit)
-
- expr := &ast.ImportExpr{
+ expr := &ImportExpr{
ModuleName: moduleName,
Token: token.Import,
TokenPos: pos,
}
p.next()
-
p.expect(token.RParen)
-
return expr
}
-func (p *Parser) parseCharLit() ast.Expr {
+func (p *Parser) parseCharLit() Expr {
if n := len(p.tokenLit); n >= 3 {
- if code, _, _, err := strconv.UnquoteChar(p.tokenLit[1:n-1], '\''); err == nil {
- x := &ast.CharLit{
- Value: rune(code),
+ code, _, _, err := strconv.UnquoteChar(p.tokenLit[1:n-1], '\'')
+ if err == nil {
+ x := &CharLit{
+ Value: code,
ValuePos: p.pos,
Literal: p.tokenLit,
}
@@ -456,38 +490,36 @@ func (p *Parser) parseCharLit() ast.Expr {
pos := p.pos
p.error(pos, "illegal char literal")
p.next()
- return &ast.BadExpr{
+ return &BadExpr{
From: pos,
To: p.pos,
}
}
-func (p *Parser) parseFuncLit() ast.Expr {
+func (p *Parser) parseFuncLit() Expr {
if p.trace {
- defer un(trace(p, "FuncLit"))
+ defer untracep(tracep(p, "FuncLit"))
}
typ := p.parseFuncType()
-
p.exprLevel++
body := p.parseBody()
p.exprLevel--
-
- return &ast.FuncLit{
+ return &FuncLit{
Type: typ,
Body: body,
}
}
-func (p *Parser) parseArrayLit() ast.Expr {
+func (p *Parser) parseArrayLit() Expr {
if p.trace {
- defer un(trace(p, "ArrayLit"))
+ defer untracep(tracep(p, "ArrayLit"))
}
lbrack := p.expect(token.LBrack)
p.exprLevel++
- var elements []ast.Expr
+ var elements []Expr
for p.token != token.RBrack && p.token != token.EOF {
elements = append(elements, p.parseExpr())
@@ -498,95 +530,83 @@ func (p *Parser) parseArrayLit() ast.Expr {
p.exprLevel--
rbrack := p.expect(token.RBrack)
-
- return &ast.ArrayLit{
+ return &ArrayLit{
Elements: elements,
LBrack: lbrack,
RBrack: rbrack,
}
}
-func (p *Parser) parseErrorExpr() ast.Expr {
+func (p *Parser) parseErrorExpr() Expr {
pos := p.pos
p.next()
-
lparen := p.expect(token.LParen)
value := p.parseExpr()
rparen := p.expect(token.RParen)
-
- expr := &ast.ErrorExpr{
+ return &ErrorExpr{
ErrorPos: pos,
Expr: value,
LParen: lparen,
RParen: rparen,
}
-
- return expr
}
-func (p *Parser) parseImmutableExpr() ast.Expr {
+func (p *Parser) parseImmutableExpr() Expr {
pos := p.pos
p.next()
-
lparen := p.expect(token.LParen)
value := p.parseExpr()
rparen := p.expect(token.RParen)
-
- expr := &ast.ImmutableExpr{
+ return &ImmutableExpr{
ErrorPos: pos,
Expr: value,
LParen: lparen,
RParen: rparen,
}
-
- return expr
}
-func (p *Parser) parseFuncType() *ast.FuncType {
+func (p *Parser) parseFuncType() *FuncType {
if p.trace {
- defer un(trace(p, "FuncType"))
+ defer untracep(tracep(p, "FuncType"))
}
pos := p.expect(token.Func)
params := p.parseIdentList()
-
- return &ast.FuncType{
+ return &FuncType{
FuncPos: pos,
Params: params,
}
}
-func (p *Parser) parseBody() *ast.BlockStmt {
+func (p *Parser) parseBody() *BlockStmt {
if p.trace {
- defer un(trace(p, "Body"))
+ defer untracep(tracep(p, "Body"))
}
lbrace := p.expect(token.LBrace)
list := p.parseStmtList()
rbrace := p.expect(token.RBrace)
-
- return &ast.BlockStmt{
+ return &BlockStmt{
LBrace: lbrace,
RBrace: rbrace,
Stmts: list,
}
}
-func (p *Parser) parseStmtList() (list []ast.Stmt) {
+func (p *Parser) parseStmtList() (list []Stmt) {
if p.trace {
- defer un(trace(p, "StatementList"))
+ defer untracep(tracep(p, "StatementList"))
}
for p.token != token.RBrace && p.token != token.EOF {
list = append(list, p.parseStmt())
}
-
return
}
-func (p *Parser) parseIdent() *ast.Ident {
+func (p *Parser) parseIdent() *Ident {
pos := p.pos
name := "_"
@@ -596,19 +616,18 @@ func (p *Parser) parseIdent() *ast.Ident {
} else {
p.expect(token.Ident)
}
-
- return &ast.Ident{
+ return &Ident{
NamePos: pos,
Name: name,
}
}
-func (p *Parser) parseIdentList() *ast.IdentList {
+func (p *Parser) parseIdentList() *IdentList {
if p.trace {
- defer un(trace(p, "IdentList"))
+ defer untracep(tracep(p, "IdentList"))
}
- var params []*ast.Ident
+ var params []*Ident
lparen := p.expect(token.LParen)
isVarArgs := false
if p.token != token.RParen {
@@ -629,8 +648,7 @@ func (p *Parser) parseIdentList() *ast.IdentList {
}
rparen := p.expect(token.RParen)
-
- return &ast.IdentList{
+ return &IdentList{
LParen: lparen,
RParen: rparen,
VarArgs: isVarArgs,
@@ -638,16 +656,18 @@ func (p *Parser) parseIdentList() *ast.IdentList {
}
}
-func (p *Parser) parseStmt() (stmt ast.Stmt) {
+func (p *Parser) parseStmt() (stmt Stmt) {
if p.trace {
- defer un(trace(p, "Statement"))
+ defer untracep(tracep(p, "Statement"))
}
switch p.token {
case // simple statements
- token.Func, token.Error, token.Immutable, token.Ident, token.Int, token.Float, token.Char, token.String, token.True, token.False,
- token.Undefined, token.Import, token.LParen, token.LBrace, token.LBrack,
- token.Add, token.Sub, token.Mul, token.And, token.Xor, token.Not:
+ token.Func, token.Error, token.Immutable, token.Ident, token.Int,
+ token.Float, token.Char, token.String, token.True, token.False,
+ token.Undefined, token.Import, token.LParen, token.LBrace,
+ token.LBrack, token.Add, token.Sub, token.Mul, token.And, token.Xor,
+ token.Not:
s := p.parseSimpleStmt(false)
p.expectSemi()
return s
@@ -662,23 +682,23 @@ func (p *Parser) parseStmt() (stmt ast.Stmt) {
case token.Break, token.Continue:
return p.parseBranchStmt(p.token)
case token.Semicolon:
- s := &ast.EmptyStmt{Semicolon: p.pos, Implicit: p.tokenLit == "\n"}
+ s := &EmptyStmt{Semicolon: p.pos, Implicit: p.tokenLit == "\n"}
p.next()
return s
case token.RBrace:
// semicolon may be omitted before a closing "}"
- return &ast.EmptyStmt{Semicolon: p.pos, Implicit: true}
+ return &EmptyStmt{Semicolon: p.pos, Implicit: true}
default:
pos := p.pos
p.errorExpected(pos, "statement")
p.advance(stmtStart)
- return &ast.BadStmt{From: pos, To: p.pos}
+ return &BadStmt{From: pos, To: p.pos}
}
}
-func (p *Parser) parseForStmt() ast.Stmt {
+func (p *Parser) parseForStmt() Stmt {
if p.trace {
- defer un(trace(p, "ForStmt"))
+ defer untracep(tracep(p, "ForStmt"))
}
pos := p.expect(token.For)
@@ -688,7 +708,7 @@ func (p *Parser) parseForStmt() ast.Stmt {
body := p.parseBlockStmt()
p.expectSemi()
- return &ast.ForStmt{
+ return &ForStmt{
ForPos: pos,
Body: body,
}
@@ -697,7 +717,7 @@ func (p *Parser) parseForStmt() ast.Stmt {
prevLevel := p.exprLevel
p.exprLevel = -1
- var s1 ast.Stmt
+ var s1 Stmt
if p.token != token.Semicolon { // skipping init
s1 = p.parseSimpleStmt(true)
}
@@ -705,7 +725,7 @@ func (p *Parser) parseForStmt() ast.Stmt {
// for _ in seq {} or
// for value in seq {} or
// for key, value in seq {}
- if forInStmt, isForIn := s1.(*ast.ForInStmt); isForIn {
+ if forInStmt, isForIn := s1.(*ForInStmt); isForIn {
forInStmt.ForPos = pos
p.exprLevel = prevLevel
forInStmt.Body = p.parseBlockStmt()
@@ -714,7 +734,7 @@ func (p *Parser) parseForStmt() ast.Stmt {
}
// for init; cond; post {}
- var s2, s3 ast.Stmt
+ var s2, s3 Stmt
if p.token == token.Semicolon {
p.next()
if p.token != token.Semicolon {
@@ -734,50 +754,45 @@ func (p *Parser) parseForStmt() ast.Stmt {
p.exprLevel = prevLevel
body := p.parseBlockStmt()
p.expectSemi()
-
cond := p.makeExpr(s2, "condition expression")
-
- return &ast.ForStmt{
+ return &ForStmt{
ForPos: pos,
Init: s1,
Cond: cond,
Post: s3,
Body: body,
}
-
}
-func (p *Parser) parseBranchStmt(tok token.Token) ast.Stmt {
+func (p *Parser) parseBranchStmt(tok token.Token) Stmt {
if p.trace {
- defer un(trace(p, "BranchStmt"))
+ defer untracep(tracep(p, "BranchStmt"))
}
pos := p.expect(tok)
- var label *ast.Ident
+ var label *Ident
if p.token == token.Ident {
label = p.parseIdent()
}
p.expectSemi()
-
- return &ast.BranchStmt{
+ return &BranchStmt{
Token: tok,
TokenPos: pos,
Label: label,
}
}
-func (p *Parser) parseIfStmt() ast.Stmt {
+func (p *Parser) parseIfStmt() Stmt {
if p.trace {
- defer un(trace(p, "IfStmt"))
+ defer untracep(tracep(p, "IfStmt"))
}
pos := p.expect(token.If)
-
init, cond := p.parseIfHeader()
body := p.parseBlockStmt()
- var elseStmt ast.Stmt
+ var elseStmt Stmt
if p.token == token.Else {
p.next()
@@ -789,13 +804,12 @@ func (p *Parser) parseIfStmt() ast.Stmt {
p.expectSemi()
default:
p.errorExpected(p.pos, "if or {")
- elseStmt = &ast.BadStmt{From: p.pos, To: p.pos}
+ elseStmt = &BadStmt{From: p.pos, To: p.pos}
}
} else {
p.expectSemi()
}
-
- return &ast.IfStmt{
+ return &IfStmt{
IfPos: pos,
Init: init,
Cond: cond,
@@ -804,40 +818,37 @@ func (p *Parser) parseIfStmt() ast.Stmt {
}
}
-func (p *Parser) parseBlockStmt() *ast.BlockStmt {
+func (p *Parser) parseBlockStmt() *BlockStmt {
if p.trace {
- defer un(trace(p, "BlockStmt"))
+ defer untracep(tracep(p, "BlockStmt"))
}
lbrace := p.expect(token.LBrace)
list := p.parseStmtList()
rbrace := p.expect(token.RBrace)
-
- return &ast.BlockStmt{
+ return &BlockStmt{
LBrace: lbrace,
RBrace: rbrace,
Stmts: list,
}
}
-func (p *Parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
+func (p *Parser) parseIfHeader() (init Stmt, cond Expr) {
if p.token == token.LBrace {
p.error(p.pos, "missing condition in if statement")
- cond = &ast.BadExpr{From: p.pos, To: p.pos}
+ cond = &BadExpr{From: p.pos, To: p.pos}
return
}
outer := p.exprLevel
p.exprLevel = -1
-
if p.token == token.Semicolon {
p.error(p.pos, "missing init in if statement")
return
}
-
init = p.parseSimpleStmt(false)
- var condStmt ast.Stmt
+ var condStmt Stmt
if p.token == token.LBrace {
condStmt = init
init = nil
@@ -852,75 +863,67 @@ func (p *Parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
if condStmt != nil {
cond = p.makeExpr(condStmt, "boolean expression")
}
-
if cond == nil {
- cond = &ast.BadExpr{From: p.pos, To: p.pos}
+ cond = &BadExpr{From: p.pos, To: p.pos}
}
-
p.exprLevel = outer
-
return
}
-func (p *Parser) makeExpr(s ast.Stmt, want string) ast.Expr {
+func (p *Parser) makeExpr(s Stmt, want string) Expr {
if s == nil {
return nil
}
- if es, isExpr := s.(*ast.ExprStmt); isExpr {
+ if es, isExpr := s.(*ExprStmt); isExpr {
return es.Expr
}
found := "simple statement"
- if _, isAss := s.(*ast.AssignStmt); isAss {
+ if _, isAss := s.(*AssignStmt); isAss {
found = "assignment"
}
-
p.error(s.Pos(), fmt.Sprintf("expected %s, found %s", want, found))
-
- return &ast.BadExpr{From: s.Pos(), To: p.safePos(s.End())}
+ return &BadExpr{From: s.Pos(), To: p.safePos(s.End())}
}
-func (p *Parser) parseReturnStmt() ast.Stmt {
+func (p *Parser) parseReturnStmt() Stmt {
if p.trace {
- defer un(trace(p, "ReturnStmt"))
+ defer untracep(tracep(p, "ReturnStmt"))
}
pos := p.pos
p.expect(token.Return)
- var x ast.Expr
+ var x Expr
if p.token != token.Semicolon && p.token != token.RBrace {
x = p.parseExpr()
}
p.expectSemi()
-
- return &ast.ReturnStmt{
+ return &ReturnStmt{
ReturnPos: pos,
Result: x,
}
}
-func (p *Parser) parseExportStmt() ast.Stmt {
+func (p *Parser) parseExportStmt() Stmt {
if p.trace {
- defer un(trace(p, "ExportStmt"))
+ defer untracep(tracep(p, "ExportStmt"))
}
pos := p.pos
p.expect(token.Export)
-
x := p.parseExpr()
p.expectSemi()
-
- return &ast.ExportStmt{
+ return &ExportStmt{
ExportPos: pos,
Result: x,
}
}
-func (p *Parser) parseSimpleStmt(forIn bool) ast.Stmt {
+func (p *Parser) parseSimpleStmt(forIn bool) Stmt {
if p.trace {
- defer un(trace(p, "SimpleStmt"))
+ defer untracep(tracep(p, "SimpleStmt"))
}
x := p.parseExprList()
@@ -929,10 +932,8 @@ func (p *Parser) parseSimpleStmt(forIn bool) ast.Stmt {
case token.Assign, token.Define: // assignment statement
pos, tok := p.pos, p.token
p.next()
-
y := p.parseExprList()
-
- return &ast.AssignStmt{
+ return &AssignStmt{
LHS: x,
RHS: y,
Token: tok,
@@ -941,35 +942,32 @@ func (p *Parser) parseSimpleStmt(forIn bool) ast.Stmt {
case token.In:
if forIn {
p.next()
-
y := p.parseExpr()
- var key, value *ast.Ident
+ var key, value *Ident
var ok bool
-
switch len(x) {
case 1:
- key = &ast.Ident{Name: "_", NamePos: x[0].Pos()}
+ key = &Ident{Name: "_", NamePos: x[0].Pos()}
- value, ok = x[0].(*ast.Ident)
+ value, ok = x[0].(*Ident)
if !ok {
p.errorExpected(x[0].Pos(), "identifier")
- value = &ast.Ident{Name: "_", NamePos: x[0].Pos()}
+ value = &Ident{Name: "_", NamePos: x[0].Pos()}
}
case 2:
- key, ok = x[0].(*ast.Ident)
+ key, ok = x[0].(*Ident)
if !ok {
p.errorExpected(x[0].Pos(), "identifier")
- key = &ast.Ident{Name: "_", NamePos: x[0].Pos()}
+ key = &Ident{Name: "_", NamePos: x[0].Pos()}
}
- value, ok = x[1].(*ast.Ident)
+ value, ok = x[1].(*Ident)
if !ok {
p.errorExpected(x[1].Pos(), "identifier")
- value = &ast.Ident{Name: "_", NamePos: x[1].Pos()}
+ value = &Ident{Name: "_", NamePos: x[1].Pos()}
}
}
-
- return &ast.ForInStmt{
+ return &ForInStmt{
Key: key,
Value: value,
Iterable: y,
@@ -984,33 +982,30 @@ func (p *Parser) parseSimpleStmt(forIn bool) ast.Stmt {
switch p.token {
case token.Define,
- token.AddAssign, token.SubAssign, token.MulAssign, token.QuoAssign, token.RemAssign,
- token.AndAssign, token.OrAssign, token.XorAssign, token.ShlAssign, token.ShrAssign, token.AndNotAssign:
+ token.AddAssign, token.SubAssign, token.MulAssign, token.QuoAssign,
+ token.RemAssign, token.AndAssign, token.OrAssign, token.XorAssign,
+ token.ShlAssign, token.ShrAssign, token.AndNotAssign:
pos, tok := p.pos, p.token
p.next()
-
y := p.parseExpr()
-
- return &ast.AssignStmt{
- LHS: []ast.Expr{x[0]},
- RHS: []ast.Expr{y},
+ return &AssignStmt{
+ LHS: []Expr{x[0]},
+ RHS: []Expr{y},
Token: tok,
TokenPos: pos,
}
case token.Inc, token.Dec:
// increment or decrement statement
- s := &ast.IncDecStmt{Expr: x[0], Token: p.token, TokenPos: p.pos}
+ s := &IncDecStmt{Expr: x[0], Token: p.token, TokenPos: p.pos}
p.next()
return s
}
-
- // expression statement
- return &ast.ExprStmt{Expr: x[0]}
+ return &ExprStmt{Expr: x[0]}
}
-func (p *Parser) parseExprList() (list []ast.Expr) {
+func (p *Parser) parseExprList() (list []Expr) {
if p.trace {
- defer un(trace(p, "ExpressionList"))
+ defer untracep(tracep(p, "ExpressionList"))
}
list = append(list, p.parseExpr())
@@ -1018,18 +1013,16 @@ func (p *Parser) parseExprList() (list []ast.Expr) {
p.next()
list = append(list, p.parseExpr())
}
-
return
}
-func (p *Parser) parseMapElementLit() *ast.MapElementLit {
+func (p *Parser) parseMapElementLit() *MapElementLit {
if p.trace {
- defer un(trace(p, "MapElementLit"))
+ defer untracep(tracep(p, "MapElementLit"))
}
pos := p.pos
name := "_"
-
if p.token == token.Ident {
name = p.tokenLit
} else if p.token == token.String {
@@ -1038,13 +1031,10 @@ func (p *Parser) parseMapElementLit() *ast.MapElementLit {
} else {
p.errorExpected(pos, "map key")
}
-
p.next()
-
colonPos := p.expect(token.Colon)
valueExpr := p.parseExpr()
-
- return &ast.MapElementLit{
+ return &MapElementLit{
Key: name,
KeyPos: pos,
ColonPos: colonPos,
@@ -1052,15 +1042,15 @@ func (p *Parser) parseMapElementLit() *ast.MapElementLit {
}
}
-func (p *Parser) parseMapLit() *ast.MapLit {
+func (p *Parser) parseMapLit() *MapLit {
if p.trace {
- defer un(trace(p, "MapLit"))
+ defer untracep(tracep(p, "MapLit"))
}
lbrace := p.expect(token.LBrace)
p.exprLevel++
- var elements []*ast.MapElementLit
+ var elements []*MapElementLit
for p.token != token.RBrace && p.token != token.EOF {
elements = append(elements, p.parseMapElementLit())
@@ -1071,22 +1061,20 @@ func (p *Parser) parseMapLit() *ast.MapLit {
p.exprLevel--
rbrace := p.expect(token.RBrace)
-
- return &ast.MapLit{
+ return &MapLit{
LBrace: lbrace,
RBrace: rbrace,
Elements: elements,
}
}
-func (p *Parser) expect(token token.Token) source.Pos {
+func (p *Parser) expect(token token.Token) Pos {
pos := p.pos
if p.token != token {
p.errorExpected(pos, "'"+token.String()+"'")
}
p.next()
-
return pos
}
@@ -1104,7 +1092,6 @@ func (p *Parser) expectSemi() {
p.errorExpected(p.pos, "';'")
p.advance(stmtStart)
}
-
}
func (p *Parser) advance(to map[token.Token]bool) {
@@ -1114,7 +1101,6 @@ func (p *Parser) advance(to map[token.Token]bool) {
p.syncCount++
return
}
-
if p.pos > p.syncPos {
p.syncPos = p.pos
p.syncCount = 0
@@ -1124,7 +1110,7 @@ func (p *Parser) advance(to map[token.Token]bool) {
}
}
-func (p *Parser) error(pos source.Pos, msg string) {
+func (p *Parser) error(pos Pos, msg string) {
filePos := p.file.Position(pos)
n := len(p.errors)
@@ -1132,16 +1118,14 @@ func (p *Parser) error(pos source.Pos, msg string) {
// discard errors reported on the same line
return
}
-
if n > 10 {
// too many errors; terminate early
panic(bailout{})
}
-
p.errors.Add(filePos, msg)
}
-func (p *Parser) errorExpected(pos source.Pos, msg string) {
+func (p *Parser) errorExpected(pos Pos, msg string) {
msg = "expected " + msg
if pos == p.pos {
// error happened at the current position: provide more specific
@@ -1154,7 +1138,6 @@ func (p *Parser) errorExpected(pos source.Pos, msg string) {
msg += ", found '" + p.token.String() + "'"
}
}
-
p.error(pos, msg)
}
@@ -1170,19 +1153,18 @@ func (p *Parser) next() {
p.printTrace(s)
}
}
-
p.token, p.tokenLit, p.pos = p.scanner.Scan()
}
func (p *Parser) printTrace(a ...interface{}) {
const (
- dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+ dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
n = len(dots)
)
filePos := p.file.Position(p.pos)
- _, _ = fmt.Fprintf(p.traceOut, "%5d: %5d:%3d: ", p.pos, filePos.Line, filePos.Column)
-
+ _, _ = fmt.Fprintf(p.traceOut, "%5d: %5d:%3d: ", p.pos, filePos.Line,
+ filePos.Column)
i := 2 * p.indent
for i > n {
_, _ = fmt.Fprint(p.traceOut, dots)
@@ -1192,25 +1174,23 @@ func (p *Parser) printTrace(a ...interface{}) {
_, _ = fmt.Fprintln(p.traceOut, a...)
}
-func (p *Parser) safePos(pos source.Pos) source.Pos {
+func (p *Parser) safePos(pos Pos) Pos {
fileBase := p.file.Base
fileSize := p.file.Size
if int(pos) < fileBase || int(pos) > fileBase+fileSize {
- return source.Pos(fileBase + fileSize)
+ return Pos(fileBase + fileSize)
}
-
return pos
}
-func trace(p *Parser, msg string) *Parser {
+func tracep(p *Parser, msg string) *Parser {
p.printTrace(msg, "(")
p.indent++
-
return p
}
-func un(p *Parser) {
+func untracep(p *Parser) {
p.indent--
p.printTrace(")")
}
diff --git a/vendor/github.com/d5/tengo/compiler/source/pos.go b/vendor/github.com/d5/tengo/v2/parser/pos.go
index 72128b13..f8d3898c 100644
--- a/vendor/github.com/d5/tengo/compiler/source/pos.go
+++ b/vendor/github.com/d5/tengo/v2/parser/pos.go
@@ -1,4 +1,4 @@
-package source
+package parser
// Pos represents a position in the file set.
type Pos int
diff --git a/vendor/github.com/d5/tengo/compiler/scanner/scanner.go b/vendor/github.com/d5/tengo/v2/parser/scanner.go
index 387cd8ee..f1d820a4 100644
--- a/vendor/github.com/d5/tengo/compiler/scanner/scanner.go
+++ b/vendor/github.com/d5/tengo/v2/parser/scanner.go
@@ -1,45 +1,53 @@
-/*
- Scanner reads the Tengo source text and tokenize them.
-
- Scanner is a modified version of Go's scanner implementation.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file.
-*/
-
-package scanner
+package parser
import (
"fmt"
"unicode"
"unicode/utf8"
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
+ "github.com/d5/tengo/v2/token"
)
// byte order mark
const bom = 0xFEFF
-// Scanner reads the Tengo source text.
+// ScanMode represents a scanner mode.
+type ScanMode int
+
+// List of scanner modes.
+const (
+ ScanComments ScanMode = 1 << iota
+ DontInsertSemis
+)
+
+// ScannerErrorHandler is an error handler for the scanner.
+type ScannerErrorHandler func(pos SourceFilePos, msg string)
+
+// Scanner reads the Tengo source text. It's based on Go's scanner
+// implementation.
type Scanner struct {
- file *source.File // source file handle
- src []byte // source
- ch rune // current character
- offset int // character offset
- readOffset int // reading offset (position after current character)
- lineOffset int // current line offset
- insertSemi bool // insert a semicolon before next newline
- errorHandler ErrorHandler // error reporting; or nil
- errorCount int // number of errors encountered
- mode Mode
+ file *SourceFile // source file handle
+ src []byte // source
+ ch rune // current character
+ offset int // character offset
+ readOffset int // reading offset (position after current character)
+ lineOffset int // current line offset
+ insertSemi bool // insert a semicolon before next newline
+ errorHandler ScannerErrorHandler // error reporting; or nil
+ errorCount int // number of errors encountered
+ mode ScanMode
}
// NewScanner creates a Scanner.
-func NewScanner(file *source.File, src []byte, errorHandler ErrorHandler, mode Mode) *Scanner {
+func NewScanner(
+ file *SourceFile,
+ src []byte,
+ errorHandler ScannerErrorHandler,
+ mode ScanMode,
+) *Scanner {
if file.Size != len(src) {
- panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size, len(src)))
+ panic(fmt.Sprintf("file size (%d) does not match src len (%d)",
+ file.Size, len(src)))
}
s := &Scanner{
@@ -64,7 +72,11 @@ func (s *Scanner) ErrorCount() int {
}
// Scan returns a token, token literal and its position.
-func (s *Scanner) Scan() (tok token.Token, literal string, pos source.Pos) {
+func (s *Scanner) Scan() (
+ tok token.Token,
+ literal string,
+ pos Pos,
+) {
s.skipWhitespace()
pos = s.file.FileSetPos(s.offset)
@@ -77,7 +89,8 @@ func (s *Scanner) Scan() (tok token.Token, literal string, pos source.Pos) {
literal = s.scanIdentifier()
tok = token.Lookup(literal)
switch tok {
- case token.Ident, token.Break, token.Continue, token.Return, token.Export, token.True, token.False, token.Undefined:
+ case token.Ident, token.Break, token.Continue, token.Return,
+ token.Export, token.True, token.False, token.Undefined:
insertSemi = true
}
case '0' <= ch && ch <= '9':
@@ -184,9 +197,11 @@ func (s *Scanner) Scan() (tok token.Token, literal string, pos source.Pos) {
case '^':
tok = s.switch2(token.Xor, token.XorAssign)
case '<':
- tok = s.switch4(token.Less, token.LessEq, '<', token.Shl, token.ShlAssign)
+ tok = s.switch4(token.Less, token.LessEq, '<',
+ token.Shl, token.ShlAssign)
case '>':
- tok = s.switch4(token.Greater, token.GreaterEq, '>', token.Shr, token.ShrAssign)
+ tok = s.switch4(token.Greater, token.GreaterEq, '>',
+ token.Shr, token.ShrAssign)
case '=':
tok = s.switch2(token.Assign, token.Equal)
case '!':
@@ -203,18 +218,17 @@ func (s *Scanner) Scan() (tok token.Token, literal string, pos source.Pos) {
default:
// next reports unexpected BOMs - don't repeat
if ch != bom {
- s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
+ s.error(s.file.Offset(pos),
+ fmt.Sprintf("illegal character %#U", ch))
}
insertSemi = s.insertSemi // preserve insertSemi info
tok = token.Illegal
literal = string(ch)
}
}
-
if s.mode&DontInsertSemis == 0 {
s.insertSemi = insertSemi
}
-
return
}
@@ -254,7 +268,6 @@ func (s *Scanner) peek() byte {
if s.readOffset < len(s.src) {
return s.src[s.readOffset]
}
-
return 0
}
@@ -262,7 +275,6 @@ func (s *Scanner) error(offset int, msg string) {
if s.errorHandler != nil {
s.errorHandler(s.file.Position(s.file.FileSetPos(offset)), msg)
}
-
s.errorCount++
}
@@ -310,11 +322,9 @@ exit:
lit = lit[:len(lit)-1]
numCR--
}
-
if numCR > 0 {
lit = StripCR(lit, lit[1] == '*')
}
-
return string(lit)
}
@@ -358,7 +368,6 @@ func (s *Scanner) findLineEnd() bool {
}
s.next() // consume '/'
}
-
return false
}
@@ -367,7 +376,6 @@ func (s *Scanner) scanIdentifier() string {
for isLetter(s.ch) || isDigit(s.ch) {
s.next()
}
-
return string(s.src[offs:s.offset])
}
@@ -377,7 +385,9 @@ func (s *Scanner) scanMantissa(base int) {
}
}
-func (s *Scanner) scanNumber(seenDecimalPoint bool) (tok token.Token, lit string) {
+func (s *Scanner) scanNumber(
+ seenDecimalPoint bool,
+) (tok token.Token, lit string) {
// digitVal(s.ch) < 10
offs := s.offset
tok = token.Int
@@ -422,7 +432,6 @@ func (s *Scanner) scanNumber(seenDecimalPoint bool) (tok token.Token, lit string
s.error(offs, "illegal octal number")
}
}
-
return
}
@@ -449,7 +458,6 @@ exponent:
s.error(offs, "illegal floating-point exponent")
}
}
-
return
}
@@ -486,7 +494,8 @@ func (s *Scanner) scanEscape(quote rune) bool {
for n > 0 {
d := uint32(digitVal(s.ch))
if d >= base {
- msg := fmt.Sprintf("illegal character %#U in escape sequence", s.ch)
+ msg := fmt.Sprintf(
+ "illegal character %#U in escape sequence", s.ch)
if s.ch < 0 {
msg = "escape sequence not terminated"
}
@@ -502,7 +511,6 @@ func (s *Scanner) scanEscape(quote rune) bool {
s.error(offs, "escape sequence is invalid Unicode code point")
return false
}
-
return true
}
@@ -537,7 +545,6 @@ func (s *Scanner) scanRune() string {
if valid && n != 1 {
s.error(offs, "illegal rune literal")
}
-
return string(s.src[offs:s.offset])
}
@@ -558,7 +565,6 @@ func (s *Scanner) scanString() string {
s.scanEscape('"')
}
}
-
return string(s.src[offs:s.offset])
}
@@ -588,30 +594,30 @@ func (s *Scanner) scanRawString() string {
if hasCR {
lit = StripCR(lit, false)
}
-
return string(lit)
}
// StripCR removes carriage return characters.
func StripCR(b []byte, comment bool) []byte {
c := make([]byte, len(b))
-
i := 0
for j, ch := range b {
- // In a /*-style comment, don't strip \r from *\r/ (incl. sequences of \r from *\r\r...\r/)
- // since the resulting */ would terminate the comment too early unless the \r is immediately
- // following the opening /* in which case it's ok because /*/ is not closed yet.
- if ch != '\r' || comment && i > len("/*") && c[i-1] == '*' && j+1 < len(b) && b[j+1] == '/' {
+ // In a /*-style comment, don't strip \r from *\r/ (incl. sequences of
+ // \r from *\r\r...\r/) since the resulting */ would terminate the
+ // comment too early unless the \r is immediately following the opening
+ // /* in which case it's ok because /*/ is not closed yet.
+ if ch != '\r' || comment && i > len("/*") && c[i-1] == '*' &&
+ j+1 < len(b) && b[j+1] == '/' {
c[i] = ch
i++
}
}
-
return c[:i]
}
func (s *Scanner) skipWhitespace() {
- for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' && !s.insertSemi || s.ch == '\r' {
+ for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' && !s.insertSemi ||
+ s.ch == '\r' {
s.next()
}
}
@@ -621,49 +627,53 @@ func (s *Scanner) switch2(tok0, tok1 token.Token) token.Token {
s.next()
return tok1
}
-
return tok0
}
-func (s *Scanner) switch3(tok0, tok1 token.Token, ch2 rune, tok2 token.Token) token.Token {
+func (s *Scanner) switch3(
+ tok0, tok1 token.Token,
+ ch2 rune,
+ tok2 token.Token,
+) token.Token {
if s.ch == '=' {
s.next()
return tok1
}
-
if s.ch == ch2 {
s.next()
return tok2
}
-
return tok0
}
-func (s *Scanner) switch4(tok0, tok1 token.Token, ch2 rune, tok2, tok3 token.Token) token.Token {
+func (s *Scanner) switch4(
+ tok0, tok1 token.Token,
+ ch2 rune,
+ tok2, tok3 token.Token,
+) token.Token {
if s.ch == '=' {
s.next()
return tok1
}
-
if s.ch == ch2 {
s.next()
if s.ch == '=' {
s.next()
return tok3
}
-
return tok2
}
-
return tok0
}
func isLetter(ch rune) bool {
- return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
+ return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' ||
+ ch >= utf8.RuneSelf && unicode.IsLetter(ch)
}
func isDigit(ch rune) bool {
- return '0' <= ch && ch <= '9' || ch >= utf8.RuneSelf && unicode.IsDigit(ch)
+ return '0' <= ch && ch <= '9' ||
+ ch >= utf8.RuneSelf && unicode.IsDigit(ch)
}
func digitVal(ch rune) int {
@@ -675,6 +685,5 @@ func digitVal(ch rune) int {
case 'A' <= ch && ch <= 'F':
return int(ch - 'A' + 10)
}
-
return 16 // larger than any legal digit val
}
diff --git a/vendor/github.com/d5/tengo/v2/parser/source_file.go b/vendor/github.com/d5/tengo/v2/parser/source_file.go
new file mode 100644
index 00000000..e9f4b0f5
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/parser/source_file.go
@@ -0,0 +1,231 @@
+package parser
+
+import (
+ "fmt"
+ "sort"
+)
+
+// SourceFilePos represents a position information in the file.
+type SourceFilePos struct {
+ Filename string // filename, if any
+ Offset int // offset, starting at 0
+ Line int // line number, starting at 1
+ Column int // column number, starting at 1 (byte count)
+}
+
+// IsValid returns true if the position is valid.
+func (p SourceFilePos) IsValid() bool {
+ return p.Line > 0
+}
+
+// String returns a string in one of several forms:
+//
+// file:line:column valid position with file name
+// file:line valid position with file name but no column (column == 0)
+// line:column valid position without file name
+// line valid position without file name and no column (column == 0)
+// file invalid position with file name
+// - invalid position without file name
+//
+func (p SourceFilePos) String() string {
+ s := p.Filename
+ if p.IsValid() {
+ if s != "" {
+ s += ":"
+ }
+ s += fmt.Sprintf("%d", p.Line)
+ if p.Column != 0 {
+ s += fmt.Sprintf(":%d", p.Column)
+ }
+ }
+ if s == "" {
+ s = "-"
+ }
+ return s
+}
+
+// SourceFileSet represents a set of source files.
+type SourceFileSet struct {
+ Base int // base offset for the next file
+ Files []*SourceFile // list of files in the order added to the set
+ LastFile *SourceFile // cache of last file looked up
+}
+
+// NewFileSet creates a new file set.
+func NewFileSet() *SourceFileSet {
+ return &SourceFileSet{
+ Base: 1, // 0 == NoPos
+ }
+}
+
+// AddFile adds a new file in the file set.
+func (s *SourceFileSet) AddFile(filename string, base, size int) *SourceFile {
+ if base < 0 {
+ base = s.Base
+ }
+ if base < s.Base || size < 0 {
+ panic("illegal base or size")
+ }
+ f := &SourceFile{
+ set: s,
+ Name: filename,
+ Base: base,
+ Size: size,
+ Lines: []int{0},
+ }
+ base += size + 1 // +1 because EOF also has a position
+ if base < 0 {
+ panic("offset overflow (> 2G of source code in file set)")
+ }
+
+ // add the file to the file set
+ s.Base = base
+ s.Files = append(s.Files, f)
+ s.LastFile = f
+ return f
+}
+
+// File returns the file that contains the position p. If no such file is
+// found (for instance for p == NoPos), the result is nil.
+func (s *SourceFileSet) File(p Pos) (f *SourceFile) {
+ if p != NoPos {
+ f = s.file(p)
+ }
+ return
+}
+
+// Position converts a SourcePos p in the fileset into a SourceFilePos value.
+func (s *SourceFileSet) Position(p Pos) (pos SourceFilePos) {
+ if p != NoPos {
+ if f := s.file(p); f != nil {
+ return f.position(p)
+ }
+ }
+ return
+}
+
+func (s *SourceFileSet) file(p Pos) *SourceFile {
+ // common case: p is in last file
+ f := s.LastFile
+ if f != nil && f.Base <= int(p) && int(p) <= f.Base+f.Size {
+ return f
+ }
+
+ // p is not in last file - search all files
+ if i := searchFiles(s.Files, int(p)); i >= 0 {
+ f := s.Files[i]
+
+ // f.base <= int(p) by definition of searchFiles
+ if int(p) <= f.Base+f.Size {
+ s.LastFile = f // race is ok - s.last is only a cache
+ return f
+ }
+ }
+ return nil
+}
+
+func searchFiles(a []*SourceFile, x int) int {
+ return sort.Search(len(a), func(i int) bool { return a[i].Base > x }) - 1
+}
+
+// SourceFile represents a source file.
+type SourceFile struct {
+ // SourceFile set for the file
+ set *SourceFileSet
+ // SourceFile name as provided to AddFile
+ Name string
+ // SourcePos value range for this file is [base...base+size]
+ Base int
+ // SourceFile size as provided to AddFile
+ Size int
+ // Lines contains the offset of the first character for each line
+ // (the first entry is always 0)
+ Lines []int
+}
+
+// Set returns SourceFileSet.
+func (f *SourceFile) Set() *SourceFileSet {
+ return f.set
+}
+
+// LineCount returns the current number of lines.
+func (f *SourceFile) LineCount() int {
+ return len(f.Lines)
+}
+
+// AddLine adds a new line.
+func (f *SourceFile) AddLine(offset int) {
+ i := len(f.Lines)
+ if (i == 0 || f.Lines[i-1] < offset) && offset < f.Size {
+ f.Lines = append(f.Lines, offset)
+ }
+}
+
+// LineStart returns the position of the first character in the line.
+func (f *SourceFile) LineStart(line int) Pos {
+ if line < 1 {
+ panic("illegal line number (line numbering starts at 1)")
+ }
+ if line > len(f.Lines) {
+ panic("illegal line number")
+ }
+ return Pos(f.Base + f.Lines[line-1])
+}
+
+// FileSetPos returns the position in the file set.
+func (f *SourceFile) FileSetPos(offset int) Pos {
+ if offset > f.Size {
+ panic("illegal file offset")
+ }
+ return Pos(f.Base + offset)
+}
+
+// Offset translates the file set position into the file offset.
+func (f *SourceFile) Offset(p Pos) int {
+ if int(p) < f.Base || int(p) > f.Base+f.Size {
+ panic("illegal SourcePos value")
+ }
+ return int(p) - f.Base
+}
+
+// Position translates the file set position into the file position.
+func (f *SourceFile) Position(p Pos) (pos SourceFilePos) {
+ if p != NoPos {
+ if int(p) < f.Base || int(p) > f.Base+f.Size {
+ panic("illegal SourcePos value")
+ }
+ pos = f.position(p)
+ }
+ return
+}
+
+func (f *SourceFile) position(p Pos) (pos SourceFilePos) {
+ offset := int(p) - f.Base
+ pos.Offset = offset
+ pos.Filename, pos.Line, pos.Column = f.unpack(offset)
+ return
+}
+
+func (f *SourceFile) unpack(offset int) (filename string, line, column int) {
+ filename = f.Name
+ if i := searchInts(f.Lines, offset); i >= 0 {
+ line, column = i+1, offset-f.Lines[i]+1
+ }
+ return
+}
+
+func searchInts(a []int, x int) int {
+ // This function body is a manually inlined version of:
+ // return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
+ i, j := 0, len(a)
+ for i < j {
+ h := i + (j-i)/2 // avoid overflow when computing h
+ // i ≤ h < j
+ if a[h] <= x {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ return i - 1
+}
diff --git a/vendor/github.com/d5/tengo/v2/parser/stmt.go b/vendor/github.com/d5/tengo/v2/parser/stmt.go
new file mode 100644
index 00000000..c0848c48
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/parser/stmt.go
@@ -0,0 +1,349 @@
+package parser
+
+import (
+ "strings"
+
+ "github.com/d5/tengo/v2/token"
+)
+
+// Stmt represents a statement in the AST.
+type Stmt interface {
+ Node
+ stmtNode()
+}
+
+// AssignStmt represents an assignment statement.
+type AssignStmt struct {
+ LHS []Expr
+ RHS []Expr
+ Token token.Token
+ TokenPos Pos
+}
+
+func (s *AssignStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *AssignStmt) Pos() Pos {
+ return s.LHS[0].Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (s *AssignStmt) End() Pos {
+ return s.RHS[len(s.RHS)-1].End()
+}
+
+func (s *AssignStmt) String() string {
+ var lhs, rhs []string
+ for _, e := range s.LHS {
+ lhs = append(lhs, e.String())
+ }
+ for _, e := range s.RHS {
+ rhs = append(rhs, e.String())
+ }
+ return strings.Join(lhs, ", ") + " " + s.Token.String() +
+ " " + strings.Join(rhs, ", ")
+}
+
+// BadStmt represents a bad statement.
+type BadStmt struct {
+ From Pos
+ To Pos
+}
+
+func (s *BadStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *BadStmt) Pos() Pos {
+ return s.From
+}
+
+// End returns the position of first character immediately after the node.
+func (s *BadStmt) End() Pos {
+ return s.To
+}
+
+func (s *BadStmt) String() string {
+ return "<bad statement>"
+}
+
+// BlockStmt represents a block statement.
+type BlockStmt struct {
+ Stmts []Stmt
+ LBrace Pos
+ RBrace Pos
+}
+
+func (s *BlockStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *BlockStmt) Pos() Pos {
+ return s.LBrace
+}
+
+// End returns the position of first character immediately after the node.
+func (s *BlockStmt) End() Pos {
+ return s.RBrace + 1
+}
+
+func (s *BlockStmt) String() string {
+ var list []string
+ for _, e := range s.Stmts {
+ list = append(list, e.String())
+ }
+ return "{" + strings.Join(list, "; ") + "}"
+}
+
+// BranchStmt represents a branch statement.
+type BranchStmt struct {
+ Token token.Token
+ TokenPos Pos
+ Label *Ident
+}
+
+func (s *BranchStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *BranchStmt) Pos() Pos {
+ return s.TokenPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *BranchStmt) End() Pos {
+ if s.Label != nil {
+ return s.Label.End()
+ }
+
+ return Pos(int(s.TokenPos) + len(s.Token.String()))
+}
+
+func (s *BranchStmt) String() string {
+ var label string
+ if s.Label != nil {
+ label = " " + s.Label.Name
+ }
+ return s.Token.String() + label
+}
+
+// EmptyStmt represents an empty statement.
+type EmptyStmt struct {
+ Semicolon Pos
+ Implicit bool
+}
+
+func (s *EmptyStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *EmptyStmt) Pos() Pos {
+ return s.Semicolon
+}
+
+// End returns the position of first character immediately after the node.
+func (s *EmptyStmt) End() Pos {
+ if s.Implicit {
+ return s.Semicolon
+ }
+ return s.Semicolon + 1
+}
+
+func (s *EmptyStmt) String() string {
+ return ";"
+}
+
+// ExportStmt represents an export statement.
+type ExportStmt struct {
+ ExportPos Pos
+ Result Expr
+}
+
+func (s *ExportStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *ExportStmt) Pos() Pos {
+ return s.ExportPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *ExportStmt) End() Pos {
+ return s.Result.End()
+}
+
+func (s *ExportStmt) String() string {
+ return "export " + s.Result.String()
+}
+
+// ExprStmt represents an expression statement.
+type ExprStmt struct {
+ Expr Expr
+}
+
+func (s *ExprStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *ExprStmt) Pos() Pos {
+ return s.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (s *ExprStmt) End() Pos {
+ return s.Expr.End()
+}
+
+func (s *ExprStmt) String() string {
+ return s.Expr.String()
+}
+
+// ForInStmt represents a for-in statement.
+type ForInStmt struct {
+ ForPos Pos
+ Key *Ident
+ Value *Ident
+ Iterable Expr
+ Body *BlockStmt
+}
+
+func (s *ForInStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *ForInStmt) Pos() Pos {
+ return s.ForPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *ForInStmt) End() Pos {
+ return s.Body.End()
+}
+
+func (s *ForInStmt) String() string {
+ if s.Value != nil {
+ return "for " + s.Key.String() + ", " + s.Value.String() +
+ " in " + s.Iterable.String() + " " + s.Body.String()
+ }
+ return "for " + s.Key.String() + " in " + s.Iterable.String() +
+ " " + s.Body.String()
+}
+
+// ForStmt represents a for statement.
+type ForStmt struct {
+ ForPos Pos
+ Init Stmt
+ Cond Expr
+ Post Stmt
+ Body *BlockStmt
+}
+
+func (s *ForStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *ForStmt) Pos() Pos {
+ return s.ForPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *ForStmt) End() Pos {
+ return s.Body.End()
+}
+
+func (s *ForStmt) String() string {
+ var init, cond, post string
+ if s.Init != nil {
+ init = s.Init.String()
+ }
+ if s.Cond != nil {
+ cond = s.Cond.String() + " "
+ }
+ if s.Post != nil {
+ post = s.Post.String()
+ }
+
+ if init != "" || post != "" {
+ return "for " + init + " ; " + cond + " ; " + post + s.Body.String()
+ }
+ return "for " + cond + s.Body.String()
+}
+
+// IfStmt represents an if statement.
+type IfStmt struct {
+ IfPos Pos
+ Init Stmt
+ Cond Expr
+ Body *BlockStmt
+ Else Stmt // else branch; or nil
+}
+
+func (s *IfStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *IfStmt) Pos() Pos {
+ return s.IfPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *IfStmt) End() Pos {
+ if s.Else != nil {
+ return s.Else.End()
+ }
+ return s.Body.End()
+}
+
+func (s *IfStmt) String() string {
+ var initStmt, elseStmt string
+ if s.Init != nil {
+ initStmt = s.Init.String() + "; "
+ }
+ if s.Else != nil {
+ elseStmt = " else " + s.Else.String()
+ }
+ return "if " + initStmt + s.Cond.String() + " " +
+ s.Body.String() + elseStmt
+}
+
+// IncDecStmt represents increment or decrement statement.
+type IncDecStmt struct {
+ Expr Expr
+ Token token.Token
+ TokenPos Pos
+}
+
+func (s *IncDecStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *IncDecStmt) Pos() Pos {
+ return s.Expr.Pos()
+}
+
+// End returns the position of first character immediately after the node.
+func (s *IncDecStmt) End() Pos {
+ return Pos(int(s.TokenPos) + 2)
+}
+
+func (s *IncDecStmt) String() string {
+ return s.Expr.String() + s.Token.String()
+}
+
+// ReturnStmt represents a return statement.
+type ReturnStmt struct {
+ ReturnPos Pos
+ Result Expr
+}
+
+func (s *ReturnStmt) stmtNode() {}
+
+// Pos returns the position of first character belonging to the node.
+func (s *ReturnStmt) Pos() Pos {
+ return s.ReturnPos
+}
+
+// End returns the position of first character immediately after the node.
+func (s *ReturnStmt) End() Pos {
+ if s.Result != nil {
+ return s.Result.End()
+ }
+ return s.ReturnPos + 6
+}
+
+func (s *ReturnStmt) String() string {
+ if s.Result != nil {
+ return "return " + s.Result.String()
+ }
+ return "return"
+}
diff --git a/vendor/github.com/d5/tengo/v2/script.go b/vendor/github.com/d5/tengo/v2/script.go
new file mode 100644
index 00000000..906771d9
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/script.go
@@ -0,0 +1,313 @@
+package tengo
+
+import (
+ "context"
+ "fmt"
+ "sync"
+
+ "github.com/d5/tengo/v2/parser"
+)
+
+// Script can simplify compilation and execution of embedded scripts.
+type Script struct {
+ variables map[string]*Variable
+ modules *ModuleMap
+ input []byte
+ maxAllocs int64
+ maxConstObjects int
+ enableFileImport bool
+}
+
+// NewScript creates a Script instance with an input script.
+func NewScript(input []byte) *Script {
+ return &Script{
+ variables: make(map[string]*Variable),
+ input: input,
+ maxAllocs: -1,
+ maxConstObjects: -1,
+ }
+}
+
+// Add adds a new variable or updates an existing variable to the script.
+func (s *Script) Add(name string, value interface{}) error {
+ obj, err := FromInterface(value)
+ if err != nil {
+ return err
+ }
+ s.variables[name] = &Variable{
+ name: name,
+ value: obj,
+ }
+ return nil
+}
+
+// Remove removes (undefines) an existing variable for the script. It returns
+// false if the variable name is not defined.
+func (s *Script) Remove(name string) bool {
+ if _, ok := s.variables[name]; !ok {
+ return false
+ }
+ delete(s.variables, name)
+ return true
+}
+
+// SetImports sets import modules.
+func (s *Script) SetImports(modules *ModuleMap) {
+ s.modules = modules
+}
+
+// SetMaxAllocs sets the maximum number of objects allocations during the run
+// time. Compiled script will return ErrObjectAllocLimit error if it
+// exceeds this limit.
+func (s *Script) SetMaxAllocs(n int64) {
+ s.maxAllocs = n
+}
+
+// SetMaxConstObjects sets the maximum number of objects in the compiled
+// constants.
+func (s *Script) SetMaxConstObjects(n int) {
+ s.maxConstObjects = n
+}
+
+// EnableFileImport enables or disables module loading from local files. Local
+// file modules are disabled by default.
+func (s *Script) EnableFileImport(enable bool) {
+ s.enableFileImport = enable
+}
+
+// Compile compiles the script with all the defined variables, and, returns
+// Compiled object.
+func (s *Script) Compile() (*Compiled, error) {
+ symbolTable, globals, err := s.prepCompile()
+ if err != nil {
+ return nil, err
+ }
+
+ fileSet := parser.NewFileSet()
+ srcFile := fileSet.AddFile("(main)", -1, len(s.input))
+ p := parser.NewParser(srcFile, s.input, nil)
+ file, err := p.ParseFile()
+ if err != nil {
+ return nil, err
+ }
+
+ c := NewCompiler(srcFile, symbolTable, nil, s.modules, nil)
+ c.EnableFileImport(s.enableFileImport)
+ if err := c.Compile(file); err != nil {
+ return nil, err
+ }
+
+ // reduce globals size
+ globals = globals[:symbolTable.MaxSymbols()+1]
+
+ // global symbol names to indexes
+ globalIndexes := make(map[string]int, len(globals))
+ for _, name := range symbolTable.Names() {
+ symbol, _, _ := symbolTable.Resolve(name)
+ if symbol.Scope == ScopeGlobal {
+ globalIndexes[name] = symbol.Index
+ }
+ }
+
+ // remove duplicates from constants
+ bytecode := c.Bytecode()
+ bytecode.RemoveDuplicates()
+
+ // check the constant objects limit
+ if s.maxConstObjects >= 0 {
+ cnt := bytecode.CountObjects()
+ if cnt > s.maxConstObjects {
+ return nil, fmt.Errorf("exceeding constant objects limit: %d", cnt)
+ }
+ }
+ return &Compiled{
+ globalIndexes: globalIndexes,
+ bytecode: bytecode,
+ globals: globals,
+ maxAllocs: s.maxAllocs,
+ }, nil
+}
+
+// Run compiles and runs the scripts. Use returned compiled object to access
+// global variables.
+func (s *Script) Run() (compiled *Compiled, err error) {
+ compiled, err = s.Compile()
+ if err != nil {
+ return
+ }
+ err = compiled.Run()
+ return
+}
+
+// RunContext is like Run but includes a context.
+func (s *Script) RunContext(
+ ctx context.Context,
+) (compiled *Compiled, err error) {
+ compiled, err = s.Compile()
+ if err != nil {
+ return
+ }
+ err = compiled.RunContext(ctx)
+ return
+}
+
+func (s *Script) prepCompile() (
+ symbolTable *SymbolTable,
+ globals []Object,
+ err error,
+) {
+ var names []string
+ for name := range s.variables {
+ names = append(names, name)
+ }
+
+ symbolTable = NewSymbolTable()
+ for idx, fn := range builtinFuncs {
+ symbolTable.DefineBuiltin(idx, fn.Name)
+ }
+
+ globals = make([]Object, GlobalsSize)
+
+ for idx, name := range names {
+ symbol := symbolTable.Define(name)
+ if symbol.Index != idx {
+ panic(fmt.Errorf("wrong symbol index: %d != %d",
+ idx, symbol.Index))
+ }
+ globals[symbol.Index] = s.variables[name].value
+ }
+ return
+}
+
+// Compiled is a compiled instance of the user script. Use Script.Compile() to
+// create Compiled object.
+type Compiled struct {
+ globalIndexes map[string]int // global symbol name to index
+ bytecode *Bytecode
+ globals []Object
+ maxAllocs int64
+ lock sync.RWMutex
+}
+
+// Run executes the compiled script in the virtual machine.
+func (c *Compiled) Run() error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ v := NewVM(c.bytecode, c.globals, c.maxAllocs)
+ return v.Run()
+}
+
+// RunContext is like Run but includes a context.
+func (c *Compiled) RunContext(ctx context.Context) (err error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ v := NewVM(c.bytecode, c.globals, c.maxAllocs)
+ ch := make(chan error, 1)
+ go func() {
+ ch <- v.Run()
+ }()
+
+ select {
+ case <-ctx.Done():
+ v.Abort()
+ <-ch
+ err = ctx.Err()
+ case err = <-ch:
+ }
+ return
+}
+
+// Clone creates a new copy of Compiled. Cloned copies are safe for concurrent
+// use by multiple goroutines.
+func (c *Compiled) Clone() *Compiled {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ clone := &Compiled{
+ globalIndexes: c.globalIndexes,
+ bytecode: c.bytecode,
+ globals: make([]Object, len(c.globals)),
+ maxAllocs: c.maxAllocs,
+ }
+ // copy global objects
+ for idx, g := range c.globals {
+ if g != nil {
+ clone.globals[idx] = g
+ }
+ }
+ return clone
+}
+
+// IsDefined returns true if the variable name is defined (has value) before or
+// after the execution.
+func (c *Compiled) IsDefined(name string) bool {
+ c.lock.RLock()
+ defer c.lock.RUnlock()
+
+ idx, ok := c.globalIndexes[name]
+ if !ok {
+ return false
+ }
+ v := c.globals[idx]
+ if v == nil {
+ return false
+ }
+ return v != UndefinedValue
+}
+
+// Get returns a variable identified by the name.
+func (c *Compiled) Get(name string) *Variable {
+ c.lock.RLock()
+ defer c.lock.RUnlock()
+
+ value := UndefinedValue
+ if idx, ok := c.globalIndexes[name]; ok {
+ value = c.globals[idx]
+ if value == nil {
+ value = UndefinedValue
+ }
+ }
+ return &Variable{
+ name: name,
+ value: value,
+ }
+}
+
+// GetAll returns all the variables that are defined by the compiled script.
+func (c *Compiled) GetAll() []*Variable {
+ c.lock.RLock()
+ defer c.lock.RUnlock()
+
+ var vars []*Variable
+ for name, idx := range c.globalIndexes {
+ value := c.globals[idx]
+ if value == nil {
+ value = UndefinedValue
+ }
+ vars = append(vars, &Variable{
+ name: name,
+ value: value,
+ })
+ }
+ return vars
+}
+
+// Set replaces the value of a global variable identified by the name. An error
+// will be returned if the name was not defined during compilation.
+func (c *Compiled) Set(name string, value interface{}) error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ obj, err := FromInterface(value)
+ if err != nil {
+ return err
+ }
+ idx, ok := c.globalIndexes[name]
+ if !ok {
+ return fmt.Errorf("'%s' is not defined", name)
+ }
+ c.globals[idx] = obj
+ return nil
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/base64.go b/vendor/github.com/d5/tengo/v2/stdlib/base64.go
new file mode 100644
index 00000000..b4c5b56e
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/base64.go
@@ -0,0 +1,34 @@
+package stdlib
+
+import (
+ "encoding/base64"
+
+ "github.com/d5/tengo/v2"
+)
+
+var base64Module = map[string]tengo.Object{
+ "encode": &tengo.UserFunction{
+ Value: FuncAYRS(base64.StdEncoding.EncodeToString),
+ },
+ "decode": &tengo.UserFunction{
+ Value: FuncASRYE(base64.StdEncoding.DecodeString),
+ },
+ "raw_encode": &tengo.UserFunction{
+ Value: FuncAYRS(base64.RawStdEncoding.EncodeToString),
+ },
+ "raw_decode": &tengo.UserFunction{
+ Value: FuncASRYE(base64.RawStdEncoding.DecodeString),
+ },
+ "url_encode": &tengo.UserFunction{
+ Value: FuncAYRS(base64.URLEncoding.EncodeToString),
+ },
+ "url_decode": &tengo.UserFunction{
+ Value: FuncASRYE(base64.URLEncoding.DecodeString),
+ },
+ "raw_url_encode": &tengo.UserFunction{
+ Value: FuncAYRS(base64.RawURLEncoding.EncodeToString),
+ },
+ "raw_url_decode": &tengo.UserFunction{
+ Value: FuncASRYE(base64.RawURLEncoding.DecodeString),
+ },
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/builtin_modules.go b/vendor/github.com/d5/tengo/v2/stdlib/builtin_modules.go
new file mode 100644
index 00000000..cf0e9621
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/builtin_modules.go
@@ -0,0 +1,18 @@
+package stdlib
+
+import (
+ "github.com/d5/tengo/v2"
+)
+
+// BuiltinModules are builtin type standard library modules.
+var BuiltinModules = map[string]map[string]tengo.Object{
+ "math": mathModule,
+ "os": osModule,
+ "text": textModule,
+ "times": timesModule,
+ "rand": randModule,
+ "fmt": fmtModule,
+ "json": jsonModule,
+ "base64": base64Module,
+ "hex": hexModule,
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/errors.go b/vendor/github.com/d5/tengo/v2/stdlib/errors.go
new file mode 100644
index 00000000..ad83c6f8
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/errors.go
@@ -0,0 +1,12 @@
+package stdlib
+
+import (
+ "github.com/d5/tengo/v2"
+)
+
+func wrapError(err error) tengo.Object {
+ if err == nil {
+ return tengo.TrueValue
+ }
+ return &tengo.Error{Value: &tengo.String{Value: err.Error()}}
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/fmt.go b/vendor/github.com/d5/tengo/v2/stdlib/fmt.go
new file mode 100644
index 00000000..9945277f
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/fmt.go
@@ -0,0 +1,101 @@
+package stdlib
+
+import (
+ "fmt"
+
+ "github.com/d5/tengo/v2"
+)
+
+var fmtModule = map[string]tengo.Object{
+ "print": &tengo.UserFunction{Name: "print", Value: fmtPrint},
+ "printf": &tengo.UserFunction{Name: "printf", Value: fmtPrintf},
+ "println": &tengo.UserFunction{Name: "println", Value: fmtPrintln},
+ "sprintf": &tengo.UserFunction{Name: "sprintf", Value: fmtSprintf},
+}
+
+func fmtPrint(args ...tengo.Object) (ret tengo.Object, err error) {
+ printArgs, err := getPrintArgs(args...)
+ if err != nil {
+ return nil, err
+ }
+ _, _ = fmt.Print(printArgs...)
+ return nil, nil
+}
+
+func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
+ numArgs := len(args)
+ if numArgs == 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ format, ok := args[0].(*tengo.String)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "format",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ }
+ if numArgs == 1 {
+ fmt.Print(format)
+ return nil, nil
+ }
+
+ s, err := tengo.Format(format.Value, args[1:]...)
+ if err != nil {
+ return nil, err
+ }
+ fmt.Print(s)
+ return nil, nil
+}
+
+func fmtPrintln(args ...tengo.Object) (ret tengo.Object, err error) {
+ printArgs, err := getPrintArgs(args...)
+ if err != nil {
+ return nil, err
+ }
+ printArgs = append(printArgs, "\n")
+ _, _ = fmt.Print(printArgs...)
+ return nil, nil
+}
+
+func fmtSprintf(args ...tengo.Object) (ret tengo.Object, err error) {
+ numArgs := len(args)
+ if numArgs == 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ format, ok := args[0].(*tengo.String)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "format",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ }
+ if numArgs == 1 {
+ // okay to return 'format' directly as String is immutable
+ return format, nil
+ }
+ s, err := tengo.Format(format.Value, args[1:]...)
+ if err != nil {
+ return nil, err
+ }
+ return &tengo.String{Value: s}, nil
+}
+
+func getPrintArgs(args ...tengo.Object) ([]interface{}, error) {
+ var printArgs []interface{}
+ l := 0
+ for _, arg := range args {
+ s, _ := tengo.ToString(arg)
+ slen := len(s)
+ // make sure length does not exceed the limit
+ if l+slen > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ l += slen
+ printArgs = append(printArgs, s)
+ }
+ return printArgs, nil
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/func_typedefs.go b/vendor/github.com/d5/tengo/v2/stdlib/func_typedefs.go
new file mode 100644
index 00000000..fdac933c
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/func_typedefs.go
@@ -0,0 +1,1049 @@
+package stdlib
+
+import (
+ "fmt"
+
+ "github.com/d5/tengo/v2"
+)
+
+// FuncAR transform a function of 'func()' signature into CallableFunc type.
+func FuncAR(fn func()) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ fn()
+ return tengo.UndefinedValue, nil
+ }
+}
+
+// FuncARI transform a function of 'func() int' signature into CallableFunc
+// type.
+func FuncARI(fn func() int) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return &tengo.Int{Value: int64(fn())}, nil
+ }
+}
+
+// FuncARI64 transform a function of 'func() int64' signature into CallableFunc
+// type.
+func FuncARI64(fn func() int64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return &tengo.Int{Value: fn()}, nil
+ }
+}
+
+// FuncAI64RI64 transform a function of 'func(int64) int64' signature into
+// CallableFunc type.
+func FuncAI64RI64(fn func(int64) int64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return &tengo.Int{Value: fn(i1)}, nil
+ }
+}
+
+// FuncAI64R transform a function of 'func(int64)' signature into CallableFunc
+// type.
+func FuncAI64R(fn func(int64)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ fn(i1)
+ return tengo.UndefinedValue, nil
+ }
+}
+
+// FuncARB transform a function of 'func() bool' signature into CallableFunc
+// type.
+func FuncARB(fn func() bool) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ if fn() {
+ return tengo.TrueValue, nil
+ }
+ return tengo.FalseValue, nil
+ }
+}
+
+// FuncARE transform a function of 'func() error' signature into CallableFunc
+// type.
+func FuncARE(fn func() error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return wrapError(fn()), nil
+ }
+}
+
+// FuncARS transform a function of 'func() string' signature into CallableFunc
+// type.
+func FuncARS(fn func() string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s := fn()
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
+
+// FuncARSE transform a function of 'func() (string, error)' signature into
+// CallableFunc type.
+func FuncARSE(fn func() (string, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ res, err := fn()
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: res}, nil
+ }
+}
+
+// FuncARYE transform a function of 'func() ([]byte, error)' signature into
+// CallableFunc type.
+func FuncARYE(fn func() ([]byte, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ res, err := fn()
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(res) > tengo.MaxBytesLen {
+ return nil, tengo.ErrBytesLimit
+ }
+ return &tengo.Bytes{Value: res}, nil
+ }
+}
+
+// FuncARF transform a function of 'func() float64' signature into CallableFunc
+// type.
+func FuncARF(fn func() float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return &tengo.Float{Value: fn()}, nil
+ }
+}
+
+// FuncARSs transform a function of 'func() []string' signature into
+// CallableFunc type.
+func FuncARSs(fn func() []string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ arr := &tengo.Array{}
+ for _, elem := range fn() {
+ if len(elem) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: elem})
+ }
+ return arr, nil
+ }
+}
+
+// FuncARIsE transform a function of 'func() ([]int, error)' signature into
+// CallableFunc type.
+func FuncARIsE(fn func() ([]int, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ res, err := fn()
+ if err != nil {
+ return wrapError(err), nil
+ }
+ arr := &tengo.Array{}
+ for _, v := range res {
+ arr.Value = append(arr.Value, &tengo.Int{Value: int64(v)})
+ }
+ return arr, nil
+ }
+}
+
+// FuncAIRIs transform a function of 'func(int) []int' signature into
+// CallableFunc type.
+func FuncAIRIs(fn func(int) []int) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res := fn(i1)
+ arr := &tengo.Array{}
+ for _, v := range res {
+ arr.Value = append(arr.Value, &tengo.Int{Value: int64(v)})
+ }
+ return arr, nil
+ }
+}
+
+// FuncAFRF transform a function of 'func(float64) float64' signature into
+// CallableFunc type.
+func FuncAFRF(fn func(float64) float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return &tengo.Float{Value: fn(f1)}, nil
+ }
+}
+
+// FuncAIR transform a function of 'func(int)' signature into CallableFunc type.
+func FuncAIR(fn func(int)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ fn(i1)
+ return tengo.UndefinedValue, nil
+ }
+}
+
+// FuncAIRF transform a function of 'func(int) float64' signature into
+// CallableFunc type.
+func FuncAIRF(fn func(int) float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return &tengo.Float{Value: fn(i1)}, nil
+ }
+}
+
+// FuncAFRI transform a function of 'func(float64) int' signature into
+// CallableFunc type.
+func FuncAFRI(fn func(float64) int) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return &tengo.Int{Value: int64(fn(f1))}, nil
+ }
+}
+
+// FuncAFFRF transform a function of 'func(float64, float64) float64' signature
+// into CallableFunc type.
+func FuncAFFRF(fn func(float64, float64) float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ f2, ok := tengo.ToFloat64(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "float(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return &tengo.Float{Value: fn(f1, f2)}, nil
+ }
+}
+
+// FuncAIFRF transform a function of 'func(int, float64) float64' signature
+// into CallableFunc type.
+func FuncAIFRF(fn func(int, float64) float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ f2, ok := tengo.ToFloat64(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "float(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return &tengo.Float{Value: fn(i1, f2)}, nil
+ }
+}
+
+// FuncAFIRF transform a function of 'func(float64, int) float64' signature
+// into CallableFunc type.
+func FuncAFIRF(fn func(float64, int) float64) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return &tengo.Float{Value: fn(f1, i2)}, nil
+ }
+}
+
+// FuncAFIRB transform a function of 'func(float64, int) bool' signature
+// into CallableFunc type.
+func FuncAFIRB(fn func(float64, int) bool) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ if fn(f1, i2) {
+ return tengo.TrueValue, nil
+ }
+ return tengo.FalseValue, nil
+ }
+}
+
+// FuncAFRB transform a function of 'func(float64) bool' signature
+// into CallableFunc type.
+func FuncAFRB(fn func(float64) bool) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ f1, ok := tengo.ToFloat64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ if fn(f1) {
+ return tengo.TrueValue, nil
+ }
+ return tengo.FalseValue, nil
+ }
+}
+
+// FuncASRS transform a function of 'func(string) string' signature into
+// CallableFunc type. User function will return 'true' if underlying native
+// function returns nil.
+func FuncASRS(fn func(string) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s := fn(s1)
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
+
+// FuncASRSs transform a function of 'func(string) []string' signature into
+// CallableFunc type.
+func FuncASRSs(fn func(string) []string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res := fn(s1)
+ arr := &tengo.Array{}
+ for _, elem := range res {
+ if len(elem) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: elem})
+ }
+ return arr, nil
+ }
+}
+
+// FuncASRSE transform a function of 'func(string) (string, error)' signature
+// into CallableFunc type. User function will return 'true' if underlying
+// native function returns nil.
+func FuncASRSE(fn func(string) (string, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := fn(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: res}, nil
+ }
+}
+
+// FuncASRE transform a function of 'func(string) error' signature into
+// CallableFunc type. User function will return 'true' if underlying native
+// function returns nil.
+func FuncASRE(fn func(string) error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return wrapError(fn(s1)), nil
+ }
+}
+
+// FuncASSRE transform a function of 'func(string, string) error' signature
+// into CallableFunc type. User function will return 'true' if underlying
+// native function returns nil.
+func FuncASSRE(fn func(string, string) error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return wrapError(fn(s1, s2)), nil
+ }
+}
+
+// FuncASSRSs transform a function of 'func(string, string) []string'
+// signature into CallableFunc type.
+func FuncASSRSs(fn func(string, string) []string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ arr := &tengo.Array{}
+ for _, res := range fn(s1, s2) {
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: res})
+ }
+ return arr, nil
+ }
+}
+
+// FuncASSIRSs transform a function of 'func(string, string, int) []string'
+// signature into CallableFunc type.
+func FuncASSIRSs(fn func(string, string, int) []string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 3 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+ arr := &tengo.Array{}
+ for _, res := range fn(s1, s2, i3) {
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: res})
+ }
+ return arr, nil
+ }
+}
+
+// FuncASSRI transform a function of 'func(string, string) int' signature into
+// CallableFunc type.
+func FuncASSRI(fn func(string, string) int) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return &tengo.Int{Value: int64(fn(s1, s2))}, nil
+ }
+}
+
+// FuncASSRS transform a function of 'func(string, string) string' signature
+// into CallableFunc type.
+func FuncASSRS(fn func(string, string) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ s := fn(s1, s2)
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
+
+// FuncASSRB transform a function of 'func(string, string) bool' signature
+// into CallableFunc type.
+func FuncASSRB(fn func(string, string) bool) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ if fn(s1, s2) {
+ return tengo.TrueValue, nil
+ }
+ return tengo.FalseValue, nil
+ }
+}
+
+// FuncASsSRS transform a function of 'func([]string, string) string' signature
+// into CallableFunc type.
+func FuncASsSRS(fn func([]string, string) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ var ss1 []string
+ switch arg0 := args[0].(type) {
+ case *tengo.Array:
+ for idx, a := range arg0.Value {
+ as, ok := tengo.ToString(a)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("first[%d]", idx),
+ Expected: "string(compatible)",
+ Found: a.TypeName(),
+ }
+ }
+ ss1 = append(ss1, as)
+ }
+ case *tengo.ImmutableArray:
+ for idx, a := range arg0.Value {
+ as, ok := tengo.ToString(a)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("first[%d]", idx),
+ Expected: "string(compatible)",
+ Found: a.TypeName(),
+ }
+ }
+ ss1 = append(ss1, as)
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "array",
+ Found: args[0].TypeName(),
+ }
+ }
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ s := fn(ss1, s2)
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
+
+// FuncASI64RE transform a function of 'func(string, int64) error' signature
+// into CallableFunc type.
+func FuncASI64RE(fn func(string, int64) error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt64(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return wrapError(fn(s1, i2)), nil
+ }
+}
+
+// FuncAIIRE transform a function of 'func(int, int) error' signature
+// into CallableFunc type.
+func FuncAIIRE(fn func(int, int) error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return wrapError(fn(i1, i2)), nil
+ }
+}
+
+// FuncASIRS transform a function of 'func(string, int) string' signature
+// into CallableFunc type.
+func FuncASIRS(fn func(string, int) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ s := fn(s1, i2)
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
+
+// FuncASIIRE transform a function of 'func(string, int, int) error' signature
+// into CallableFunc type.
+func FuncASIIRE(fn func(string, int, int) error) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 3 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+ return wrapError(fn(s1, i2, i3)), nil
+ }
+}
+
+// FuncAYRIE transform a function of 'func([]byte) (int, error)' signature
+// into CallableFunc type.
+func FuncAYRIE(fn func([]byte) (int, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ y1, ok := tengo.ToByteSlice(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := fn(y1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return &tengo.Int{Value: int64(res)}, nil
+ }
+}
+
+// FuncAYRS transform a function of 'func([]byte) string' signature into
+// CallableFunc type.
+func FuncAYRS(fn func([]byte) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ y1, ok := tengo.ToByteSlice(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res := fn(y1)
+ return &tengo.String{Value: res}, nil
+ }
+}
+
+// FuncASRIE transform a function of 'func(string) (int, error)' signature
+// into CallableFunc type.
+func FuncASRIE(fn func(string) (int, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := fn(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return &tengo.Int{Value: int64(res)}, nil
+ }
+}
+
+// FuncASRYE transform a function of 'func(string) ([]byte, error)' signature
+// into CallableFunc type.
+func FuncASRYE(fn func(string) ([]byte, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := fn(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(res) > tengo.MaxBytesLen {
+ return nil, tengo.ErrBytesLimit
+ }
+ return &tengo.Bytes{Value: res}, nil
+ }
+}
+
+// FuncAIRSsE transform a function of 'func(int) ([]string, error)' signature
+// into CallableFunc type.
+func FuncAIRSsE(fn func(int) ([]string, error)) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := fn(i1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ arr := &tengo.Array{}
+ for _, r := range res {
+ if len(r) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: r})
+ }
+ return arr, nil
+ }
+}
+
+// FuncAIRS transform a function of 'func(int) string' signature into
+// CallableFunc type.
+func FuncAIRS(fn func(int) string) tengo.CallableFunc {
+ return func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ s := fn(i1)
+ if len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+ }
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/hex.go b/vendor/github.com/d5/tengo/v2/stdlib/hex.go
new file mode 100644
index 00000000..981da696
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/hex.go
@@ -0,0 +1,12 @@
+package stdlib
+
+import (
+ "encoding/hex"
+
+ "github.com/d5/tengo/v2"
+)
+
+var hexModule = map[string]tengo.Object{
+ "encode": &tengo.UserFunction{Value: FuncAYRS(hex.EncodeToString)},
+ "decode": &tengo.UserFunction{Value: FuncASRYE(hex.DecodeString)},
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/json.go b/vendor/github.com/d5/tengo/v2/stdlib/json.go
new file mode 100644
index 00000000..be2185db
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/json.go
@@ -0,0 +1,146 @@
+package stdlib
+
+import (
+ "bytes"
+ gojson "encoding/json"
+
+ "github.com/d5/tengo/v2"
+ "github.com/d5/tengo/v2/stdlib/json"
+)
+
+var jsonModule = map[string]tengo.Object{
+ "decode": &tengo.UserFunction{
+ Name: "decode",
+ Value: jsonDecode,
+ },
+ "encode": &tengo.UserFunction{
+ Name: "encode",
+ Value: jsonEncode,
+ },
+ "indent": &tengo.UserFunction{
+ Name: "encode",
+ Value: jsonIndent,
+ },
+ "html_escape": &tengo.UserFunction{
+ Name: "html_escape",
+ Value: jsonHTMLEscape,
+ },
+}
+
+func jsonDecode(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ switch o := args[0].(type) {
+ case *tengo.Bytes:
+ v, err := json.Decode(o.Value)
+ if err != nil {
+ return &tengo.Error{
+ Value: &tengo.String{Value: err.Error()},
+ }, nil
+ }
+ return v, nil
+ case *tengo.String:
+ v, err := json.Decode([]byte(o.Value))
+ if err != nil {
+ return &tengo.Error{
+ Value: &tengo.String{Value: err.Error()},
+ }, nil
+ }
+ return v, nil
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes/string",
+ Found: args[0].TypeName(),
+ }
+ }
+}
+
+func jsonEncode(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ b, err := json.Encode(args[0])
+ if err != nil {
+ return &tengo.Error{Value: &tengo.String{Value: err.Error()}}, nil
+ }
+
+ return &tengo.Bytes{Value: b}, nil
+}
+
+func jsonIndent(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 3 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ prefix, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "prefix",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+
+ indent, ok := tengo.ToString(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "indent",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+
+ switch o := args[0].(type) {
+ case *tengo.Bytes:
+ var dst bytes.Buffer
+ err := gojson.Indent(&dst, o.Value, prefix, indent)
+ if err != nil {
+ return &tengo.Error{
+ Value: &tengo.String{Value: err.Error()},
+ }, nil
+ }
+ return &tengo.Bytes{Value: dst.Bytes()}, nil
+ case *tengo.String:
+ var dst bytes.Buffer
+ err := gojson.Indent(&dst, []byte(o.Value), prefix, indent)
+ if err != nil {
+ return &tengo.Error{
+ Value: &tengo.String{Value: err.Error()},
+ }, nil
+ }
+ return &tengo.Bytes{Value: dst.Bytes()}, nil
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes/string",
+ Found: args[0].TypeName(),
+ }
+ }
+}
+
+func jsonHTMLEscape(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ switch o := args[0].(type) {
+ case *tengo.Bytes:
+ var dst bytes.Buffer
+ gojson.HTMLEscape(&dst, o.Value)
+ return &tengo.Bytes{Value: dst.Bytes()}, nil
+ case *tengo.String:
+ var dst bytes.Buffer
+ gojson.HTMLEscape(&dst, []byte(o.Value))
+ return &tengo.Bytes{Value: dst.Bytes()}, nil
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes/string",
+ Found: args[0].TypeName(),
+ }
+ }
+}
diff --git a/vendor/github.com/d5/tengo/stdlib/json/decode.go b/vendor/github.com/d5/tengo/v2/stdlib/json/decode.go
index 5a3fe6c7..6d468ef0 100644
--- a/vendor/github.com/d5/tengo/stdlib/json/decode.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/json/decode.go
@@ -12,21 +12,19 @@ import (
"unicode/utf16"
"unicode/utf8"
- "github.com/d5/tengo/objects"
+ "github.com/d5/tengo/v2"
)
// Decode parses the JSON-encoded data and returns the result object.
-func Decode(data []byte) (objects.Object, error) {
+func Decode(data []byte) (tengo.Object, error) {
var d decodeState
err := checkValid(data, &d.scan)
if err != nil {
return nil, err
}
-
d.init(data)
d.scan.reset()
d.scanWhile(scanSkipSpace)
-
return d.value()
}
@@ -80,45 +78,37 @@ func (d *decodeState) scanWhile(op int) {
d.opcode = d.scan.eof()
}
-func (d *decodeState) value() (objects.Object, error) {
+func (d *decodeState) value() (tengo.Object, error) {
switch d.opcode {
default:
panic(phasePanicMsg)
-
case scanBeginArray:
o, err := d.array()
if err != nil {
return nil, err
}
-
d.scanNext()
-
return o, nil
-
case scanBeginObject:
o, err := d.object()
if err != nil {
return nil, err
}
-
d.scanNext()
-
return o, nil
-
case scanBeginLiteral:
return d.literal()
}
}
-func (d *decodeState) array() (objects.Object, error) {
- var arr []objects.Object
+func (d *decodeState) array() (tengo.Object, error) {
+ var arr []tengo.Object
for {
// Look ahead for ] - can only happen on first iteration.
d.scanWhile(scanSkipSpace)
if d.opcode == scanEndArray {
break
}
-
o, err := d.value()
if err != nil {
return nil, err
@@ -136,12 +126,11 @@ func (d *decodeState) array() (objects.Object, error) {
panic(phasePanicMsg)
}
}
-
- return &objects.Array{Value: arr}, nil
+ return &tengo.Array{Value: arr}, nil
}
-func (d *decodeState) object() (objects.Object, error) {
- m := make(map[string]objects.Object)
+func (d *decodeState) object() (tengo.Object, error) {
+ m := make(map[string]tengo.Object)
for {
// Read opening " of string key or closing }.
d.scanWhile(scanSkipSpace)
@@ -190,11 +179,10 @@ func (d *decodeState) object() (objects.Object, error) {
panic(phasePanicMsg)
}
}
-
- return &objects.Map{Value: m}, nil
+ return &tengo.Map{Value: m}, nil
}
-func (d *decodeState) literal() (objects.Object, error) {
+func (d *decodeState) literal() (tengo.Object, error) {
// All bytes inside literal return scanContinue op code.
start := d.readIndex()
d.scanWhile(scanContinue)
@@ -203,28 +191,27 @@ func (d *decodeState) literal() (objects.Object, error) {
switch c := item[0]; c {
case 'n': // null
- return objects.UndefinedValue, nil
+ return tengo.UndefinedValue, nil
case 't', 'f': // true, false
if c == 't' {
- return objects.TrueValue, nil
+ return tengo.TrueValue, nil
}
- return objects.FalseValue, nil
+ return tengo.FalseValue, nil
case '"': // string
s, ok := unquote(item)
if !ok {
panic(phasePanicMsg)
}
- return &objects.String{Value: s}, nil
+ return &tengo.String{Value: s}, nil
default: // number
if c != '-' && (c < '0' || c > '9') {
panic(phasePanicMsg)
}
-
n, _ := strconv.ParseFloat(string(item), 10)
- return &objects.Float{Value: n}, nil
+ return &tengo.Float{Value: n}, nil
}
}
@@ -265,9 +252,8 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
}
s = s[1 : len(s)-1]
- // Check for unusual characters. If there are none,
- // then no unquoting is needed, so return a slice of the
- // original bytes.
+ // Check for unusual characters. If there are none, then no unquoting is
+ // needed, so return a slice of the original bytes.
r := 0
for r < len(s) {
c := s[r]
@@ -341,7 +327,8 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
r += 6
if utf16.IsSurrogate(rr) {
rr1 := getu4(s[r:])
- if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ dec := utf16.DecodeRune(rr, rr1)
+ if dec != unicode.ReplacementChar {
// A valid pair; consume.
r += 6
w += utf8.EncodeRune(b[w:], dec)
@@ -352,17 +339,14 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
}
w += utf8.EncodeRune(b[w:], rr)
}
-
// Quote, control characters are invalid.
case c == '"', c < ' ':
return
-
// ASCII
case c < utf8.RuneSelf:
b[w] = c
r++
w++
-
// Coerce to well-formed UTF-8.
default:
rr, size := utf8.DecodeRune(s[r:])
diff --git a/vendor/github.com/d5/tengo/stdlib/json/encode.go b/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go
index 2b8b17eb..ab7ca6ff 100644
--- a/vendor/github.com/d5/tengo/stdlib/json/encode.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go
@@ -12,15 +12,15 @@ import (
"math"
"strconv"
- "github.com/d5/tengo/objects"
+ "github.com/d5/tengo/v2"
)
// Encode returns the JSON encoding of the object.
-func Encode(o objects.Object) ([]byte, error) {
+func Encode(o tengo.Object) ([]byte, error) {
var b []byte
switch o := o.(type) {
- case *objects.Array:
+ case *tengo.Array:
b = append(b, '[')
len1 := len(o.Value) - 1
for idx, elem := range o.Value {
@@ -34,7 +34,7 @@ func Encode(o objects.Object) ([]byte, error) {
}
}
b = append(b, ']')
- case *objects.ImmutableArray:
+ case *tengo.ImmutableArray:
b = append(b, '[')
len1 := len(o.Value) - 1
for idx, elem := range o.Value {
@@ -48,7 +48,7 @@ func Encode(o objects.Object) ([]byte, error) {
}
}
b = append(b, ']')
- case *objects.Map:
+ case *tengo.Map:
b = append(b, '{')
len1 := len(o.Value) - 1
idx := 0
@@ -66,7 +66,7 @@ func Encode(o objects.Object) ([]byte, error) {
idx++
}
b = append(b, '}')
- case *objects.ImmutableMap:
+ case *tengo.ImmutableMap:
b = append(b, '{')
len1 := len(o.Value) - 1
idx := 0
@@ -84,22 +84,22 @@ func Encode(o objects.Object) ([]byte, error) {
idx++
}
b = append(b, '}')
- case *objects.Bool:
+ case *tengo.Bool:
if o.IsFalsy() {
b = strconv.AppendBool(b, false)
} else {
b = strconv.AppendBool(b, true)
}
- case *objects.Bytes:
+ case *tengo.Bytes:
b = append(b, '"')
encodedLen := base64.StdEncoding.EncodedLen(len(o.Value))
dst := make([]byte, encodedLen)
base64.StdEncoding.Encode(dst, o.Value)
b = append(b, dst...)
b = append(b, '"')
- case *objects.Char:
+ case *tengo.Char:
b = strconv.AppendInt(b, int64(o.Value), 10)
- case *objects.Float:
+ case *tengo.Float:
var y []byte
f := o.Value
@@ -127,21 +127,20 @@ func Encode(o objects.Object) ([]byte, error) {
}
b = append(b, y...)
- case *objects.Int:
+ case *tengo.Int:
b = strconv.AppendInt(b, o.Value, 10)
- case *objects.String:
+ case *tengo.String:
b = strconv.AppendQuote(b, o.Value)
- case *objects.Time:
+ case *tengo.Time:
y, err := o.Value.MarshalJSON()
if err != nil {
return nil, err
}
b = append(b, y...)
- case *objects.Undefined:
+ case *tengo.Undefined:
b = append(b, "null"...)
default:
// unknown type: ignore
}
-
return b, nil
}
diff --git a/vendor/github.com/d5/tengo/stdlib/json/scanner.go b/vendor/github.com/d5/tengo/v2/stdlib/json/scanner.go
index 8fc6776d..aed15cf5 100644
--- a/vendor/github.com/d5/tengo/stdlib/json/scanner.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/json/scanner.go
@@ -532,14 +532,17 @@ func stateNul(s *scanner, c byte) int {
// stateError is the state after reaching a syntax error,
// such as after reading `[1}` or `5.1.2`.
-func stateError(s *scanner, c byte) int {
+func stateError(_ *scanner, _ byte) int {
return scanError
}
// error records an error and switches to the error state.
func (s *scanner) error(c byte, context string) int {
s.step = stateError
- s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
+ s.err = &SyntaxError{
+ msg: "invalid character " + quoteChar(c) + " " + context,
+ Offset: s.bytes,
+ }
return scanError
}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/math.go b/vendor/github.com/d5/tengo/v2/stdlib/math.go
new file mode 100644
index 00000000..633ea09f
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/math.go
@@ -0,0 +1,233 @@
+package stdlib
+
+import (
+ "math"
+
+ "github.com/d5/tengo/v2"
+)
+
+var mathModule = map[string]tengo.Object{
+ "e": &tengo.Float{Value: math.E},
+ "pi": &tengo.Float{Value: math.Pi},
+ "phi": &tengo.Float{Value: math.Phi},
+ "sqrt2": &tengo.Float{Value: math.Sqrt2},
+ "sqrtE": &tengo.Float{Value: math.SqrtE},
+ "sqrtPi": &tengo.Float{Value: math.SqrtPi},
+ "sqrtPhi": &tengo.Float{Value: math.SqrtPhi},
+ "ln2": &tengo.Float{Value: math.Ln2},
+ "log2E": &tengo.Float{Value: math.Log2E},
+ "ln10": &tengo.Float{Value: math.Ln10},
+ "log10E": &tengo.Float{Value: math.Log10E},
+ "abs": &tengo.UserFunction{
+ Name: "abs",
+ Value: FuncAFRF(math.Abs),
+ },
+ "acos": &tengo.UserFunction{
+ Name: "acos",
+ Value: FuncAFRF(math.Acos),
+ },
+ "acosh": &tengo.UserFunction{
+ Name: "acosh",
+ Value: FuncAFRF(math.Acosh),
+ },
+ "asin": &tengo.UserFunction{
+ Name: "asin",
+ Value: FuncAFRF(math.Asin),
+ },
+ "asinh": &tengo.UserFunction{
+ Name: "asinh",
+ Value: FuncAFRF(math.Asinh),
+ },
+ "atan": &tengo.UserFunction{
+ Name: "atan",
+ Value: FuncAFRF(math.Atan),
+ },
+ "atan2": &tengo.UserFunction{
+ Name: "atan2",
+ Value: FuncAFFRF(math.Atan2),
+ },
+ "atanh": &tengo.UserFunction{
+ Name: "atanh",
+ Value: FuncAFRF(math.Atanh),
+ },
+ "cbrt": &tengo.UserFunction{
+ Name: "cbrt",
+ Value: FuncAFRF(math.Cbrt),
+ },
+ "ceil": &tengo.UserFunction{
+ Name: "ceil",
+ Value: FuncAFRF(math.Ceil),
+ },
+ "copysign": &tengo.UserFunction{
+ Name: "copysign",
+ Value: FuncAFFRF(math.Copysign),
+ },
+ "cos": &tengo.UserFunction{
+ Name: "cos",
+ Value: FuncAFRF(math.Cos),
+ },
+ "cosh": &tengo.UserFunction{
+ Name: "cosh",
+ Value: FuncAFRF(math.Cosh),
+ },
+ "dim": &tengo.UserFunction{
+ Name: "dim",
+ Value: FuncAFFRF(math.Dim),
+ },
+ "erf": &tengo.UserFunction{
+ Name: "erf",
+ Value: FuncAFRF(math.Erf),
+ },
+ "erfc": &tengo.UserFunction{
+ Name: "erfc",
+ Value: FuncAFRF(math.Erfc),
+ },
+ "exp": &tengo.UserFunction{
+ Name: "exp",
+ Value: FuncAFRF(math.Exp),
+ },
+ "exp2": &tengo.UserFunction{
+ Name: "exp2",
+ Value: FuncAFRF(math.Exp2),
+ },
+ "expm1": &tengo.UserFunction{
+ Name: "expm1",
+ Value: FuncAFRF(math.Expm1),
+ },
+ "floor": &tengo.UserFunction{
+ Name: "floor",
+ Value: FuncAFRF(math.Floor),
+ },
+ "gamma": &tengo.UserFunction{
+ Name: "gamma",
+ Value: FuncAFRF(math.Gamma),
+ },
+ "hypot": &tengo.UserFunction{
+ Name: "hypot",
+ Value: FuncAFFRF(math.Hypot),
+ },
+ "ilogb": &tengo.UserFunction{
+ Name: "ilogb",
+ Value: FuncAFRI(math.Ilogb),
+ },
+ "inf": &tengo.UserFunction{
+ Name: "inf",
+ Value: FuncAIRF(math.Inf),
+ },
+ "is_inf": &tengo.UserFunction{
+ Name: "is_inf",
+ Value: FuncAFIRB(math.IsInf),
+ },
+ "is_nan": &tengo.UserFunction{
+ Name: "is_nan",
+ Value: FuncAFRB(math.IsNaN),
+ },
+ "j0": &tengo.UserFunction{
+ Name: "j0",
+ Value: FuncAFRF(math.J0),
+ },
+ "j1": &tengo.UserFunction{
+ Name: "j1",
+ Value: FuncAFRF(math.J1),
+ },
+ "jn": &tengo.UserFunction{
+ Name: "jn",
+ Value: FuncAIFRF(math.Jn),
+ },
+ "ldexp": &tengo.UserFunction{
+ Name: "ldexp",
+ Value: FuncAFIRF(math.Ldexp),
+ },
+ "log": &tengo.UserFunction{
+ Name: "log",
+ Value: FuncAFRF(math.Log),
+ },
+ "log10": &tengo.UserFunction{
+ Name: "log10",
+ Value: FuncAFRF(math.Log10),
+ },
+ "log1p": &tengo.UserFunction{
+ Name: "log1p",
+ Value: FuncAFRF(math.Log1p),
+ },
+ "log2": &tengo.UserFunction{
+ Name: "log2",
+ Value: FuncAFRF(math.Log2),
+ },
+ "logb": &tengo.UserFunction{
+ Name: "logb",
+ Value: FuncAFRF(math.Logb),
+ },
+ "max": &tengo.UserFunction{
+ Name: "max",
+ Value: FuncAFFRF(math.Max),
+ },
+ "min": &tengo.UserFunction{
+ Name: "min",
+ Value: FuncAFFRF(math.Min),
+ },
+ "mod": &tengo.UserFunction{
+ Name: "mod",
+ Value: FuncAFFRF(math.Mod),
+ },
+ "nan": &tengo.UserFunction{
+ Name: "nan",
+ Value: FuncARF(math.NaN),
+ },
+ "nextafter": &tengo.UserFunction{
+ Name: "nextafter",
+ Value: FuncAFFRF(math.Nextafter),
+ },
+ "pow": &tengo.UserFunction{
+ Name: "pow",
+ Value: FuncAFFRF(math.Pow),
+ },
+ "pow10": &tengo.UserFunction{
+ Name: "pow10",
+ Value: FuncAIRF(math.Pow10),
+ },
+ "remainder": &tengo.UserFunction{
+ Name: "remainder",
+ Value: FuncAFFRF(math.Remainder),
+ },
+ "signbit": &tengo.UserFunction{
+ Name: "signbit",
+ Value: FuncAFRB(math.Signbit),
+ },
+ "sin": &tengo.UserFunction{
+ Name: "sin",
+ Value: FuncAFRF(math.Sin),
+ },
+ "sinh": &tengo.UserFunction{
+ Name: "sinh",
+ Value: FuncAFRF(math.Sinh),
+ },
+ "sqrt": &tengo.UserFunction{
+ Name: "sqrt",
+ Value: FuncAFRF(math.Sqrt),
+ },
+ "tan": &tengo.UserFunction{
+ Name: "tan",
+ Value: FuncAFRF(math.Tan),
+ },
+ "tanh": &tengo.UserFunction{
+ Name: "tanh",
+ Value: FuncAFRF(math.Tanh),
+ },
+ "trunc": &tengo.UserFunction{
+ Name: "trunc",
+ Value: FuncAFRF(math.Trunc),
+ },
+ "y0": &tengo.UserFunction{
+ Name: "y0",
+ Value: FuncAFRF(math.Y0),
+ },
+ "y1": &tengo.UserFunction{
+ Name: "y1",
+ Value: FuncAFRF(math.Y1),
+ },
+ "yn": &tengo.UserFunction{
+ Name: "yn",
+ Value: FuncAIFRF(math.Yn),
+ },
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/os.go b/vendor/github.com/d5/tengo/v2/stdlib/os.go
new file mode 100644
index 00000000..576bc94b
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/os.go
@@ -0,0 +1,564 @@
+package stdlib
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+
+ "github.com/d5/tengo/v2"
+)
+
+var osModule = map[string]tengo.Object{
+ "o_rdonly": &tengo.Int{Value: int64(os.O_RDONLY)},
+ "o_wronly": &tengo.Int{Value: int64(os.O_WRONLY)},
+ "o_rdwr": &tengo.Int{Value: int64(os.O_RDWR)},
+ "o_append": &tengo.Int{Value: int64(os.O_APPEND)},
+ "o_create": &tengo.Int{Value: int64(os.O_CREATE)},
+ "o_excl": &tengo.Int{Value: int64(os.O_EXCL)},
+ "o_sync": &tengo.Int{Value: int64(os.O_SYNC)},
+ "o_trunc": &tengo.Int{Value: int64(os.O_TRUNC)},
+ "mode_dir": &tengo.Int{Value: int64(os.ModeDir)},
+ "mode_append": &tengo.Int{Value: int64(os.ModeAppend)},
+ "mode_exclusive": &tengo.Int{Value: int64(os.ModeExclusive)},
+ "mode_temporary": &tengo.Int{Value: int64(os.ModeTemporary)},
+ "mode_symlink": &tengo.Int{Value: int64(os.ModeSymlink)},
+ "mode_device": &tengo.Int{Value: int64(os.ModeDevice)},
+ "mode_named_pipe": &tengo.Int{Value: int64(os.ModeNamedPipe)},
+ "mode_socket": &tengo.Int{Value: int64(os.ModeSocket)},
+ "mode_setuid": &tengo.Int{Value: int64(os.ModeSetuid)},
+ "mode_setgui": &tengo.Int{Value: int64(os.ModeSetgid)},
+ "mode_char_device": &tengo.Int{Value: int64(os.ModeCharDevice)},
+ "mode_sticky": &tengo.Int{Value: int64(os.ModeSticky)},
+ "mode_type": &tengo.Int{Value: int64(os.ModeType)},
+ "mode_perm": &tengo.Int{Value: int64(os.ModePerm)},
+ "path_separator": &tengo.Char{Value: os.PathSeparator},
+ "path_list_separator": &tengo.Char{Value: os.PathListSeparator},
+ "dev_null": &tengo.String{Value: os.DevNull},
+ "seek_set": &tengo.Int{Value: int64(io.SeekStart)},
+ "seek_cur": &tengo.Int{Value: int64(io.SeekCurrent)},
+ "seek_end": &tengo.Int{Value: int64(io.SeekEnd)},
+ "args": &tengo.UserFunction{
+ Name: "args",
+ Value: osArgs,
+ }, // args() => array(string)
+ "chdir": &tengo.UserFunction{
+ Name: "chdir",
+ Value: FuncASRE(os.Chdir),
+ }, // chdir(dir string) => error
+ "chmod": osFuncASFmRE("chmod", os.Chmod), // chmod(name string, mode int) => error
+ "chown": &tengo.UserFunction{
+ Name: "chown",
+ Value: FuncASIIRE(os.Chown),
+ }, // chown(name string, uid int, gid int) => error
+ "clearenv": &tengo.UserFunction{
+ Name: "clearenv",
+ Value: FuncAR(os.Clearenv),
+ }, // clearenv()
+ "environ": &tengo.UserFunction{
+ Name: "environ",
+ Value: FuncARSs(os.Environ),
+ }, // environ() => array(string)
+ "exit": &tengo.UserFunction{
+ Name: "exit",
+ Value: FuncAIR(os.Exit),
+ }, // exit(code int)
+ "expand_env": &tengo.UserFunction{
+ Name: "expand_env",
+ Value: osExpandEnv,
+ }, // expand_env(s string) => string
+ "getegid": &tengo.UserFunction{
+ Name: "getegid",
+ Value: FuncARI(os.Getegid),
+ }, // getegid() => int
+ "getenv": &tengo.UserFunction{
+ Name: "getenv",
+ Value: FuncASRS(os.Getenv),
+ }, // getenv(s string) => string
+ "geteuid": &tengo.UserFunction{
+ Name: "geteuid",
+ Value: FuncARI(os.Geteuid),
+ }, // geteuid() => int
+ "getgid": &tengo.UserFunction{
+ Name: "getgid",
+ Value: FuncARI(os.Getgid),
+ }, // getgid() => int
+ "getgroups": &tengo.UserFunction{
+ Name: "getgroups",
+ Value: FuncARIsE(os.Getgroups),
+ }, // getgroups() => array(string)/error
+ "getpagesize": &tengo.UserFunction{
+ Name: "getpagesize",
+ Value: FuncARI(os.Getpagesize),
+ }, // getpagesize() => int
+ "getpid": &tengo.UserFunction{
+ Name: "getpid",
+ Value: FuncARI(os.Getpid),
+ }, // getpid() => int
+ "getppid": &tengo.UserFunction{
+ Name: "getppid",
+ Value: FuncARI(os.Getppid),
+ }, // getppid() => int
+ "getuid": &tengo.UserFunction{
+ Name: "getuid",
+ Value: FuncARI(os.Getuid),
+ }, // getuid() => int
+ "getwd": &tengo.UserFunction{
+ Name: "getwd",
+ Value: FuncARSE(os.Getwd),
+ }, // getwd() => string/error
+ "hostname": &tengo.UserFunction{
+ Name: "hostname",
+ Value: FuncARSE(os.Hostname),
+ }, // hostname() => string/error
+ "lchown": &tengo.UserFunction{
+ Name: "lchown",
+ Value: FuncASIIRE(os.Lchown),
+ }, // lchown(name string, uid int, gid int) => error
+ "link": &tengo.UserFunction{
+ Name: "link",
+ Value: FuncASSRE(os.Link),
+ }, // link(oldname string, newname string) => error
+ "lookup_env": &tengo.UserFunction{
+ Name: "lookup_env",
+ Value: osLookupEnv,
+ }, // lookup_env(key string) => string/false
+ "mkdir": osFuncASFmRE("mkdir", os.Mkdir), // mkdir(name string, perm int) => error
+ "mkdir_all": osFuncASFmRE("mkdir_all", os.MkdirAll), // mkdir_all(name string, perm int) => error
+ "readlink": &tengo.UserFunction{
+ Name: "readlink",
+ Value: FuncASRSE(os.Readlink),
+ }, // readlink(name string) => string/error
+ "remove": &tengo.UserFunction{
+ Name: "remove",
+ Value: FuncASRE(os.Remove),
+ }, // remove(name string) => error
+ "remove_all": &tengo.UserFunction{
+ Name: "remove_all",
+ Value: FuncASRE(os.RemoveAll),
+ }, // remove_all(name string) => error
+ "rename": &tengo.UserFunction{
+ Name: "rename",
+ Value: FuncASSRE(os.Rename),
+ }, // rename(oldpath string, newpath string) => error
+ "setenv": &tengo.UserFunction{
+ Name: "setenv",
+ Value: FuncASSRE(os.Setenv),
+ }, // setenv(key string, value string) => error
+ "symlink": &tengo.UserFunction{
+ Name: "symlink",
+ Value: FuncASSRE(os.Symlink),
+ }, // symlink(oldname string newname string) => error
+ "temp_dir": &tengo.UserFunction{
+ Name: "temp_dir",
+ Value: FuncARS(os.TempDir),
+ }, // temp_dir() => string
+ "truncate": &tengo.UserFunction{
+ Name: "truncate",
+ Value: FuncASI64RE(os.Truncate),
+ }, // truncate(name string, size int) => error
+ "unsetenv": &tengo.UserFunction{
+ Name: "unsetenv",
+ Value: FuncASRE(os.Unsetenv),
+ }, // unsetenv(key string) => error
+ "create": &tengo.UserFunction{
+ Name: "create",
+ Value: osCreate,
+ }, // create(name string) => imap(file)/error
+ "open": &tengo.UserFunction{
+ Name: "open",
+ Value: osOpen,
+ }, // open(name string) => imap(file)/error
+ "open_file": &tengo.UserFunction{
+ Name: "open_file",
+ Value: osOpenFile,
+ }, // open_file(name string, flag int, perm int) => imap(file)/error
+ "find_process": &tengo.UserFunction{
+ Name: "find_process",
+ Value: osFindProcess,
+ }, // find_process(pid int) => imap(process)/error
+ "start_process": &tengo.UserFunction{
+ Name: "start_process",
+ Value: osStartProcess,
+ }, // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
+ "exec_look_path": &tengo.UserFunction{
+ Name: "exec_look_path",
+ Value: FuncASRSE(exec.LookPath),
+ }, // exec_look_path(file) => string/error
+ "exec": &tengo.UserFunction{
+ Name: "exec",
+ Value: osExec,
+ }, // exec(name, args...) => command
+ "stat": &tengo.UserFunction{
+ Name: "stat",
+ Value: osStat,
+ }, // stat(name) => imap(fileinfo)/error
+ "read_file": &tengo.UserFunction{
+ Name: "read_file",
+ Value: osReadFile,
+ }, // readfile(name) => array(byte)/error
+}
+
+func osReadFile(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ fname, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ bytes, err := ioutil.ReadFile(fname)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ if len(bytes) > tengo.MaxBytesLen {
+ return nil, tengo.ErrBytesLimit
+ }
+ return &tengo.Bytes{Value: bytes}, nil
+}
+
+func osStat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ fname, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ stat, err := os.Stat(fname)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ fstat := &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "name": &tengo.String{Value: stat.Name()},
+ "mtime": &tengo.Time{Value: stat.ModTime()},
+ "size": &tengo.Int{Value: stat.Size()},
+ "mode": &tengo.Int{Value: int64(stat.Mode())},
+ },
+ }
+ if stat.IsDir() {
+ fstat.Value["directory"] = tengo.TrueValue
+ } else {
+ fstat.Value["directory"] = tengo.FalseValue
+ }
+ return fstat, nil
+}
+
+func osCreate(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := os.Create(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osOpen(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := os.Open(s1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osOpenFile(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 3 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+ res, err := os.OpenFile(s1, i2, os.FileMode(i3))
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSFile(res), nil
+}
+
+func osArgs(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ arr := &tengo.Array{}
+ for _, osArg := range os.Args {
+ if len(osArg) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ arr.Value = append(arr.Value, &tengo.String{Value: osArg})
+ }
+ return arr, nil
+}
+
+func osFuncASFmRE(
+ name string,
+ fn func(string, os.FileMode) error,
+) *tengo.UserFunction {
+ return &tengo.UserFunction{
+ Name: name,
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt64(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ return wrapError(fn(s1, os.FileMode(i2))), nil
+ },
+ }
+}
+
+func osLookupEnv(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, ok := os.LookupEnv(s1)
+ if !ok {
+ return tengo.FalseValue, nil
+ }
+ if len(res) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: res}, nil
+}
+
+func osExpandEnv(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var vlen int
+ var failed bool
+ s := os.Expand(s1, func(k string) string {
+ if failed {
+ return ""
+ }
+ v := os.Getenv(k)
+
+ // this does not count the other texts that are not being replaced
+ // but the code checks the final length at the end
+ vlen += len(v)
+ if vlen > tengo.MaxStringLen {
+ failed = true
+ return ""
+ }
+ return v
+ })
+ if failed || len(s) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+ return &tengo.String{Value: s}, nil
+}
+
+func osExec(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) == 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ name, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var execArgs []string
+ for idx, arg := range args[1:] {
+ execArg, ok := tengo.ToString(arg)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("args[%d]", idx),
+ Expected: "string(compatible)",
+ Found: args[1+idx].TypeName(),
+ }
+ }
+ execArgs = append(execArgs, execArg)
+ }
+ return makeOSExecCommand(exec.Command(name, execArgs...)), nil
+}
+
+func osFindProcess(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ proc, err := os.FindProcess(i1)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSProcess(proc), nil
+}
+
+func osStartProcess(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 4 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ name, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ var argv []string
+ var err error
+ switch arg1 := args[1].(type) {
+ case *tengo.Array:
+ argv, err = stringArray(arg1.Value, "second")
+ if err != nil {
+ return nil, err
+ }
+ case *tengo.ImmutableArray:
+ argv, err = stringArray(arg1.Value, "second")
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "array",
+ Found: arg1.TypeName(),
+ }
+ }
+
+ dir, ok := tengo.ToString(args[2])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ }
+
+ var env []string
+ switch arg3 := args[3].(type) {
+ case *tengo.Array:
+ env, err = stringArray(arg3.Value, "fourth")
+ if err != nil {
+ return nil, err
+ }
+ case *tengo.ImmutableArray:
+ env, err = stringArray(arg3.Value, "fourth")
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "array",
+ Found: arg3.TypeName(),
+ }
+ }
+
+ proc, err := os.StartProcess(name, argv, &os.ProcAttr{
+ Dir: dir,
+ Env: env,
+ })
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSProcess(proc), nil
+}
+
+func stringArray(arr []tengo.Object, argName string) ([]string, error) {
+ var sarr []string
+ for idx, elem := range arr {
+ str, ok := elem.(*tengo.String)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("%s[%d]", argName, idx),
+ Expected: "string",
+ Found: elem.TypeName(),
+ }
+ }
+ sarr = append(sarr, str.Value)
+ }
+ return sarr, nil
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/os_exec.go b/vendor/github.com/d5/tengo/v2/stdlib/os_exec.go
new file mode 100644
index 00000000..7ee5c1cd
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/os_exec.go
@@ -0,0 +1,119 @@
+package stdlib
+
+import (
+ "os/exec"
+
+ "github.com/d5/tengo/v2"
+)
+
+func makeOSExecCommand(cmd *exec.Cmd) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ // combined_output() => bytes/error
+ "combined_output": &tengo.UserFunction{
+ Name: "combined_output",
+ Value: FuncARYE(cmd.CombinedOutput),
+ },
+ // output() => bytes/error
+ "output": &tengo.UserFunction{
+ Name: "output",
+ Value: FuncARYE(cmd.Output),
+ }, //
+ // run() => error
+ "run": &tengo.UserFunction{
+ Name: "run",
+ Value: FuncARE(cmd.Run),
+ }, //
+ // start() => error
+ "start": &tengo.UserFunction{
+ Name: "start",
+ Value: FuncARE(cmd.Start),
+ }, //
+ // wait() => error
+ "wait": &tengo.UserFunction{
+ Name: "wait",
+ Value: FuncARE(cmd.Wait),
+ }, //
+ // set_path(path string)
+ "set_path": &tengo.UserFunction{
+ Name: "set_path",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ cmd.Path = s1
+ return tengo.UndefinedValue, nil
+ },
+ },
+ // set_dir(dir string)
+ "set_dir": &tengo.UserFunction{
+ Name: "set_dir",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ cmd.Dir = s1
+ return tengo.UndefinedValue, nil
+ },
+ },
+ // set_env(env array(string))
+ "set_env": &tengo.UserFunction{
+ Name: "set_env",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ var env []string
+ var err error
+ switch arg0 := args[0].(type) {
+ case *tengo.Array:
+ env, err = stringArray(arg0.Value, "first")
+ if err != nil {
+ return nil, err
+ }
+ case *tengo.ImmutableArray:
+ env, err = stringArray(arg0.Value, "first")
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "array",
+ Found: arg0.TypeName(),
+ }
+ }
+ cmd.Env = env
+ return tengo.UndefinedValue, nil
+ },
+ },
+ // process() => imap(process)
+ "process": &tengo.UserFunction{
+ Name: "process",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return makeOSProcess(cmd.Process), nil
+ },
+ },
+ },
+ }
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/os_file.go b/vendor/github.com/d5/tengo/v2/stdlib/os_file.go
new file mode 100644
index 00000000..4f59b4c4
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/os_file.go
@@ -0,0 +1,117 @@
+package stdlib
+
+import (
+ "os"
+
+ "github.com/d5/tengo/v2"
+)
+
+func makeOSFile(file *os.File) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ // chdir() => true/error
+ "chdir": &tengo.UserFunction{
+ Name: "chdir",
+ Value: FuncARE(file.Chdir),
+ }, //
+ // chown(uid int, gid int) => true/error
+ "chown": &tengo.UserFunction{
+ Name: "chown",
+ Value: FuncAIIRE(file.Chown),
+ }, //
+ // close() => error
+ "close": &tengo.UserFunction{
+ Name: "close",
+ Value: FuncARE(file.Close),
+ }, //
+ // name() => string
+ "name": &tengo.UserFunction{
+ Name: "name",
+ Value: FuncARS(file.Name),
+ }, //
+ // readdirnames(n int) => array(string)/error
+ "readdirnames": &tengo.UserFunction{
+ Name: "readdirnames",
+ Value: FuncAIRSsE(file.Readdirnames),
+ }, //
+ // sync() => error
+ "sync": &tengo.UserFunction{
+ Name: "sync",
+ Value: FuncARE(file.Sync),
+ }, //
+ // write(bytes) => int/error
+ "write": &tengo.UserFunction{
+ Name: "write",
+ Value: FuncAYRIE(file.Write),
+ }, //
+ // write(string) => int/error
+ "write_string": &tengo.UserFunction{
+ Name: "write_string",
+ Value: FuncASRIE(file.WriteString),
+ }, //
+ // read(bytes) => int/error
+ "read": &tengo.UserFunction{
+ Name: "read",
+ Value: FuncAYRIE(file.Read),
+ }, //
+ // chmod(mode int) => error
+ "chmod": &tengo.UserFunction{
+ Name: "chmod",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return wrapError(file.Chmod(os.FileMode(i1))), nil
+ },
+ },
+ // seek(offset int, whence int) => int/error
+ "seek": &tengo.UserFunction{
+ Name: "seek",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+ res, err := file.Seek(i1, i2)
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return &tengo.Int{Value: res}, nil
+ },
+ },
+ // stat() => imap(fileinfo)/error
+ "stat": &tengo.UserFunction{
+ Name: "stat",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ return osStat(&tengo.String{Value: file.Name()})
+ },
+ },
+ },
+ }
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/os_process.go b/vendor/github.com/d5/tengo/v2/stdlib/os_process.go
new file mode 100644
index 00000000..7fcf27a4
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/os_process.go
@@ -0,0 +1,76 @@
+package stdlib
+
+import (
+ "os"
+ "syscall"
+
+ "github.com/d5/tengo/v2"
+)
+
+func makeOSProcessState(state *os.ProcessState) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "exited": &tengo.UserFunction{
+ Name: "exited",
+ Value: FuncARB(state.Exited),
+ },
+ "pid": &tengo.UserFunction{
+ Name: "pid",
+ Value: FuncARI(state.Pid),
+ },
+ "string": &tengo.UserFunction{
+ Name: "string",
+ Value: FuncARS(state.String),
+ },
+ "success": &tengo.UserFunction{
+ Name: "success",
+ Value: FuncARB(state.Success),
+ },
+ },
+ }
+}
+
+func makeOSProcess(proc *os.Process) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "kill": &tengo.UserFunction{
+ Name: "kill",
+ Value: FuncARE(proc.Kill),
+ },
+ "release": &tengo.UserFunction{
+ Name: "release",
+ Value: FuncARE(proc.Release),
+ },
+ "signal": &tengo.UserFunction{
+ Name: "signal",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ return wrapError(proc.Signal(syscall.Signal(i1))), nil
+ },
+ },
+ "wait": &tengo.UserFunction{
+ Name: "wait",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 0 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ state, err := proc.Wait()
+ if err != nil {
+ return wrapError(err), nil
+ }
+ return makeOSProcessState(state), nil
+ },
+ },
+ },
+ }
+}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/rand.go b/vendor/github.com/d5/tengo/v2/stdlib/rand.go
new file mode 100644
index 00000000..5d21e1df
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/rand.go
@@ -0,0 +1,138 @@
+package stdlib
+
+import (
+ "math/rand"
+
+ "github.com/d5/tengo/v2"
+)
+
+var randModule = map[string]tengo.Object{
+ "int": &tengo.UserFunction{
+ Name: "int",
+ Value: FuncARI64(rand.Int63),
+ },
+ "float": &tengo.UserFunction{
+ Name: "float",
+ Value: FuncARF(rand.Float64),
+ },
+ "intn": &tengo.UserFunction{
+ Name: "intn",
+ Value: FuncAI64RI64(rand.Int63n),
+ },
+ "exp_float": &tengo.UserFunction{
+ Name: "exp_float",
+ Value: FuncARF(rand.ExpFloat64),
+ },
+ "norm_float": &tengo.UserFunction{
+ Name: "norm_float",
+ Value: FuncARF(rand.NormFloat64),
+ },
+ "perm": &tengo.UserFunction{
+ Name: "perm",
+ Value: FuncAIRIs(rand.Perm),
+ },
+ "seed": &tengo.UserFunction{
+ Name: "seed",
+ Value: FuncAI64R(rand.Seed),
+ },
+ "read": &tengo.UserFunction{
+ Name: "read",
+ Value: func(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ y1, ok := args[0].(*tengo.Bytes)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := rand.Read(y1.Value)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+ return &tengo.Int{Value: int64(res)}, nil
+ },
+ },
+ "rand": &tengo.UserFunction{
+ Name: "rand",
+ Value: func(args ...tengo.Object) (tengo.Object, error) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+ src := rand.NewSource(i1)
+ return randRand(rand.New(src)), nil
+ },
+ },
+}
+
+func randRand(r *rand.Rand) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "int": &tengo.UserFunction{
+ Name: "int",
+ Value: FuncARI64(r.Int63),
+ },
+ "float": &tengo.UserFunction{
+ Name: "float",
+ Value: FuncARF(r.Float64),
+ },
+ "intn": &tengo.UserFunction{
+ Name: "intn",
+ Value: FuncAI64RI64(r.Int63n),
+ },
+ "exp_float": &tengo.UserFunction{
+ Name: "exp_float",
+ Value: FuncARF(r.ExpFloat64),
+ },
+ "norm_float": &tengo.UserFunction{
+ Name: "norm_float",
+ Value: FuncARF(r.NormFloat64),
+ },
+ "perm": &tengo.UserFunction{
+ Name: "perm",
+ Value: FuncAIRIs(r.Perm),
+ },
+ "seed": &tengo.UserFunction{
+ Name: "seed",
+ Value: FuncAI64R(r.Seed),
+ },
+ "read": &tengo.UserFunction{
+ Name: "read",
+ Value: func(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+ ) {
+ if len(args) != 1 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+ y1, ok := args[0].(*tengo.Bytes)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bytes",
+ Found: args[0].TypeName(),
+ }
+ }
+ res, err := r.Read(y1.Value)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+ return &tengo.Int{Value: int64(res)}, nil
+ },
+ },
+ },
+ }
+}
diff --git a/vendor/github.com/d5/tengo/stdlib/source_modules.go b/vendor/github.com/d5/tengo/v2/stdlib/source_modules.go
index ca69d7d1..ca69d7d1 100644
--- a/vendor/github.com/d5/tengo/stdlib/source_modules.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/source_modules.go
diff --git a/vendor/github.com/d5/tengo/stdlib/srcmod_enum.tengo b/vendor/github.com/d5/tengo/v2/stdlib/srcmod_enum.tengo
index 7a5ea637..7a5ea637 100644
--- a/vendor/github.com/d5/tengo/stdlib/srcmod_enum.tengo
+++ b/vendor/github.com/d5/tengo/v2/stdlib/srcmod_enum.tengo
diff --git a/vendor/github.com/d5/tengo/stdlib/stdlib.go b/vendor/github.com/d5/tengo/v2/stdlib/stdlib.go
index aad220ee..16c369a0 100644
--- a/vendor/github.com/d5/tengo/stdlib/stdlib.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/stdlib.go
@@ -2,7 +2,9 @@ package stdlib
//go:generate go run gensrcmods.go
-import "github.com/d5/tengo/objects"
+import (
+ "github.com/d5/tengo/v2"
+)
// AllModuleNames returns a list of all default module names.
func AllModuleNames() []string {
@@ -18,9 +20,8 @@ func AllModuleNames() []string {
// GetModuleMap returns the module map that includes all modules
// for the given module names.
-func GetModuleMap(names ...string) *objects.ModuleMap {
- modules := objects.NewModuleMap()
-
+func GetModuleMap(names ...string) *tengo.ModuleMap {
+ modules := tengo.NewModuleMap()
for _, name := range names {
if mod := BuiltinModules[name]; mod != nil {
modules.AddBuiltinModule(name, mod)
@@ -29,6 +30,5 @@ func GetModuleMap(names ...string) *objects.ModuleMap {
modules.AddSourceModule(name, []byte(mod))
}
}
-
return modules
}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/text.go b/vendor/github.com/d5/tengo/v2/stdlib/text.go
new file mode 100644
index 00000000..d7d5d1da
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/text.go
@@ -0,0 +1,1072 @@
+package stdlib
+
+import (
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+ "unicode/utf8"
+
+ "github.com/d5/tengo/v2"
+)
+
+var textModule = map[string]tengo.Object{
+ "re_match": &tengo.UserFunction{
+ Name: "re_match",
+ Value: textREMatch,
+ }, // re_match(pattern, text) => bool/error
+ "re_find": &tengo.UserFunction{
+ Name: "re_find",
+ Value: textREFind,
+ }, // re_find(pattern, text, count) => [[{text:,begin:,end:}]]/undefined
+ "re_replace": &tengo.UserFunction{
+ Name: "re_replace",
+ Value: textREReplace,
+ }, // re_replace(pattern, text, repl) => string/error
+ "re_split": &tengo.UserFunction{
+ Name: "re_split",
+ Value: textRESplit,
+ }, // re_split(pattern, text, count) => [string]/error
+ "re_compile": &tengo.UserFunction{
+ Name: "re_compile",
+ Value: textRECompile,
+ }, // re_compile(pattern) => Regexp/error
+ "compare": &tengo.UserFunction{
+ Name: "compare",
+ Value: FuncASSRI(strings.Compare),
+ }, // compare(a, b) => int
+ "contains": &tengo.UserFunction{
+ Name: "contains",
+ Value: FuncASSRB(strings.Contains),
+ }, // contains(s, substr) => bool
+ "contains_any": &tengo.UserFunction{
+ Name: "contains_any",
+ Value: FuncASSRB(strings.ContainsAny),
+ }, // contains_any(s, chars) => bool
+ "count": &tengo.UserFunction{
+ Name: "count",
+ Value: FuncASSRI(strings.Count),
+ }, // count(s, substr) => int
+ "equal_fold": &tengo.UserFunction{
+ Name: "equal_fold",
+ Value: FuncASSRB(strings.EqualFold),
+ }, // "equal_fold(s, t) => bool
+ "fields": &tengo.UserFunction{
+ Name: "fields",
+ Value: FuncASRSs(strings.Fields),
+ }, // fields(s) => [string]
+ "has_prefix": &tengo.UserFunction{
+ Name: "has_prefix",
+ Value: FuncASSRB(strings.HasPrefix),
+ }, // has_prefix(s, prefix) => bool
+ "has_suffix": &tengo.UserFunction{
+ Name: "has_suffix",
+ Value: FuncASSRB(strings.HasSuffix),
+ }, // has_suffix(s, suffix) => bool
+ "index": &tengo.UserFunction{
+ Name: "index",
+ Value: FuncASSRI(strings.Index),
+ }, // index(s, substr) => int
+ "index_any": &tengo.UserFunction{
+ Name: "index_any",
+ Value: FuncASSRI(strings.IndexAny),
+ }, // index_any(s, chars) => int
+ "join": &tengo.UserFunction{
+ Name: "join",
+ Value: textJoin,
+ }, // join(arr, sep) => string
+ "last_index": &tengo.UserFunction{
+ Name: "last_index",
+ Value: FuncASSRI(strings.LastIndex),
+ }, // last_index(s, substr) => int
+ "last_index_any": &tengo.UserFunction{
+ Name: "last_index_any",
+ Value: FuncASSRI(strings.LastIndexAny),
+ }, // last_index_any(s, chars) => int
+ "repeat": &tengo.UserFunction{
+ Name: "repeat",
+ Value: textRepeat,
+ }, // repeat(s, count) => string
+ "replace": &tengo.UserFunction{
+ Name: "replace",
+ Value: textReplace,
+ }, // replace(s, old, new, n) => string
+ "substr": &tengo.UserFunction{
+ Name: "substr",
+ Value: textSubstring,
+ }, // substr(s, lower, upper) => string
+ "split": &tengo.UserFunction{
+ Name: "split",
+ Value: FuncASSRSs(strings.Split),
+ }, // split(s, sep) => [string]
+ "split_after": &tengo.UserFunction{
+ Name: "split_after",
+ Value: FuncASSRSs(strings.SplitAfter),
+ }, // split_after(s, sep) => [string]
+ "split_after_n": &tengo.UserFunction{
+ Name: "split_after_n",
+ Value: FuncASSIRSs(strings.SplitAfterN),
+ }, // split_after_n(s, sep, n) => [string]
+ "split_n": &tengo.UserFunction{
+ Name: "split_n",
+ Value: FuncASSIRSs(strings.SplitN),
+ }, // split_n(s, sep, n) => [string]
+ "title": &tengo.UserFunction{
+ Name: "title",
+ Value: FuncASRS(strings.Title),
+ }, // title(s) => string
+ "to_lower": &tengo.UserFunction{
+ Name: "to_lower",
+ Value: FuncASRS(strings.ToLower),
+ }, // to_lower(s) => string
+ "to_title": &tengo.UserFunction{
+ Name: "to_title",
+ Value: FuncASRS(strings.ToTitle),
+ }, // to_title(s) => string
+ "to_upper": &tengo.UserFunction{
+ Name: "to_upper",
+ Value: FuncASRS(strings.ToUpper),
+ }, // to_upper(s) => string
+ "pad_left": &tengo.UserFunction{
+ Name: "pad_left",
+ Value: textPadLeft,
+ }, // pad_left(s, pad_len, pad_with) => string
+ "pad_right": &tengo.UserFunction{
+ Name: "pad_right",
+ Value: textPadRight,
+ }, // pad_right(s, pad_len, pad_with) => string
+ "trim": &tengo.UserFunction{
+ Name: "trim",
+ Value: FuncASSRS(strings.Trim),
+ }, // trim(s, cutset) => string
+ "trim_left": &tengo.UserFunction{
+ Name: "trim_left",
+ Value: FuncASSRS(strings.TrimLeft),
+ }, // trim_left(s, cutset) => string
+ "trim_prefix": &tengo.UserFunction{
+ Name: "trim_prefix",
+ Value: FuncASSRS(strings.TrimPrefix),
+ }, // trim_prefix(s, prefix) => string
+ "trim_right": &tengo.UserFunction{
+ Name: "trim_right",
+ Value: FuncASSRS(strings.TrimRight),
+ }, // trim_right(s, cutset) => string
+ "trim_space": &tengo.UserFunction{
+ Name: "trim_space",
+ Value: FuncASRS(strings.TrimSpace),
+ }, // trim_space(s) => string
+ "trim_suffix": &tengo.UserFunction{
+ Name: "trim_suffix",
+ Value: FuncASSRS(strings.TrimSuffix),
+ }, // trim_suffix(s, suffix) => string
+ "atoi": &tengo.UserFunction{
+ Name: "atoi",
+ Value: FuncASRIE(strconv.Atoi),
+ }, // atoi(str) => int/error
+ "format_bool": &tengo.UserFunction{
+ Name: "format_bool",
+ Value: textFormatBool,
+ }, // format_bool(b) => string
+ "format_float": &tengo.UserFunction{
+ Name: "format_float",
+ Value: textFormatFloat,
+ }, // format_float(f, fmt, prec, bits) => string
+ "format_int": &tengo.UserFunction{
+ Name: "format_int",
+ Value: textFormatInt,
+ }, // format_int(i, base) => string
+ "itoa": &tengo.UserFunction{
+ Name: "itoa",
+ Value: FuncAIRS(strconv.Itoa),
+ }, // itoa(i) => string
+ "parse_bool": &tengo.UserFunction{
+ Name: "parse_bool",
+ Value: textParseBool,
+ }, // parse_bool(str) => bool/error
+ "parse_float": &tengo.UserFunction{
+ Name: "parse_float",
+ Value: textParseFloat,
+ }, // parse_float(str, bits) => float/error
+ "parse_int": &tengo.UserFunction{
+ Name: "parse_int",
+ Value: textParseInt,
+ }, // parse_int(str, base, bits) => int/error
+ "quote": &tengo.UserFunction{
+ Name: "quote",
+ Value: FuncASRS(strconv.Quote),
+ }, // quote(str) => string
+ "unquote": &tengo.UserFunction{
+ Name: "unquote",
+ Value: FuncASRSE(strconv.Unquote),
+ }, // unquote(str) => string/error
+}
+
+func textREMatch(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ matched, err := regexp.MatchString(s1, s2)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ if matched {
+ ret = tengo.TrueValue
+ } else {
+ ret = tengo.FalseValue
+ }
+
+ return
+}
+
+func textREFind(args ...tengo.Object) (ret tengo.Object, err error) {
+ numArgs := len(args)
+ if numArgs != 2 && numArgs != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ re, err := regexp.Compile(s1)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ if numArgs < 3 {
+ m := re.FindStringSubmatchIndex(s2)
+ if m == nil {
+ ret = tengo.UndefinedValue
+ return
+ }
+
+ arr := &tengo.Array{}
+ for i := 0; i < len(m); i += 2 {
+ arr.Value = append(arr.Value,
+ &tengo.ImmutableMap{Value: map[string]tengo.Object{
+ "text": &tengo.String{Value: s2[m[i]:m[i+1]]},
+ "begin": &tengo.Int{Value: int64(m[i])},
+ "end": &tengo.Int{Value: int64(m[i+1])},
+ }})
+ }
+
+ ret = &tengo.Array{Value: []tengo.Object{arr}}
+
+ return
+ }
+
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ m := re.FindAllStringSubmatchIndex(s2, i3)
+ if m == nil {
+ ret = tengo.UndefinedValue
+ return
+ }
+
+ arr := &tengo.Array{}
+ for _, m := range m {
+ subMatch := &tengo.Array{}
+ for i := 0; i < len(m); i += 2 {
+ subMatch.Value = append(subMatch.Value,
+ &tengo.ImmutableMap{Value: map[string]tengo.Object{
+ "text": &tengo.String{Value: s2[m[i]:m[i+1]]},
+ "begin": &tengo.Int{Value: int64(m[i])},
+ "end": &tengo.Int{Value: int64(m[i+1])},
+ }})
+ }
+
+ arr.Value = append(arr.Value, subMatch)
+ }
+
+ ret = arr
+
+ return
+}
+
+func textREReplace(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ s3, ok := tengo.ToString(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+
+ re, err := regexp.Compile(s1)
+ if err != nil {
+ ret = wrapError(err)
+ } else {
+ s, ok := doTextRegexpReplace(re, s2, s3)
+ if !ok {
+ return nil, tengo.ErrStringLimit
+ }
+
+ ret = &tengo.String{Value: s}
+ }
+
+ return
+}
+
+func textRESplit(args ...tengo.Object) (ret tengo.Object, err error) {
+ numArgs := len(args)
+ if numArgs != 2 && numArgs != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ var i3 = -1
+ if numArgs > 2 {
+ i3, ok = tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ }
+
+ re, err := regexp.Compile(s1)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ arr := &tengo.Array{}
+ for _, s := range re.Split(s2, i3) {
+ arr.Value = append(arr.Value, &tengo.String{Value: s})
+ }
+
+ ret = arr
+
+ return
+}
+
+func textRECompile(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ re, err := regexp.Compile(s1)
+ if err != nil {
+ ret = wrapError(err)
+ } else {
+ ret = makeTextRegexp(re)
+ }
+
+ return
+}
+
+func textReplace(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 4 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ s3, ok := tengo.ToString(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+
+ i4, ok := tengo.ToInt(args[3])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "int(compatible)",
+ Found: args[3].TypeName(),
+ }
+ return
+ }
+
+ s, ok := doTextReplace(s1, s2, s3, i4)
+ if !ok {
+ err = tengo.ErrStringLimit
+ return
+ }
+
+ ret = &tengo.String{Value: s}
+
+ return
+}
+
+func textSubstring(args ...tengo.Object) (ret tengo.Object, err error) {
+ argslen := len(args)
+ if argslen != 2 && argslen != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ strlen := len(s1)
+ i3 := strlen
+ if argslen == 3 {
+ i3, ok = tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ }
+
+ if i2 > i3 {
+ err = tengo.ErrInvalidIndexType
+ return
+ }
+
+ if i2 < 0 {
+ i2 = 0
+ } else if i2 > strlen {
+ i2 = strlen
+ }
+
+ if i3 < 0 {
+ i3 = 0
+ } else if i3 > strlen {
+ i3 = strlen
+ }
+
+ ret = &tengo.String{Value: s1[i2:i3]}
+
+ return
+}
+
+func textPadLeft(args ...tengo.Object) (ret tengo.Object, err error) {
+ argslen := len(args)
+ if argslen != 2 && argslen != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ if i2 > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+
+ sLen := len(s1)
+ if sLen >= i2 {
+ ret = &tengo.String{Value: s1}
+ return
+ }
+
+ s3 := " "
+ if argslen == 3 {
+ s3, ok = tengo.ToString(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ }
+
+ padStrLen := len(s3)
+ if padStrLen == 0 {
+ ret = &tengo.String{Value: s1}
+ return
+ }
+
+ padCount := ((i2 - padStrLen) / padStrLen) + 1
+ retStr := strings.Repeat(s3, padCount) + s1
+ ret = &tengo.String{Value: retStr[len(retStr)-i2:]}
+
+ return
+}
+
+func textPadRight(args ...tengo.Object) (ret tengo.Object, err error) {
+ argslen := len(args)
+ if argslen != 2 && argslen != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ if i2 > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+
+ sLen := len(s1)
+ if sLen >= i2 {
+ ret = &tengo.String{Value: s1}
+ return
+ }
+
+ s3 := " "
+ if argslen == 3 {
+ s3, ok = tengo.ToString(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "string(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ }
+
+ padStrLen := len(s3)
+ if padStrLen == 0 {
+ ret = &tengo.String{Value: s1}
+ return
+ }
+
+ padCount := ((i2 - padStrLen) / padStrLen) + 1
+ retStr := s1 + strings.Repeat(s3, padCount)
+ ret = &tengo.String{Value: retStr[:i2]}
+
+ return
+}
+
+func textRepeat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+
+ if len(s1)*i2 > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+
+ return &tengo.String{Value: strings.Repeat(s1, i2)}, nil
+}
+
+func textJoin(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ return nil, tengo.ErrWrongNumArguments
+ }
+
+ var slen int
+ var ss1 []string
+ switch arg0 := args[0].(type) {
+ case *tengo.Array:
+ for idx, a := range arg0.Value {
+ as, ok := tengo.ToString(a)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("first[%d]", idx),
+ Expected: "string(compatible)",
+ Found: a.TypeName(),
+ }
+ }
+ slen += len(as)
+ ss1 = append(ss1, as)
+ }
+ case *tengo.ImmutableArray:
+ for idx, a := range arg0.Value {
+ as, ok := tengo.ToString(a)
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: fmt.Sprintf("first[%d]", idx),
+ Expected: "string(compatible)",
+ Found: a.TypeName(),
+ }
+ }
+ slen += len(as)
+ ss1 = append(ss1, as)
+ }
+ default:
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "array",
+ Found: args[0].TypeName(),
+ }
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ return nil, tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ }
+
+ // make sure output length does not exceed the limit
+ if slen+len(s2)*(len(ss1)-1) > tengo.MaxStringLen {
+ return nil, tengo.ErrStringLimit
+ }
+
+ return &tengo.String{Value: strings.Join(ss1, s2)}, nil
+}
+
+func textFormatBool(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ b1, ok := args[0].(*tengo.Bool)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "bool",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ if b1 == tengo.TrueValue {
+ ret = &tengo.String{Value: "true"}
+ } else {
+ ret = &tengo.String{Value: "false"}
+ }
+
+ return
+}
+
+func textFormatFloat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 4 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ f1, ok := args[0].(*tengo.Float)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "float",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+
+ i4, ok := tengo.ToInt(args[3])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "int(compatible)",
+ Found: args[3].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: strconv.FormatFloat(f1.Value, s2[0], i3, i4)}
+
+ return
+}
+
+func textFormatInt(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := args[0].(*tengo.Int)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: strconv.FormatInt(i1.Value, i2)}
+
+ return
+}
+
+func textParseBool(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := args[0].(*tengo.String)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ parsed, err := strconv.ParseBool(s1.Value)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ if parsed {
+ ret = tengo.TrueValue
+ } else {
+ ret = tengo.FalseValue
+ }
+
+ return
+}
+
+func textParseFloat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := args[0].(*tengo.String)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ parsed, err := strconv.ParseFloat(s1.Value, i2)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ ret = &tengo.Float{Value: parsed}
+
+ return
+}
+
+func textParseInt(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 3 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := args[0].(*tengo.String)
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+
+ parsed, err := strconv.ParseInt(s1.Value, i2, i3)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ ret = &tengo.Int{Value: parsed}
+
+ return
+}
+
+// Modified implementation of strings.Replace
+// to limit the maximum length of output string.
+func doTextReplace(s, old, new string, n int) (string, bool) {
+ if old == new || n == 0 {
+ return s, true // avoid allocation
+ }
+
+ // Compute number of replacements.
+ if m := strings.Count(s, old); m == 0 {
+ return s, true // avoid allocation
+ } else if n < 0 || m < n {
+ n = m
+ }
+
+ // Apply replacements to buffer.
+ t := make([]byte, len(s)+n*(len(new)-len(old)))
+ w := 0
+ start := 0
+ for i := 0; i < n; i++ {
+ j := start
+ if len(old) == 0 {
+ if i > 0 {
+ _, wid := utf8.DecodeRuneInString(s[start:])
+ j += wid
+ }
+ } else {
+ j += strings.Index(s[start:], old)
+ }
+
+ ssj := s[start:j]
+ if w+len(ssj)+len(new) > tengo.MaxStringLen {
+ return "", false
+ }
+
+ w += copy(t[w:], ssj)
+ w += copy(t[w:], new)
+ start = j + len(old)
+ }
+
+ ss := s[start:]
+ if w+len(ss) > tengo.MaxStringLen {
+ return "", false
+ }
+
+ w += copy(t[w:], ss)
+
+ return string(t[0:w]), true
+}
diff --git a/vendor/github.com/d5/tengo/stdlib/text_regexp.go b/vendor/github.com/d5/tengo/v2/stdlib/text_regexp.go
index 16f135bf..1a7ecf07 100644
--- a/vendor/github.com/d5/tengo/stdlib/text_regexp.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/text_regexp.go
@@ -3,24 +3,26 @@ package stdlib
import (
"regexp"
- "github.com/d5/tengo"
- "github.com/d5/tengo/objects"
+ "github.com/d5/tengo/v2"
)
-func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
- return &objects.ImmutableMap{
- Value: map[string]objects.Object{
+func makeTextRegexp(re *regexp.Regexp) *tengo.ImmutableMap {
+ return &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
// match(text) => bool
- "match": &objects.UserFunction{
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
+ "match": &tengo.UserFunction{
+ Value: func(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+ ) {
if len(args) != 1 {
- err = objects.ErrWrongNumArguments
+ err = tengo.ErrWrongNumArguments
return
}
- s1, ok := objects.ToString(args[0])
+ s1, ok := tengo.ToString(args[0])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
@@ -29,9 +31,9 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
}
if re.MatchString(s1) {
- ret = objects.TrueValue
+ ret = tengo.TrueValue
} else {
- ret = objects.FalseValue
+ ret = tengo.FalseValue
}
return
@@ -40,17 +42,20 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
// find(text) => array(array({text:,begin:,end:}))/undefined
// find(text, maxCount) => array(array({text:,begin:,end:}))/undefined
- "find": &objects.UserFunction{
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
+ "find": &tengo.UserFunction{
+ Value: func(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+ ) {
numArgs := len(args)
if numArgs != 1 && numArgs != 2 {
- err = objects.ErrWrongNumArguments
+ err = tengo.ErrWrongNumArguments
return
}
- s1, ok := objects.ToString(args[0])
+ s1, ok := tengo.ToString(args[0])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
@@ -61,27 +66,35 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
if numArgs == 1 {
m := re.FindStringSubmatchIndex(s1)
if m == nil {
- ret = objects.UndefinedValue
+ ret = tengo.UndefinedValue
return
}
- arr := &objects.Array{}
+ arr := &tengo.Array{}
for i := 0; i < len(m); i += 2 {
- arr.Value = append(arr.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
- "text": &objects.String{Value: s1[m[i]:m[i+1]]},
- "begin": &objects.Int{Value: int64(m[i])},
- "end": &objects.Int{Value: int64(m[i+1])},
- }})
+ arr.Value = append(arr.Value,
+ &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "text": &tengo.String{
+ Value: s1[m[i]:m[i+1]],
+ },
+ "begin": &tengo.Int{
+ Value: int64(m[i]),
+ },
+ "end": &tengo.Int{
+ Value: int64(m[i+1]),
+ },
+ }})
}
- ret = &objects.Array{Value: []objects.Object{arr}}
+ ret = &tengo.Array{Value: []tengo.Object{arr}}
return
}
- i2, ok := objects.ToInt(args[1])
+ i2, ok := tengo.ToInt(args[1])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "second",
Expected: "int(compatible)",
Found: args[1].TypeName(),
@@ -90,19 +103,27 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
}
m := re.FindAllStringSubmatchIndex(s1, i2)
if m == nil {
- ret = objects.UndefinedValue
+ ret = tengo.UndefinedValue
return
}
- arr := &objects.Array{}
+ arr := &tengo.Array{}
for _, m := range m {
- subMatch := &objects.Array{}
+ subMatch := &tengo.Array{}
for i := 0; i < len(m); i += 2 {
- subMatch.Value = append(subMatch.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
- "text": &objects.String{Value: s1[m[i]:m[i+1]]},
- "begin": &objects.Int{Value: int64(m[i])},
- "end": &objects.Int{Value: int64(m[i+1])},
- }})
+ subMatch.Value = append(subMatch.Value,
+ &tengo.ImmutableMap{
+ Value: map[string]tengo.Object{
+ "text": &tengo.String{
+ Value: s1[m[i]:m[i+1]],
+ },
+ "begin": &tengo.Int{
+ Value: int64(m[i]),
+ },
+ "end": &tengo.Int{
+ Value: int64(m[i+1]),
+ },
+ }})
}
arr.Value = append(arr.Value, subMatch)
@@ -115,16 +136,19 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
},
// replace(src, repl) => string
- "replace": &objects.UserFunction{
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
+ "replace": &tengo.UserFunction{
+ Value: func(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+ ) {
if len(args) != 2 {
- err = objects.ErrWrongNumArguments
+ err = tengo.ErrWrongNumArguments
return
}
- s1, ok := objects.ToString(args[0])
+ s1, ok := tengo.ToString(args[0])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
@@ -132,9 +156,9 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
return
}
- s2, ok := objects.ToString(args[1])
+ s2, ok := tengo.ToString(args[1])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "second",
Expected: "string(compatible)",
Found: args[1].TypeName(),
@@ -144,10 +168,10 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
s, ok := doTextRegexpReplace(re, s1, s2)
if !ok {
- return nil, objects.ErrStringLimit
+ return nil, tengo.ErrStringLimit
}
- ret = &objects.String{Value: s}
+ ret = &tengo.String{Value: s}
return
},
@@ -155,17 +179,20 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
// split(text) => array(string)
// split(text, maxCount) => array(string)
- "split": &objects.UserFunction{
- Value: func(args ...objects.Object) (ret objects.Object, err error) {
+ "split": &tengo.UserFunction{
+ Value: func(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+ ) {
numArgs := len(args)
if numArgs != 1 && numArgs != 2 {
- err = objects.ErrWrongNumArguments
+ err = tengo.ErrWrongNumArguments
return
}
- s1, ok := objects.ToString(args[0])
+ s1, ok := tengo.ToString(args[0])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "first",
Expected: "string(compatible)",
Found: args[0].TypeName(),
@@ -175,9 +202,9 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
var i2 = -1
if numArgs > 1 {
- i2, ok = objects.ToInt(args[1])
+ i2, ok = tengo.ToInt(args[1])
if !ok {
- err = objects.ErrInvalidArgumentType{
+ err = tengo.ErrInvalidArgumentType{
Name: "second",
Expected: "int(compatible)",
Found: args[1].TypeName(),
@@ -186,9 +213,10 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
}
}
- arr := &objects.Array{}
+ arr := &tengo.Array{}
for _, s := range re.Split(s1, i2) {
- arr.Value = append(arr.Value, &objects.String{Value: s})
+ arr.Value = append(arr.Value,
+ &tengo.String{Value: s})
}
ret = arr
@@ -204,15 +232,12 @@ func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
func doTextRegexpReplace(re *regexp.Regexp, src, repl string) (string, bool) {
idx := 0
out := ""
-
for _, m := range re.FindAllStringSubmatchIndex(src, -1) {
var exp []byte
exp = re.ExpandString(exp, repl, src, m)
-
if len(out)+m[0]-idx+len(exp) > tengo.MaxStringLen {
return "", false
}
-
out += src[idx:m[0]] + string(exp)
idx = m[1]
}
@@ -220,9 +245,7 @@ func doTextRegexpReplace(re *regexp.Regexp, src, repl string) (string, bool) {
if len(out)+len(src)-idx > tengo.MaxStringLen {
return "", false
}
-
out += src[idx:]
}
-
- return string(out), true
+ return out, true
}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/times.go b/vendor/github.com/d5/tengo/v2/stdlib/times.go
new file mode 100644
index 00000000..0b6f7bd4
--- /dev/null
+++ b/vendor/github.com/d5/tengo/v2/stdlib/times.go
@@ -0,0 +1,1135 @@
+package stdlib
+
+import (
+ "time"
+
+ "github.com/d5/tengo/v2"
+)
+
+var timesModule = map[string]tengo.Object{
+ "format_ansic": &tengo.String{Value: time.ANSIC},
+ "format_unix_date": &tengo.String{Value: time.UnixDate},
+ "format_ruby_date": &tengo.String{Value: time.RubyDate},
+ "format_rfc822": &tengo.String{Value: time.RFC822},
+ "format_rfc822z": &tengo.String{Value: time.RFC822Z},
+ "format_rfc850": &tengo.String{Value: time.RFC850},
+ "format_rfc1123": &tengo.String{Value: time.RFC1123},
+ "format_rfc1123z": &tengo.String{Value: time.RFC1123Z},
+ "format_rfc3339": &tengo.String{Value: time.RFC3339},
+ "format_rfc3339_nano": &tengo.String{Value: time.RFC3339Nano},
+ "format_kitchen": &tengo.String{Value: time.Kitchen},
+ "format_stamp": &tengo.String{Value: time.Stamp},
+ "format_stamp_milli": &tengo.String{Value: time.StampMilli},
+ "format_stamp_micro": &tengo.String{Value: time.StampMicro},
+ "format_stamp_nano": &tengo.String{Value: time.StampNano},
+ "nanosecond": &tengo.Int{Value: int64(time.Nanosecond)},
+ "microsecond": &tengo.Int{Value: int64(time.Microsecond)},
+ "millisecond": &tengo.Int{Value: int64(time.Millisecond)},
+ "second": &tengo.Int{Value: int64(time.Second)},
+ "minute": &tengo.Int{Value: int64(time.Minute)},
+ "hour": &tengo.Int{Value: int64(time.Hour)},
+ "january": &tengo.Int{Value: int64(time.January)},
+ "february": &tengo.Int{Value: int64(time.February)},
+ "march": &tengo.Int{Value: int64(time.March)},
+ "april": &tengo.Int{Value: int64(time.April)},
+ "may": &tengo.Int{Value: int64(time.May)},
+ "june": &tengo.Int{Value: int64(time.June)},
+ "july": &tengo.Int{Value: int64(time.July)},
+ "august": &tengo.Int{Value: int64(time.August)},
+ "september": &tengo.Int{Value: int64(time.September)},
+ "october": &tengo.Int{Value: int64(time.October)},
+ "november": &tengo.Int{Value: int64(time.November)},
+ "december": &tengo.Int{Value: int64(time.December)},
+ "sleep": &tengo.UserFunction{
+ Name: "sleep",
+ Value: timesSleep,
+ }, // sleep(int)
+ "parse_duration": &tengo.UserFunction{
+ Name: "parse_duration",
+ Value: timesParseDuration,
+ }, // parse_duration(str) => int
+ "since": &tengo.UserFunction{
+ Name: "since",
+ Value: timesSince,
+ }, // since(time) => int
+ "until": &tengo.UserFunction{
+ Name: "until",
+ Value: timesUntil,
+ }, // until(time) => int
+ "duration_hours": &tengo.UserFunction{
+ Name: "duration_hours",
+ Value: timesDurationHours,
+ }, // duration_hours(int) => float
+ "duration_minutes": &tengo.UserFunction{
+ Name: "duration_minutes",
+ Value: timesDurationMinutes,
+ }, // duration_minutes(int) => float
+ "duration_nanoseconds": &tengo.UserFunction{
+ Name: "duration_nanoseconds",
+ Value: timesDurationNanoseconds,
+ }, // duration_nanoseconds(int) => int
+ "duration_seconds": &tengo.UserFunction{
+ Name: "duration_seconds",
+ Value: timesDurationSeconds,
+ }, // duration_seconds(int) => float
+ "duration_string": &tengo.UserFunction{
+ Name: "duration_string",
+ Value: timesDurationString,
+ }, // duration_string(int) => string
+ "month_string": &tengo.UserFunction{
+ Name: "month_string",
+ Value: timesMonthString,
+ }, // month_string(int) => string
+ "date": &tengo.UserFunction{
+ Name: "date",
+ Value: timesDate,
+ }, // date(year, month, day, hour, min, sec, nsec) => time
+ "now": &tengo.UserFunction{
+ Name: "now",
+ Value: timesNow,
+ }, // now() => time
+ "parse": &tengo.UserFunction{
+ Name: "parse",
+ Value: timesParse,
+ }, // parse(format, str) => time
+ "unix": &tengo.UserFunction{
+ Name: "unix",
+ Value: timesUnix,
+ }, // unix(sec, nsec) => time
+ "add": &tengo.UserFunction{
+ Name: "add",
+ Value: timesAdd,
+ }, // add(time, int) => time
+ "add_date": &tengo.UserFunction{
+ Name: "add_date",
+ Value: timesAddDate,
+ }, // add_date(time, years, months, days) => time
+ "sub": &tengo.UserFunction{
+ Name: "sub",
+ Value: timesSub,
+ }, // sub(t time, u time) => int
+ "after": &tengo.UserFunction{
+ Name: "after",
+ Value: timesAfter,
+ }, // after(t time, u time) => bool
+ "before": &tengo.UserFunction{
+ Name: "before",
+ Value: timesBefore,
+ }, // before(t time, u time) => bool
+ "time_year": &tengo.UserFunction{
+ Name: "time_year",
+ Value: timesTimeYear,
+ }, // time_year(time) => int
+ "time_month": &tengo.UserFunction{
+ Name: "time_month",
+ Value: timesTimeMonth,
+ }, // time_month(time) => int
+ "time_day": &tengo.UserFunction{
+ Name: "time_day",
+ Value: timesTimeDay,
+ }, // time_day(time) => int
+ "time_weekday": &tengo.UserFunction{
+ Name: "time_weekday",
+ Value: timesTimeWeekday,
+ }, // time_weekday(time) => int
+ "time_hour": &tengo.UserFunction{
+ Name: "time_hour",
+ Value: timesTimeHour,
+ }, // time_hour(time) => int
+ "time_minute": &tengo.UserFunction{
+ Name: "time_minute",
+ Value: timesTimeMinute,
+ }, // time_minute(time) => int
+ "time_second": &tengo.UserFunction{
+ Name: "time_second",
+ Value: timesTimeSecond,
+ }, // time_second(time) => int
+ "time_nanosecond": &tengo.UserFunction{
+ Name: "time_nanosecond",
+ Value: timesTimeNanosecond,
+ }, // time_nanosecond(time) => int
+ "time_unix": &tengo.UserFunction{
+ Name: "time_unix",
+ Value: timesTimeUnix,
+ }, // time_unix(time) => int
+ "time_unix_nano": &tengo.UserFunction{
+ Name: "time_unix_nano",
+ Value: timesTimeUnixNano,
+ }, // time_unix_nano(time) => int
+ "time_format": &tengo.UserFunction{
+ Name: "time_format",
+ Value: timesTimeFormat,
+ }, // time_format(time, format) => string
+ "time_location": &tengo.UserFunction{
+ Name: "time_location",
+ Value: timesTimeLocation,
+ }, // time_location(time) => string
+ "time_string": &tengo.UserFunction{
+ Name: "time_string",
+ Value: timesTimeString,
+ }, // time_string(time) => string
+ "is_zero": &tengo.UserFunction{
+ Name: "is_zero",
+ Value: timesIsZero,
+ }, // is_zero(time) => bool
+ "to_local": &tengo.UserFunction{
+ Name: "to_local",
+ Value: timesToLocal,
+ }, // to_local(time) => time
+ "to_utc": &tengo.UserFunction{
+ Name: "to_utc",
+ Value: timesToUTC,
+ }, // to_utc(time) => time
+}
+
+func timesSleep(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ time.Sleep(time.Duration(i1))
+ ret = tengo.UndefinedValue
+
+ return
+}
+
+func timesParseDuration(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ dur, err := time.ParseDuration(s1)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(dur)}
+
+ return
+}
+
+func timesSince(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(time.Since(t1))}
+
+ return
+}
+
+func timesUntil(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(time.Until(t1))}
+
+ return
+}
+
+func timesDurationHours(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Float{Value: time.Duration(i1).Hours()}
+
+ return
+}
+
+func timesDurationMinutes(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Float{Value: time.Duration(i1).Minutes()}
+
+ return
+}
+
+func timesDurationNanoseconds(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: time.Duration(i1).Nanoseconds()}
+
+ return
+}
+
+func timesDurationSeconds(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Float{Value: time.Duration(i1).Seconds()}
+
+ return
+}
+
+func timesDurationString(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: time.Duration(i1).String()}
+
+ return
+}
+
+func timesMonthString(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: time.Month(i1).String()}
+
+ return
+}
+
+func timesDate(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 7 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+ i4, ok := tengo.ToInt(args[3])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "int(compatible)",
+ Found: args[3].TypeName(),
+ }
+ return
+ }
+ i5, ok := tengo.ToInt(args[4])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "fifth",
+ Expected: "int(compatible)",
+ Found: args[4].TypeName(),
+ }
+ return
+ }
+ i6, ok := tengo.ToInt(args[5])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "sixth",
+ Expected: "int(compatible)",
+ Found: args[5].TypeName(),
+ }
+ return
+ }
+ i7, ok := tengo.ToInt(args[6])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "seventh",
+ Expected: "int(compatible)",
+ Found: args[6].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{
+ Value: time.Date(i1,
+ time.Month(i2), i3, i4, i5, i6, i7, time.Now().Location()),
+ }
+
+ return
+}
+
+func timesNow(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 0 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ ret = &tengo.Time{Value: time.Now()}
+
+ return
+}
+
+func timesParse(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ s1, ok := tengo.ToString(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "string(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ parsed, err := time.Parse(s1, s2)
+ if err != nil {
+ ret = wrapError(err)
+ return
+ }
+
+ ret = &tengo.Time{Value: parsed}
+
+ return
+}
+
+func timesUnix(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ i1, ok := tengo.ToInt64(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "int(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt64(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{Value: time.Unix(i1, i2)}
+
+ return
+}
+
+func timesAdd(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt64(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{Value: t1.Add(time.Duration(i2))}
+
+ return
+}
+
+func timesSub(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ t2, ok := tengo.ToTime(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "time(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Sub(t2))}
+
+ return
+}
+
+func timesAddDate(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 4 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ i2, ok := tengo.ToInt(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "int(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ i3, ok := tengo.ToInt(args[2])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "third",
+ Expected: "int(compatible)",
+ Found: args[2].TypeName(),
+ }
+ return
+ }
+
+ i4, ok := tengo.ToInt(args[3])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "fourth",
+ Expected: "int(compatible)",
+ Found: args[3].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{Value: t1.AddDate(i2, i3, i4)}
+
+ return
+}
+
+func timesAfter(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ t2, ok := tengo.ToTime(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "time(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ if t1.After(t2) {
+ ret = tengo.TrueValue
+ } else {
+ ret = tengo.FalseValue
+ }
+
+ return
+}
+
+func timesBefore(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ t2, ok := tengo.ToTime(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ if t1.Before(t2) {
+ ret = tengo.TrueValue
+ } else {
+ ret = tengo.FalseValue
+ }
+
+ return
+}
+
+func timesTimeYear(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Year())}
+
+ return
+}
+
+func timesTimeMonth(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Month())}
+
+ return
+}
+
+func timesTimeDay(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Day())}
+
+ return
+}
+
+func timesTimeWeekday(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Weekday())}
+
+ return
+}
+
+func timesTimeHour(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Hour())}
+
+ return
+}
+
+func timesTimeMinute(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Minute())}
+
+ return
+}
+
+func timesTimeSecond(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Second())}
+
+ return
+}
+
+func timesTimeNanosecond(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: int64(t1.Nanosecond())}
+
+ return
+}
+
+func timesTimeUnix(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: t1.Unix()}
+
+ return
+}
+
+func timesTimeUnixNano(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Int{Value: t1.UnixNano()}
+
+ return
+}
+
+func timesTimeFormat(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 2 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ s2, ok := tengo.ToString(args[1])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "second",
+ Expected: "string(compatible)",
+ Found: args[1].TypeName(),
+ }
+ return
+ }
+
+ s := t1.Format(s2)
+ if len(s) > tengo.MaxStringLen {
+
+ return nil, tengo.ErrStringLimit
+ }
+
+ ret = &tengo.String{Value: s}
+
+ return
+}
+
+func timesIsZero(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ if t1.IsZero() {
+ ret = tengo.TrueValue
+ } else {
+ ret = tengo.FalseValue
+ }
+
+ return
+}
+
+func timesToLocal(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{Value: t1.Local()}
+
+ return
+}
+
+func timesToUTC(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.Time{Value: t1.UTC()}
+
+ return
+}
+
+func timesTimeLocation(args ...tengo.Object) (
+ ret tengo.Object,
+ err error,
+) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: t1.Location().String()}
+
+ return
+}
+
+func timesTimeString(args ...tengo.Object) (ret tengo.Object, err error) {
+ if len(args) != 1 {
+ err = tengo.ErrWrongNumArguments
+ return
+ }
+
+ t1, ok := tengo.ToTime(args[0])
+ if !ok {
+ err = tengo.ErrInvalidArgumentType{
+ Name: "first",
+ Expected: "time(compatible)",
+ Found: args[0].TypeName(),
+ }
+ return
+ }
+
+ ret = &tengo.String{Value: t1.String()}
+
+ return
+}
diff --git a/vendor/github.com/d5/tengo/compiler/symbol_table.go b/vendor/github.com/d5/tengo/v2/symbol_table.go
index 94c868de..6ae5d7d3 100644
--- a/vendor/github.com/d5/tengo/compiler/symbol_table.go
+++ b/vendor/github.com/d5/tengo/v2/symbol_table.go
@@ -1,4 +1,23 @@
-package compiler
+package tengo
+
+// SymbolScope represents a symbol scope.
+type SymbolScope string
+
+// List of symbol scopes
+const (
+ ScopeGlobal SymbolScope = "GLOBAL"
+ ScopeLocal SymbolScope = "LOCAL"
+ ScopeBuiltin SymbolScope = "BUILTIN"
+ ScopeFree SymbolScope = "FREE"
+)
+
+// Symbol represents a symbol in the symbol table.
+type Symbol struct {
+ Name string
+ Scope SymbolScope
+ Index int
+ LocalAssigned bool // if the local symbol is assigned at least once
+}
// SymbolTable represents a symbol table.
type SymbolTable struct {
@@ -28,11 +47,8 @@ func (t *SymbolTable) Define(name string) *Symbol {
} else {
symbol.Scope = ScopeLocal
}
-
t.store[name] = symbol
-
t.updateMaxDefs(symbol.Index + 1)
-
return symbol
}
@@ -47,34 +63,32 @@ func (t *SymbolTable) DefineBuiltin(index int, name string) *Symbol {
Index: index,
Scope: ScopeBuiltin,
}
-
t.store[name] = symbol
-
t.builtinSymbols = append(t.builtinSymbols, symbol)
-
return symbol
}
// Resolve resolves a symbol with a given name.
-func (t *SymbolTable) Resolve(name string) (symbol *Symbol, depth int, ok bool) {
+func (t *SymbolTable) Resolve(
+ name string,
+) (symbol *Symbol, depth int, ok bool) {
symbol, ok = t.store[name]
if !ok && t.parent != nil {
symbol, depth, ok = t.parent.Resolve(name)
if !ok {
return
}
-
depth++
// if symbol is defined in parent table and if it's not global/builtin
// then it's free variable.
- if !t.block && depth > 0 && symbol.Scope != ScopeGlobal && symbol.Scope != ScopeBuiltin {
+ if !t.block && depth > 0 &&
+ symbol.Scope != ScopeGlobal &&
+ symbol.Scope != ScopeBuiltin {
return t.defineFree(symbol), depth, true
}
-
return
}
-
return
}
@@ -92,7 +106,6 @@ func (t *SymbolTable) Parent(skipBlock bool) *SymbolTable {
if skipBlock && t.block {
return t.parent.Parent(skipBlock)
}
-
return t.parent
}
@@ -111,7 +124,6 @@ func (t *SymbolTable) BuiltinSymbols() []*Symbol {
if t.parent != nil {
return t.parent.BuiltinSymbols()
}
-
return t.builtinSymbols
}
@@ -128,7 +140,6 @@ func (t *SymbolTable) nextIndex() int {
if t.block {
return t.parent.nextIndex() + t.numDefinition
}
-
return t.numDefinition
}
@@ -136,7 +147,6 @@ func (t *SymbolTable) updateMaxDefs(numDefs int) {
if numDefs > t.maxDefinition {
t.maxDefinition = numDefs
}
-
if t.block {
t.parent.updateMaxDefs(numDefs)
}
@@ -144,16 +154,12 @@ func (t *SymbolTable) updateMaxDefs(numDefs int) {
func (t *SymbolTable) defineFree(original *Symbol) *Symbol {
// TODO: should we check duplicates?
-
t.freeSymbols = append(t.freeSymbols, original)
-
symbol := &Symbol{
Name: original.Name,
Index: len(t.freeSymbols) - 1,
Scope: ScopeFree,
}
-
t.store[original.Name] = symbol
-
return symbol
}
diff --git a/vendor/github.com/d5/tengo/objects/conversion.go b/vendor/github.com/d5/tengo/v2/tengo.go
index 27514132..098a1970 100644
--- a/vendor/github.com/d5/tengo/objects/conversion.go
+++ b/vendor/github.com/d5/tengo/v2/tengo.go
@@ -1,29 +1,75 @@
-package objects
+package tengo
import (
"errors"
"fmt"
"strconv"
"time"
+)
+
+var (
+ // MaxStringLen is the maximum byte-length for string value. Note this
+ // limit applies to all compiler/VM instances in the process.
+ MaxStringLen = 2147483647
- "github.com/d5/tengo"
+ // MaxBytesLen is the maximum length for bytes value. Note this limit
+ // applies to all compiler/VM instances in the process.
+ MaxBytesLen = 2147483647
)
+const (
+ // GlobalsSize is the maximum number of global variables for a VM.
+ GlobalsSize = 1024
+
+ // StackSize is the maximum stack size for a VM.
+ StackSize = 2048
+
+ // MaxFrames is the maximum number of function frames for a VM.
+ MaxFrames = 1024
+)
+
+// CallableFunc is a function signature for the callable functions.
+type CallableFunc = func(args ...Object) (ret Object, err error)
+
+// CountObjects returns the number of objects that a given object o contains.
+// For scalar value types, it will always be 1. For compound value types,
+// this will include its elements and all of their elements recursively.
+func CountObjects(o Object) (c int) {
+ c = 1
+ switch o := o.(type) {
+ case *Array:
+ for _, v := range o.Value {
+ c += CountObjects(v)
+ }
+ case *ImmutableArray:
+ for _, v := range o.Value {
+ c += CountObjects(v)
+ }
+ case *Map:
+ for _, v := range o.Value {
+ c += CountObjects(v)
+ }
+ case *ImmutableMap:
+ for _, v := range o.Value {
+ c += CountObjects(v)
+ }
+ case *Error:
+ c += CountObjects(o.Value)
+ }
+ return
+}
+
// ToString will try to convert object o to string value.
func ToString(o Object) (v string, ok bool) {
if o == UndefinedValue {
- //ok = false
return
}
-
ok = true
-
if str, isStr := o.(*String); isStr {
v = str.Value
} else {
v = o.String()
}
-
return
}
@@ -51,8 +97,6 @@ func ToInt(o Object) (v int, ok bool) {
ok = true
}
}
-
- //ok = false
return
}
@@ -80,8 +124,6 @@ func ToInt64(o Object) (v int64, ok bool) {
ok = true
}
}
-
- //ok = false
return
}
@@ -101,8 +143,6 @@ func ToFloat64(o Object) (v float64, ok bool) {
ok = true
}
}
-
- //ok = false
return
}
@@ -110,7 +150,6 @@ func ToFloat64(o Object) (v float64, ok bool) {
func ToBool(o Object) (v bool, ok bool) {
ok = true
v = !o.IsFalsy()
-
return
}
@@ -121,11 +160,9 @@ func ToRune(o Object) (v rune, ok bool) {
v = rune(o.Value)
ok = true
case *Char:
- v = rune(o.Value)
+ v = o.Value
ok = true
}
-
- //ok = false
return
}
@@ -139,8 +176,6 @@ func ToByteSlice(o Object) (v []byte, ok bool) {
v = []byte(o.Value)
ok = true
}
-
- //ok = false
return
}
@@ -154,8 +189,6 @@ func ToTime(o Object) (v time.Time, ok bool) {
v = time.Unix(o.Value, 0)
ok = true
}
-
- //ok = false
return
}
@@ -203,7 +236,6 @@ func ToInterface(o Object) (res interface{}) {
case Object:
return o
}
-
return
}
@@ -213,7 +245,7 @@ func FromInterface(v interface{}) (Object, error) {
case nil:
return UndefinedValue, nil
case string:
- if len(v) > tengo.MaxStringLen {
+ if len(v) > MaxStringLen {
return nil, ErrStringLimit
}
return &String{Value: v}, nil
@@ -233,7 +265,7 @@ func FromInterface(v interface{}) (Object, error) {
case float64:
return &Float{Value: v}, nil
case []byte:
- if len(v) > tengo.MaxBytesLen {
+ if len(v) > MaxBytesLen {
return nil, ErrBytesLimit
}
return &Bytes{Value: v}, nil
@@ -260,7 +292,6 @@ func FromInterface(v interface{}) (Object, error) {
if err != nil {
return nil, err
}
-
arr[i] = vo
}
return &Array{Value: arr}, nil
@@ -271,6 +302,5 @@ func FromInterface(v interface{}) (Object, error) {
case CallableFunc:
return &UserFunction{Value: v}, nil
}
-
return nil, fmt.Errorf("cannot convert to object: %T", v)
}
diff --git a/vendor/github.com/d5/tengo/compiler/token/tokens.go b/vendor/github.com/d5/tengo/v2/token/token.go
index b32d36ee..4e6aa80a 100644
--- a/vendor/github.com/d5/tengo/compiler/token/tokens.go
+++ b/vendor/github.com/d5/tengo/v2/token/token.go
@@ -2,6 +2,8 @@ package token
import "strconv"
+var keywords map[string]Token
+
// Token represents a token.
type Token int
@@ -206,3 +208,18 @@ func (tok Token) IsOperator() bool {
func (tok Token) IsKeyword() bool {
return _keywordBeg < tok && tok < _keywordEnd
}
+
+// Lookup returns corresponding keyword if ident is a keyword.
+func Lookup(ident string) Token {
+ if tok, isKeyword := keywords[ident]; isKeyword {
+ return tok
+ }
+ return Ident
+}
+
+func init() {
+ keywords = make(map[string]Token)
+ for i := _keywordBeg + 1; i < _keywordEnd; i++ {
+ keywords[tokens[i]] = i
+ }
+}
diff --git a/vendor/github.com/d5/tengo/script/variable.go b/vendor/github.com/d5/tengo/v2/variable.go
index df345115..481b36b8 100644
--- a/vendor/github.com/d5/tengo/script/variable.go
+++ b/vendor/github.com/d5/tengo/v2/variable.go
@@ -1,24 +1,21 @@
-package script
+package tengo
import (
"errors"
-
- "github.com/d5/tengo/objects"
)
// Variable is a user-defined variable for the script.
type Variable struct {
name string
- value objects.Object
+ value Object
}
// NewVariable creates a Variable.
func NewVariable(name string, value interface{}) (*Variable, error) {
- obj, err := objects.FromInterface(value)
+ obj, err := FromInterface(value)
if err != nil {
return nil, err
}
-
return &Variable{
name: name,
value: obj,
@@ -32,7 +29,7 @@ func (v *Variable) Name() string {
// Value returns an empty interface of the variable value.
func (v *Variable) Value() interface{} {
- return objects.ToInterface(v.value)
+ return ToInterface(v.value)
}
// ValueType returns the name of the value type.
@@ -43,107 +40,97 @@ func (v *Variable) ValueType() string {
// Int returns int value of the variable value.
// It returns 0 if the value is not convertible to int.
func (v *Variable) Int() int {
- c, _ := objects.ToInt(v.value)
-
+ c, _ := ToInt(v.value)
return c
}
-// Int64 returns int64 value of the variable value.
-// It returns 0 if the value is not convertible to int64.
+// Int64 returns int64 value of the variable value. It returns 0 if the value
+// is not convertible to int64.
func (v *Variable) Int64() int64 {
- c, _ := objects.ToInt64(v.value)
-
+ c, _ := ToInt64(v.value)
return c
}
-// Float returns float64 value of the variable value.
-// It returns 0.0 if the value is not convertible to float64.
+// Float returns float64 value of the variable value. It returns 0.0 if the
+// value is not convertible to float64.
func (v *Variable) Float() float64 {
- c, _ := objects.ToFloat64(v.value)
-
+ c, _ := ToFloat64(v.value)
return c
}
-// Char returns rune value of the variable value.
-// It returns 0 if the value is not convertible to rune.
+// Char returns rune value of the variable value. It returns 0 if the value is
+// not convertible to rune.
func (v *Variable) Char() rune {
- c, _ := objects.ToRune(v.value)
-
+ c, _ := ToRune(v.value)
return c
}
-// Bool returns bool value of the variable value.
-// It returns 0 if the value is not convertible to bool.
+// Bool returns bool value of the variable value. It returns 0 if the value is
+// not convertible to bool.
func (v *Variable) Bool() bool {
- c, _ := objects.ToBool(v.value)
-
+ c, _ := ToBool(v.value)
return c
}
-// Array returns []interface value of the variable value.
-// It returns 0 if the value is not convertible to []interface.
+// Array returns []interface value of the variable value. It returns 0 if the
+// value is not convertible to []interface.
func (v *Variable) Array() []interface{} {
switch val := v.value.(type) {
- case *objects.Array:
+ case *Array:
var arr []interface{}
for _, e := range val.Value {
- arr = append(arr, objects.ToInterface(e))
+ arr = append(arr, ToInterface(e))
}
return arr
}
-
return nil
}
-// Map returns map[string]interface{} value of the variable value.
-// It returns 0 if the value is not convertible to map[string]interface{}.
+// Map returns map[string]interface{} value of the variable value. It returns
+// 0 if the value is not convertible to map[string]interface{}.
func (v *Variable) Map() map[string]interface{} {
switch val := v.value.(type) {
- case *objects.Map:
+ case *Map:
kv := make(map[string]interface{})
for mk, mv := range val.Value {
- kv[mk] = objects.ToInterface(mv)
+ kv[mk] = ToInterface(mv)
}
return kv
}
-
return nil
}
-// String returns string value of the variable value.
-// It returns 0 if the value is not convertible to string.
+// String returns string value of the variable value. It returns 0 if the value
+// is not convertible to string.
func (v *Variable) String() string {
- c, _ := objects.ToString(v.value)
-
+ c, _ := ToString(v.value)
return c
}
-// Bytes returns a byte slice of the variable value.
-// It returns nil if the value is not convertible to byte slice.
+// Bytes returns a byte slice of the variable value. It returns nil if the
+// value is not convertible to byte slice.
func (v *Variable) Bytes() []byte {
- c, _ := objects.ToByteSlice(v.value)
-
+ c, _ := ToByteSlice(v.value)
return c
}
-// Error returns an error if the underlying value is error object.
-// If not, this returns nil.
+// Error returns an error if the underlying value is error object. If not,
+// this returns nil.
func (v *Variable) Error() error {
- err, ok := v.value.(*objects.Error)
+ err, ok := v.value.(*Error)
if ok {
return errors.New(err.String())
}
-
return nil
}
-// Object returns an underlying Object of the variable value.
-// Note that returned Object is a copy of an actual Object used in the script.
-func (v *Variable) Object() objects.Object {
+// Object returns an underlying Object of the variable value. Note that
+// returned Object is a copy of an actual Object used in the script.
+func (v *Variable) Object() Object {
return v.value
}
// IsUndefined returns true if the underlying value is undefined.
func (v *Variable) IsUndefined() bool {
- return v.value == objects.UndefinedValue
+ return v.value == UndefinedValue
}
diff --git a/vendor/github.com/d5/tengo/runtime/vm.go b/vendor/github.com/d5/tengo/v2/vm.go
index 07f6e530..783a54a9 100644
--- a/vendor/github.com/d5/tengo/runtime/vm.go
+++ b/vendor/github.com/d5/tengo/v2/vm.go
@@ -1,36 +1,31 @@
-package runtime
+package tengo
import (
"fmt"
"sync/atomic"
- "github.com/d5/tengo/compiler"
- "github.com/d5/tengo/compiler/source"
- "github.com/d5/tengo/compiler/token"
- "github.com/d5/tengo/objects"
+ "github.com/d5/tengo/v2/parser"
+ "github.com/d5/tengo/v2/token"
)
-const (
- // StackSize is the maximum stack size.
- StackSize = 2048
-
- // GlobalsSize is the maximum number of global variables.
- GlobalsSize = 1024
-
- // MaxFrames is the maximum number of function frames.
- MaxFrames = 1024
-)
+// frame represents a function call frame.
+type frame struct {
+ fn *CompiledFunction
+ freeVars []*ObjectPtr
+ ip int
+ basePointer int
+}
// VM is a virtual machine that executes the bytecode compiled by Compiler.
type VM struct {
- constants []objects.Object
- stack [StackSize]objects.Object
+ constants []Object
+ stack [StackSize]Object
sp int
- globals []objects.Object
- fileSet *source.FileSet
- frames [MaxFrames]Frame
+ globals []Object
+ fileSet *parser.SourceFileSet
+ frames [MaxFrames]frame
framesIndex int
- curFrame *Frame
+ curFrame *frame
curInsts []byte
ip int
aborting int64
@@ -40,11 +35,14 @@ type VM struct {
}
// NewVM creates a VM.
-func NewVM(bytecode *compiler.Bytecode, globals []objects.Object, maxAllocs int64) *VM {
+func NewVM(
+ bytecode *Bytecode,
+ globals []Object,
+ maxAllocs int64,
+) *VM {
if globals == nil {
- globals = make([]objects.Object, GlobalsSize)
+ globals = make([]Object, GlobalsSize)
}
-
v := &VM{
constants: bytecode.Constants,
sp: 0,
@@ -54,12 +52,10 @@ func NewVM(bytecode *compiler.Bytecode, globals []objects.Object, maxAllocs int6
ip: -1,
maxAllocs: maxAllocs,
}
-
v.frames[0].fn = bytecode.MainFunction
v.frames[0].ip = -1
v.curFrame = &v.frames[0]
v.curInsts = v.curFrame.fn.Instructions
-
return v
}
@@ -79,75 +75,52 @@ func (v *VM) Run() (err error) {
v.allocs = v.maxAllocs + 1
v.run()
-
atomic.StoreInt64(&v.aborting, 0)
-
err = v.err
if err != nil {
- filePos := v.fileSet.Position(v.curFrame.fn.SourcePos(v.ip - 1))
- err = fmt.Errorf("Runtime Error: %s\n\tat %s", err.Error(), filePos)
+ filePos := v.fileSet.Position(
+ v.curFrame.fn.SourcePos(v.ip - 1))
+ err = fmt.Errorf("Runtime Error: %s\n\tat %s",
+ err.Error(), filePos)
for v.framesIndex > 1 {
v.framesIndex--
v.curFrame = &v.frames[v.framesIndex-1]
-
- filePos = v.fileSet.Position(v.curFrame.fn.SourcePos(v.curFrame.ip - 1))
+ filePos = v.fileSet.Position(
+ v.curFrame.fn.SourcePos(v.curFrame.ip - 1))
err = fmt.Errorf("%s\n\tat %s", err.Error(), filePos)
}
return err
}
-
return nil
}
func (v *VM) run() {
- defer func() {
- if r := recover(); r != nil {
- if v.sp >= StackSize || v.framesIndex >= MaxFrames {
- v.err = ErrStackOverflow
- return
- }
-
- if v.ip < len(v.curInsts)-1 {
- if err, ok := r.(error); ok {
- v.err = err
- } else {
- v.err = fmt.Errorf("panic: %v", r)
- }
- }
- }
- }()
-
for atomic.LoadInt64(&v.aborting) == 0 {
v.ip++
switch v.curInsts[v.ip] {
- case compiler.OpConstant:
+ case parser.OpConstant:
v.ip += 2
cidx := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
v.stack[v.sp] = v.constants[cidx]
v.sp++
-
- case compiler.OpNull:
- v.stack[v.sp] = objects.UndefinedValue
+ case parser.OpNull:
+ v.stack[v.sp] = UndefinedValue
v.sp++
-
- case compiler.OpBinaryOp:
+ case parser.OpBinaryOp:
v.ip++
right := v.stack[v.sp-1]
left := v.stack[v.sp-2]
-
tok := token.Token(v.curInsts[v.ip])
res, e := left.BinaryOp(tok, right)
if e != nil {
v.sp -= 2
-
- if e == objects.ErrInvalidOperator {
+ if e == ErrInvalidOperator {
v.err = fmt.Errorf("invalid operation: %s %s %s",
left.TypeName(), tok.String(), right.TypeName())
return
}
-
v.err = e
return
}
@@ -160,185 +133,155 @@ func (v *VM) run() {
v.stack[v.sp-2] = res
v.sp--
-
- case compiler.OpEqual:
+ case parser.OpEqual:
right := v.stack[v.sp-1]
left := v.stack[v.sp-2]
v.sp -= 2
-
if left.Equals(right) {
- v.stack[v.sp] = objects.TrueValue
+ v.stack[v.sp] = TrueValue
} else {
- v.stack[v.sp] = objects.FalseValue
+ v.stack[v.sp] = FalseValue
}
v.sp++
-
- case compiler.OpNotEqual:
+ case parser.OpNotEqual:
right := v.stack[v.sp-1]
left := v.stack[v.sp-2]
v.sp -= 2
-
if left.Equals(right) {
- v.stack[v.sp] = objects.FalseValue
+ v.stack[v.sp] = FalseValue
} else {
- v.stack[v.sp] = objects.TrueValue
+ v.stack[v.sp] = TrueValue
}
v.sp++
-
- case compiler.OpPop:
+ case parser.OpPop:
v.sp--
-
- case compiler.OpTrue:
- v.stack[v.sp] = objects.TrueValue
+ case parser.OpTrue:
+ v.stack[v.sp] = TrueValue
v.sp++
-
- case compiler.OpFalse:
- v.stack[v.sp] = objects.FalseValue
+ case parser.OpFalse:
+ v.stack[v.sp] = FalseValue
v.sp++
-
- case compiler.OpLNot:
+ case parser.OpLNot:
operand := v.stack[v.sp-1]
v.sp--
-
if operand.IsFalsy() {
- v.stack[v.sp] = objects.TrueValue
+ v.stack[v.sp] = TrueValue
} else {
- v.stack[v.sp] = objects.FalseValue
+ v.stack[v.sp] = FalseValue
}
v.sp++
-
- case compiler.OpBComplement:
+ case parser.OpBComplement:
operand := v.stack[v.sp-1]
v.sp--
switch x := operand.(type) {
- case *objects.Int:
- var res objects.Object = &objects.Int{Value: ^x.Value}
-
+ case *Int:
+ var res Object = &Int{Value: ^x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = res
v.sp++
default:
- v.err = fmt.Errorf("invalid operation: ^%s", operand.TypeName())
+ v.err = fmt.Errorf("invalid operation: ^%s",
+ operand.TypeName())
return
}
-
- case compiler.OpMinus:
+ case parser.OpMinus:
operand := v.stack[v.sp-1]
v.sp--
switch x := operand.(type) {
- case *objects.Int:
- var res objects.Object = &objects.Int{Value: -x.Value}
-
+ case *Int:
+ var res Object = &Int{Value: -x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = res
v.sp++
- case *objects.Float:
- var res objects.Object = &objects.Float{Value: -x.Value}
-
+ case *Float:
+ var res Object = &Float{Value: -x.Value}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = res
v.sp++
default:
- v.err = fmt.Errorf("invalid operation: -%s", operand.TypeName())
+ v.err = fmt.Errorf("invalid operation: -%s",
+ operand.TypeName())
return
}
-
- case compiler.OpJumpFalsy:
+ case parser.OpJumpFalsy:
v.ip += 2
v.sp--
if v.stack[v.sp].IsFalsy() {
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
v.ip = pos - 1
}
-
- case compiler.OpAndJump:
+ case parser.OpAndJump:
v.ip += 2
-
if v.stack[v.sp-1].IsFalsy() {
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
v.ip = pos - 1
} else {
v.sp--
}
-
- case compiler.OpOrJump:
+ case parser.OpOrJump:
v.ip += 2
-
if v.stack[v.sp-1].IsFalsy() {
v.sp--
} else {
pos := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
v.ip = pos - 1
}
-
- case compiler.OpJump:
+ case parser.OpJump:
pos := int(v.curInsts[v.ip+2]) | int(v.curInsts[v.ip+1])<<8
v.ip = pos - 1
-
- case compiler.OpSetGlobal:
+ case parser.OpSetGlobal:
v.ip += 2
v.sp--
-
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
v.globals[globalIndex] = v.stack[v.sp]
-
- case compiler.OpSetSelGlobal:
+ case parser.OpSetSelGlobal:
v.ip += 3
globalIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
numSelectors := int(v.curInsts[v.ip])
// selectors and RHS value
- selectors := make([]objects.Object, numSelectors)
+ selectors := make([]Object, numSelectors)
for i := 0; i < numSelectors; i++ {
selectors[i] = v.stack[v.sp-numSelectors+i]
}
-
val := v.stack[v.sp-numSelectors-1]
v.sp -= numSelectors + 1
-
- if e := indexAssign(v.globals[globalIndex], val, selectors); e != nil {
+ e := indexAssign(v.globals[globalIndex], val, selectors)
+ if e != nil {
v.err = e
return
}
-
- case compiler.OpGetGlobal:
+ case parser.OpGetGlobal:
v.ip += 2
globalIndex := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
-
val := v.globals[globalIndex]
-
v.stack[v.sp] = val
v.sp++
-
- case compiler.OpArray:
+ case parser.OpArray:
v.ip += 2
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
- var elements []objects.Object
+ var elements []Object
for i := v.sp - numElements; i < v.sp; i++ {
elements = append(elements, v.stack[i])
}
v.sp -= numElements
- var arr objects.Object = &objects.Array{Value: elements}
-
+ var arr Object = &Array{Value: elements}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
@@ -347,355 +290,260 @@ func (v *VM) run() {
v.stack[v.sp] = arr
v.sp++
-
- case compiler.OpMap:
+ case parser.OpMap:
v.ip += 2
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
-
- kv := make(map[string]objects.Object)
+ kv := make(map[string]Object)
for i := v.sp - numElements; i < v.sp; i += 2 {
key := v.stack[i]
value := v.stack[i+1]
- kv[key.(*objects.String).Value] = value
+ kv[key.(*String).Value] = value
}
v.sp -= numElements
- var m objects.Object = &objects.Map{Value: kv}
-
+ var m Object = &Map{Value: kv}
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = m
v.sp++
-
- case compiler.OpError:
+ case parser.OpError:
value := v.stack[v.sp-1]
-
- var e objects.Object = &objects.Error{
+ var e Object = &Error{
Value: value,
}
-
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp-1] = e
-
- case compiler.OpImmutable:
+ case parser.OpImmutable:
value := v.stack[v.sp-1]
-
switch value := value.(type) {
- case *objects.Array:
- var immutableArray objects.Object = &objects.ImmutableArray{
+ case *Array:
+ var immutableArray Object = &ImmutableArray{
Value: value.Value,
}
-
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp-1] = immutableArray
- case *objects.Map:
- var immutableMap objects.Object = &objects.ImmutableMap{
+ case *Map:
+ var immutableMap Object = &ImmutableMap{
Value: value.Value,
}
-
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp-1] = immutableMap
}
-
- case compiler.OpIndex:
+ case parser.OpIndex:
index := v.stack[v.sp-1]
left := v.stack[v.sp-2]
v.sp -= 2
- switch left := left.(type) {
- case objects.Indexable:
- val, e := left.IndexGet(index)
- if e != nil {
-
- if e == objects.ErrInvalidIndexType {
- v.err = fmt.Errorf("invalid index type: %s", index.TypeName())
- return
- }
-
- v.err = e
+ val, err := left.IndexGet(index)
+ if err != nil {
+ if err == ErrNotIndexable {
+ v.err = fmt.Errorf("not indexable: %s", index.TypeName())
return
}
- if val == nil {
- val = objects.UndefinedValue
- }
-
- v.stack[v.sp] = val
- v.sp++
-
- case *objects.Error: // e.value
- key, ok := index.(*objects.String)
- if !ok || key.Value != "value" {
- v.err = fmt.Errorf("invalid index on error")
+ if err == ErrInvalidIndexType {
+ v.err = fmt.Errorf("invalid index type: %s",
+ index.TypeName())
return
}
-
- v.stack[v.sp] = left.Value
- v.sp++
-
- default:
- v.err = fmt.Errorf("not indexable: %s", left.TypeName())
+ v.err = err
return
}
-
- case compiler.OpSliceIndex:
+ if val == nil {
+ val = UndefinedValue
+ }
+ v.stack[v.sp] = val
+ v.sp++
+ case parser.OpSliceIndex:
high := v.stack[v.sp-1]
low := v.stack[v.sp-2]
left := v.stack[v.sp-3]
v.sp -= 3
var lowIdx int64
- if low != objects.UndefinedValue {
- if low, ok := low.(*objects.Int); ok {
+ if low != UndefinedValue {
+ if low, ok := low.(*Int); ok {
lowIdx = low.Value
} else {
- v.err = fmt.Errorf("invalid slice index type: %s", low.TypeName())
+ v.err = fmt.Errorf("invalid slice index type: %s",
+ low.TypeName())
return
}
}
switch left := left.(type) {
- case *objects.Array:
+ case *Array:
numElements := int64(len(left.Value))
var highIdx int64
- if high == objects.UndefinedValue {
+ if high == UndefinedValue {
highIdx = numElements
- } else if high, ok := high.(*objects.Int); ok {
+ } else if high, ok := high.(*Int); ok {
highIdx = high.Value
} else {
- v.err = fmt.Errorf("invalid slice index type: %s", high.TypeName())
+ v.err = fmt.Errorf("invalid slice index type: %s",
+ high.TypeName())
return
}
-
if lowIdx > highIdx {
- v.err = fmt.Errorf("invalid slice index: %d > %d", lowIdx, highIdx)
+ v.err = fmt.Errorf("invalid slice index: %d > %d",
+ lowIdx, highIdx)
return
}
-
if lowIdx < 0 {
lowIdx = 0
} else if lowIdx > numElements {
lowIdx = numElements
}
-
if highIdx < 0 {
highIdx = 0
} else if highIdx > numElements {
highIdx = numElements
}
-
- var val objects.Object = &objects.Array{Value: left.Value[lowIdx:highIdx]}
-
+ var val Object = &Array{
+ Value: left.Value[lowIdx:highIdx],
+ }
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = val
v.sp++
-
- case *objects.ImmutableArray:
+ case *ImmutableArray:
numElements := int64(len(left.Value))
var highIdx int64
- if high == objects.UndefinedValue {
+ if high == UndefinedValue {
highIdx = numElements
- } else if high, ok := high.(*objects.Int); ok {
+ } else if high, ok := high.(*Int); ok {
highIdx = high.Value
} else {
- v.err = fmt.Errorf("invalid slice index type: %s", high.TypeName())
+ v.err = fmt.Errorf("invalid slice index type: %s",
+ high.TypeName())
return
}
-
if lowIdx > highIdx {
- v.err = fmt.Errorf("invalid slice index: %d > %d", lowIdx, highIdx)
+ v.err = fmt.Errorf("invalid slice index: %d > %d",
+ lowIdx, highIdx)
return
}
-
if lowIdx < 0 {
lowIdx = 0
} else if lowIdx > numElements {
lowIdx = numElements
}
-
if highIdx < 0 {
highIdx = 0
} else if highIdx > numElements {
highIdx = numElements
}
-
- var val objects.Object = &objects.Array{Value: left.Value[lowIdx:highIdx]}
-
+ var val Object = &Array{
+ Value: left.Value[lowIdx:highIdx],
+ }
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = val
v.sp++
-
- case *objects.String:
+ case *String:
numElements := int64(len(left.Value))
var highIdx int64
- if high == objects.UndefinedValue {
+ if high == UndefinedValue {
highIdx = numElements
- } else if high, ok := high.(*objects.Int); ok {
+ } else if high, ok := high.(*Int); ok {
highIdx = high.Value
} else {
- v.err = fmt.Errorf("invalid slice index type: %s", high.TypeName())
+ v.err = fmt.Errorf("invalid slice index type: %s",
+ high.TypeName())
return
}
-
if lowIdx > highIdx {
- v.err = fmt.Errorf("invalid slice index: %d > %d", lowIdx, highIdx)
+ v.err = fmt.Errorf("invalid slice index: %d > %d",
+ lowIdx, highIdx)
return
}
-
if lowIdx < 0 {
lowIdx = 0
} else if lowIdx > numElements {
lowIdx = numElements
}
-
if highIdx < 0 {
highIdx = 0
} else if highIdx > numElements {
highIdx = numElements
}
-
- var val objects.Object = &objects.String{Value: left.Value[lowIdx:highIdx]}
-
+ var val Object = &String{
+ Value: left.Value[lowIdx:highIdx],
+ }
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = val
v.sp++
-
- case *objects.Bytes:
+ case *Bytes:
numElements := int64(len(left.Value))
var highIdx int64
- if high == objects.UndefinedValue {
+ if high == UndefinedValue {
highIdx = numElements
- } else if high, ok := high.(*objects.Int); ok {
+ } else if high, ok := high.(*Int); ok {
highIdx = high.Value
} else {
- v.err = fmt.Errorf("invalid slice index type: %s", high.TypeName())
+ v.err = fmt.Errorf("invalid slice index type: %s",
+ high.TypeName())
return
}
-
if lowIdx > highIdx {
- v.err = fmt.Errorf("invalid slice index: %d > %d", lowIdx, highIdx)
+ v.err = fmt.Errorf("invalid slice index: %d > %d",
+ lowIdx, highIdx)
return
}
-
if lowIdx < 0 {
lowIdx = 0
} else if lowIdx > numElements {
lowIdx = numElements
}
-
if highIdx < 0 {
highIdx = 0
} else if highIdx > numElements {
highIdx = numElements
}
-
- var val objects.Object = &objects.Bytes{Value: left.Value[lowIdx:highIdx]}
-
+ var val Object = &Bytes{
+ Value: left.Value[lowIdx:highIdx],
+ }
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = val
v.sp++
}
-
- case compiler.OpCall:
+ case parser.OpCall:
numArgs := int(v.curInsts[v.ip+1])
v.ip++
-
value := v.stack[v.sp-1-numArgs]
-
- switch callee := value.(type) {
- case *objects.Closure:
- if callee.Fn.VarArgs {
- // if the closure is variadic,
- // roll up all variadic parameters into an array
- realArgs := callee.Fn.NumParameters - 1
- varArgs := numArgs - realArgs
- if varArgs >= 0 {
- numArgs = realArgs + 1
- args := make([]objects.Object, varArgs)
- spStart := v.sp - varArgs
- for i := spStart; i < v.sp; i++ {
- args[i-spStart] = v.stack[i]
- }
- v.stack[spStart] = &objects.Array{Value: args}
- v.sp = spStart + 1
- }
- }
-
- if numArgs != callee.Fn.NumParameters {
- if callee.Fn.VarArgs {
- v.err = fmt.Errorf("wrong number of arguments: want>=%d, got=%d",
- callee.Fn.NumParameters-1, numArgs)
- } else {
- v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d",
- callee.Fn.NumParameters, numArgs)
- }
- return
- }
-
- // test if it's tail-call
- if callee.Fn == v.curFrame.fn { // recursion
- nextOp := v.curInsts[v.ip+1]
- if nextOp == compiler.OpReturn ||
- (nextOp == compiler.OpPop && compiler.OpReturn == v.curInsts[v.ip+2]) {
- for p := 0; p < numArgs; p++ {
- v.stack[v.curFrame.basePointer+p] = v.stack[v.sp-numArgs+p]
- }
- v.sp -= numArgs + 1
- v.ip = -1 // reset IP to beginning of the frame
- continue
- }
- }
-
- // update call frame
- v.curFrame.ip = v.ip // store current ip before call
- v.curFrame = &(v.frames[v.framesIndex])
- v.curFrame.fn = callee.Fn
- v.curFrame.freeVars = callee.Free
- v.curFrame.basePointer = v.sp - numArgs
- v.curInsts = callee.Fn.Instructions
- v.ip = -1
- v.framesIndex++
- v.sp = v.sp - numArgs + callee.Fn.NumLocals
-
- case *objects.CompiledFunction:
+ if !value.CanCall() {
+ v.err = fmt.Errorf("not callable: %s", value.TypeName())
+ return
+ }
+ if callee, ok := value.(*CompiledFunction); ok {
if callee.VarArgs {
// if the closure is variadic,
// roll up all variadic parameters into an array
@@ -703,22 +551,23 @@ func (v *VM) run() {
varArgs := numArgs - realArgs
if varArgs >= 0 {
numArgs = realArgs + 1
- args := make([]objects.Object, varArgs)
+ args := make([]Object, varArgs)
spStart := v.sp - varArgs
for i := spStart; i < v.sp; i++ {
args[i-spStart] = v.stack[i]
}
- v.stack[spStart] = &objects.Array{Value: args}
+ v.stack[spStart] = &Array{Value: args}
v.sp = spStart + 1
}
}
-
if numArgs != callee.NumParameters {
if callee.VarArgs {
- v.err = fmt.Errorf("wrong number of arguments: want>=%d, got=%d",
+ v.err = fmt.Errorf(
+ "wrong number of arguments: want>=%d, got=%d",
callee.NumParameters-1, numArgs)
} else {
- v.err = fmt.Errorf("wrong number of arguments: want=%d, got=%d",
+ v.err = fmt.Errorf(
+ "wrong number of arguments: want=%d, got=%d",
callee.NumParameters, numArgs)
}
return
@@ -727,321 +576,271 @@ func (v *VM) run() {
// test if it's tail-call
if callee == v.curFrame.fn { // recursion
nextOp := v.curInsts[v.ip+1]
- if nextOp == compiler.OpReturn ||
- (nextOp == compiler.OpPop && compiler.OpReturn == v.curInsts[v.ip+2]) {
+ if nextOp == parser.OpReturn ||
+ (nextOp == parser.OpPop &&
+ parser.OpReturn == v.curInsts[v.ip+2]) {
for p := 0; p < numArgs; p++ {
- v.stack[v.curFrame.basePointer+p] = v.stack[v.sp-numArgs+p]
+ v.stack[v.curFrame.basePointer+p] =
+ v.stack[v.sp-numArgs+p]
}
v.sp -= numArgs + 1
v.ip = -1 // reset IP to beginning of the frame
continue
}
}
+ if v.framesIndex >= MaxFrames {
+ v.err = ErrStackOverflow
+ return
+ }
// update call frame
v.curFrame.ip = v.ip // store current ip before call
v.curFrame = &(v.frames[v.framesIndex])
v.curFrame.fn = callee
- v.curFrame.freeVars = nil
+ v.curFrame.freeVars = callee.Free
v.curFrame.basePointer = v.sp - numArgs
v.curInsts = callee.Instructions
v.ip = -1
v.framesIndex++
v.sp = v.sp - numArgs + callee.NumLocals
-
- case objects.Callable:
- var args []objects.Object
+ } else {
+ var args []Object
args = append(args, v.stack[v.sp-numArgs:v.sp]...)
-
- ret, e := callee.Call(args...)
+ ret, e := value.Call(args...)
v.sp -= numArgs + 1
// runtime error
if e != nil {
- if e == objects.ErrWrongNumArguments {
- v.err = fmt.Errorf("wrong number of arguments in call to '%s'",
+ if e == ErrWrongNumArguments {
+ v.err = fmt.Errorf(
+ "wrong number of arguments in call to '%s'",
value.TypeName())
return
}
-
- if e, ok := e.(objects.ErrInvalidArgumentType); ok {
- v.err = fmt.Errorf("invalid type for argument '%s' in call to '%s': expected %s, found %s",
+ if e, ok := e.(ErrInvalidArgumentType); ok {
+ v.err = fmt.Errorf(
+ "invalid type for argument '%s' in call to '%s': "+
+ "expected %s, found %s",
e.Name, value.TypeName(), e.Expected, e.Found)
return
}
-
v.err = e
return
}
// nil return -> undefined
if ret == nil {
- ret = objects.UndefinedValue
+ ret = UndefinedValue
}
-
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = ret
v.sp++
-
- default:
- v.err = fmt.Errorf("not callable: %s", callee.TypeName())
- return
}
-
- case compiler.OpReturn:
+ case parser.OpReturn:
v.ip++
- var retVal objects.Object
+ var retVal Object
if int(v.curInsts[v.ip]) == 1 {
retVal = v.stack[v.sp-1]
} else {
- retVal = objects.UndefinedValue
+ retVal = UndefinedValue
}
//v.sp--
-
v.framesIndex--
v.curFrame = &v.frames[v.framesIndex-1]
v.curInsts = v.curFrame.fn.Instructions
v.ip = v.curFrame.ip
-
//v.sp = lastFrame.basePointer - 1
v.sp = v.frames[v.framesIndex].basePointer
-
// skip stack overflow check because (newSP) <= (oldSP)
v.stack[v.sp-1] = retVal
//v.sp++
-
- case compiler.OpDefineLocal:
+ case parser.OpDefineLocal:
v.ip++
localIndex := int(v.curInsts[v.ip])
-
sp := v.curFrame.basePointer + localIndex
// local variables can be mutated by other actions
// so always store the copy of popped value
val := v.stack[v.sp-1]
v.sp--
-
v.stack[sp] = val
-
- case compiler.OpSetLocal:
+ case parser.OpSetLocal:
localIndex := int(v.curInsts[v.ip+1])
v.ip++
-
sp := v.curFrame.basePointer + localIndex
- // update pointee of v.stack[sp] instead of replacing the pointer itself.
- // this is needed because there can be free variables referencing the same local variables.
+ // update pointee of v.stack[sp] instead of replacing the pointer
+ // itself. this is needed because there can be free variables
+ // referencing the same local variables.
val := v.stack[v.sp-1]
v.sp--
-
- if obj, ok := v.stack[sp].(*objects.ObjectPtr); ok {
+ if obj, ok := v.stack[sp].(*ObjectPtr); ok {
*obj.Value = val
val = obj
}
v.stack[sp] = val // also use a copy of popped value
-
- case compiler.OpSetSelLocal:
+ case parser.OpSetSelLocal:
localIndex := int(v.curInsts[v.ip+1])
numSelectors := int(v.curInsts[v.ip+2])
v.ip += 2
// selectors and RHS value
- selectors := make([]objects.Object, numSelectors)
+ selectors := make([]Object, numSelectors)
for i := 0; i < numSelectors; i++ {
selectors[i] = v.stack[v.sp-numSelectors+i]
}
-
val := v.stack[v.sp-numSelectors-1]
v.sp -= numSelectors + 1
-
dst := v.stack[v.curFrame.basePointer+localIndex]
- if obj, ok := dst.(*objects.ObjectPtr); ok {
+ if obj, ok := dst.(*ObjectPtr); ok {
dst = *obj.Value
}
-
if e := indexAssign(dst, val, selectors); e != nil {
v.err = e
return
}
-
- case compiler.OpGetLocal:
+ case parser.OpGetLocal:
v.ip++
localIndex := int(v.curInsts[v.ip])
-
val := v.stack[v.curFrame.basePointer+localIndex]
-
- if obj, ok := val.(*objects.ObjectPtr); ok {
+ if obj, ok := val.(*ObjectPtr); ok {
val = *obj.Value
}
-
v.stack[v.sp] = val
v.sp++
-
- case compiler.OpGetBuiltin:
+ case parser.OpGetBuiltin:
v.ip++
builtinIndex := int(v.curInsts[v.ip])
-
- v.stack[v.sp] = objects.Builtins[builtinIndex]
+ v.stack[v.sp] = builtinFuncs[builtinIndex]
v.sp++
-
- case compiler.OpClosure:
+ case parser.OpClosure:
v.ip += 3
constIndex := int(v.curInsts[v.ip-1]) | int(v.curInsts[v.ip-2])<<8
numFree := int(v.curInsts[v.ip])
-
- fn, ok := v.constants[constIndex].(*objects.CompiledFunction)
+ fn, ok := v.constants[constIndex].(*CompiledFunction)
if !ok {
v.err = fmt.Errorf("not function: %s", fn.TypeName())
return
}
-
- free := make([]*objects.ObjectPtr, numFree)
+ free := make([]*ObjectPtr, numFree)
for i := 0; i < numFree; i++ {
switch freeVar := (v.stack[v.sp-numFree+i]).(type) {
- case *objects.ObjectPtr:
+ case *ObjectPtr:
free[i] = freeVar
default:
- free[i] = &objects.ObjectPtr{Value: &v.stack[v.sp-numFree+i]}
+ free[i] = &ObjectPtr{
+ Value: &v.stack[v.sp-numFree+i],
+ }
}
}
-
v.sp -= numFree
-
- var cl = &objects.Closure{
- Fn: fn,
- Free: free,
+ cl := &CompiledFunction{
+ Instructions: fn.Instructions,
+ NumLocals: fn.NumLocals,
+ NumParameters: fn.NumParameters,
+ VarArgs: fn.VarArgs,
+ Free: free,
}
-
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = cl
v.sp++
-
- case compiler.OpGetFreePtr:
+ case parser.OpGetFreePtr:
v.ip++
freeIndex := int(v.curInsts[v.ip])
-
val := v.curFrame.freeVars[freeIndex]
-
v.stack[v.sp] = val
v.sp++
-
- case compiler.OpGetFree:
+ case parser.OpGetFree:
v.ip++
freeIndex := int(v.curInsts[v.ip])
-
val := *v.curFrame.freeVars[freeIndex].Value
-
v.stack[v.sp] = val
v.sp++
-
- case compiler.OpSetFree:
+ case parser.OpSetFree:
v.ip++
freeIndex := int(v.curInsts[v.ip])
-
*v.curFrame.freeVars[freeIndex].Value = v.stack[v.sp-1]
-
v.sp--
-
- case compiler.OpGetLocalPtr:
+ case parser.OpGetLocalPtr:
v.ip++
localIndex := int(v.curInsts[v.ip])
-
sp := v.curFrame.basePointer + localIndex
val := v.stack[sp]
-
- var freeVar *objects.ObjectPtr
- if obj, ok := val.(*objects.ObjectPtr); ok {
+ var freeVar *ObjectPtr
+ if obj, ok := val.(*ObjectPtr); ok {
freeVar = obj
} else {
- freeVar = &objects.ObjectPtr{Value: &val}
+ freeVar = &ObjectPtr{Value: &val}
v.stack[sp] = freeVar
}
-
v.stack[v.sp] = freeVar
v.sp++
-
- case compiler.OpSetSelFree:
+ case parser.OpSetSelFree:
v.ip += 2
freeIndex := int(v.curInsts[v.ip-1])
numSelectors := int(v.curInsts[v.ip])
// selectors and RHS value
- selectors := make([]objects.Object, numSelectors)
+ selectors := make([]Object, numSelectors)
for i := 0; i < numSelectors; i++ {
selectors[i] = v.stack[v.sp-numSelectors+i]
}
val := v.stack[v.sp-numSelectors-1]
v.sp -= numSelectors + 1
-
- if e := indexAssign(*v.curFrame.freeVars[freeIndex].Value, val, selectors); e != nil {
+ e := indexAssign(*v.curFrame.freeVars[freeIndex].Value,
+ val, selectors)
+ if e != nil {
v.err = e
return
}
-
- case compiler.OpIteratorInit:
- var iterator objects.Object
-
+ case parser.OpIteratorInit:
+ var iterator Object
dst := v.stack[v.sp-1]
v.sp--
-
- iterable, ok := dst.(objects.Iterable)
- if !ok {
+ if !dst.CanIterate() {
v.err = fmt.Errorf("not iterable: %s", dst.TypeName())
return
}
-
- iterator = iterable.Iterate()
-
+ iterator = dst.Iterate()
v.allocs--
if v.allocs == 0 {
v.err = ErrObjectAllocLimit
return
}
-
v.stack[v.sp] = iterator
v.sp++
-
- case compiler.OpIteratorNext:
+ case parser.OpIteratorNext:
iterator := v.stack[v.sp-1]
v.sp--
-
- hasMore := iterator.(objects.Iterator).Next()
-
+ hasMore := iterator.(Iterator).Next()
if hasMore {
- v.stack[v.sp] = objects.TrueValue
+ v.stack[v.sp] = TrueValue
} else {
- v.stack[v.sp] = objects.FalseValue
+ v.stack[v.sp] = FalseValue
}
v.sp++
-
- case compiler.OpIteratorKey:
+ case parser.OpIteratorKey:
iterator := v.stack[v.sp-1]
v.sp--
-
- val := iterator.(objects.Iterator).Key()
-
+ val := iterator.(Iterator).Key()
v.stack[v.sp] = val
v.sp++
-
- case compiler.OpIteratorValue:
+ case parser.OpIteratorValue:
iterator := v.stack[v.sp-1]
v.sp--
-
- val := iterator.(objects.Iterator).Value()
-
+ val := iterator.(Iterator).Value()
v.stack[v.sp] = val
v.sp++
-
+ case parser.OpSuspend:
+ return
default:
v.err = fmt.Errorf("unknown opcode: %d", v.curInsts[v.ip])
return
@@ -1054,39 +853,31 @@ func (v *VM) IsStackEmpty() bool {
return v.sp == 0
}
-func indexAssign(dst, src objects.Object, selectors []objects.Object) error {
+func indexAssign(dst, src Object, selectors []Object) error {
numSel := len(selectors)
-
for sidx := numSel - 1; sidx > 0; sidx-- {
- indexable, ok := dst.(objects.Indexable)
- if !ok {
- return fmt.Errorf("not indexable: %s", dst.TypeName())
- }
-
- next, err := indexable.IndexGet(selectors[sidx])
+ next, err := dst.IndexGet(selectors[sidx])
if err != nil {
- if err == objects.ErrInvalidIndexType {
- return fmt.Errorf("invalid index type: %s", selectors[sidx].TypeName())
+ if err == ErrNotIndexable {
+ return fmt.Errorf("not indexable: %s", dst.TypeName())
+ }
+ if err == ErrInvalidIndexType {
+ return fmt.Errorf("invalid index type: %s",
+ selectors[sidx].TypeName())
}
-
return err
}
-
dst = next
}
- indexAssignable, ok := dst.(objects.IndexAssignable)
- if !ok {
- return fmt.Errorf("not index-assignable: %s", dst.TypeName())
- }
-
- if err := indexAssignable.IndexSet(selectors[0], src); err != nil {
- if err == objects.ErrInvalidIndexValueType {
+ if err := dst.IndexSet(selectors[0], src); err != nil {
+ if err == ErrNotIndexAssignable {
+ return fmt.Errorf("not index-assignable: %s", dst.TypeName())
+ }
+ if err == ErrInvalidIndexValueType {
return fmt.Errorf("invaid index value type: %s", src.TypeName())
}
-
return err
}
-
return nil
}