mirror of
https://github.com/cwinfo/matterbridge.git
synced 2024-11-22 01:10:27 +00:00
Update to tengo v2 (#976)
This commit is contained in:
parent
0f708daf2d
commit
9d84d6dd64
@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/internal"
|
"github.com/42wim/matterbridge/internal"
|
||||||
"github.com/d5/tengo/script"
|
"github.com/d5/tengo/v2"
|
||||||
"github.com/d5/tengo/stdlib"
|
"github.com/d5/tengo/v2/stdlib"
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/matterbridge/emoji"
|
"github.com/matterbridge/emoji"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -514,7 +514,7 @@ func modifyMessageTengo(filename string, msg *config.Message) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s := script.New(res)
|
s := tengo.NewScript(res)
|
||||||
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
||||||
_ = s.Add("msgText", msg.Text)
|
_ = s.Add("msgText", msg.Text)
|
||||||
_ = s.Add("msgUsername", msg.Username)
|
_ = s.Add("msgUsername", msg.Username)
|
||||||
@ -541,7 +541,7 @@ func (gw *Gateway) modifyUsernameTengo(msg *config.Message, br *bridge.Bridge) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
s := script.New(res)
|
s := tengo.NewScript(res)
|
||||||
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
||||||
_ = s.Add("result", "")
|
_ = s.Add("result", "")
|
||||||
_ = s.Add("msgText", msg.Text)
|
_ = s.Add("msgText", msg.Text)
|
||||||
@ -580,7 +580,7 @@ func (gw *Gateway) modifySendMessageTengo(origmsg *config.Message, msg *config.M
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s := script.New(res)
|
s := tengo.NewScript(res)
|
||||||
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
|
||||||
_ = s.Add("inAccount", origmsg.Account)
|
_ = s.Add("inAccount", origmsg.Account)
|
||||||
_ = s.Add("inProtocol", origmsg.Protocol)
|
_ = s.Add("inProtocol", origmsg.Protocol)
|
||||||
|
2
go.mod
2
go.mod
@ -7,7 +7,7 @@ require (
|
|||||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0
|
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0
|
||||||
github.com/Rhymen/go-whatsapp v0.1.0
|
github.com/Rhymen/go-whatsapp v0.1.0
|
||||||
github.com/bwmarrin/discordgo v0.20.2
|
github.com/bwmarrin/discordgo v0.20.2
|
||||||
github.com/d5/tengo v1.24.8
|
github.com/d5/tengo/v2 v2.0.2
|
||||||
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible
|
||||||
|
4
go.sum
4
go.sum
@ -33,8 +33,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
|||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/d5/tengo v1.24.8 h1:PRJ+NWt7ae/9sSbIfThOBTkPSvNV+dwYoBAvwfNgNJY=
|
github.com/d5/tengo/v2 v2.0.2 h1:3APkPZPc1FExaJoWrN5YzvDqc6GNkQH6ehmCRDmN83I=
|
||||||
github.com/d5/tengo v1.24.8/go.mod h1:VhLq8Q2QFhCIJO3NhvM934qOThykMqJi9y9Siqd1ocQ=
|
github.com/d5/tengo/v2 v2.0.2/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
17
vendor/github.com/d5/tengo/.travis.yml
generated
vendored
17
vendor/github.com/d5/tengo/.travis.yml
generated
vendored
@ -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
|
|
35
vendor/github.com/d5/tengo/compiler/ast/array_lit.go
generated
vendored
35
vendor/github.com/d5/tengo/compiler/ast/array_lit.go
generated
vendored
@ -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, ", ") + "]"
|
|
||||||
}
|
|
40
vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go
generated
vendored
40
vendor/github.com/d5/tengo/compiler/ast/assign_stmt.go
generated
vendored
@ -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, ", ")
|
|
||||||
}
|
|
5
vendor/github.com/d5/tengo/compiler/ast/ast.go
generated
vendored
5
vendor/github.com/d5/tengo/compiler/ast/ast.go
generated
vendored
@ -1,5 +0,0 @@
|
|||||||
package ast
|
|
||||||
|
|
||||||
const (
|
|
||||||
nullRep = "<null>"
|
|
||||||
)
|
|
25
vendor/github.com/d5/tengo/compiler/ast/bad_expr.go
generated
vendored
25
vendor/github.com/d5/tengo/compiler/ast/bad_expr.go
generated
vendored
@ -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>"
|
|
||||||
}
|
|
25
vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go
generated
vendored
25
vendor/github.com/d5/tengo/compiler/ast/bad_stmt.go
generated
vendored
@ -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>"
|
|
||||||
}
|
|
30
vendor/github.com/d5/tengo/compiler/ast/binary_expr.go
generated
vendored
30
vendor/github.com/d5/tengo/compiler/ast/binary_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
35
vendor/github.com/d5/tengo/compiler/ast/block_stmt.go
generated
vendored
35
vendor/github.com/d5/tengo/compiler/ast/block_stmt.go
generated
vendored
@ -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, "; ") + "}"
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/bool_lit.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/bool_lit.go
generated
vendored
@ -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
|
|
||||||
}
|
|
38
vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go
generated
vendored
38
vendor/github.com/d5/tengo/compiler/ast/branch_stmt.go
generated
vendored
@ -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
|
|
||||||
}
|
|
36
vendor/github.com/d5/tengo/compiler/ast/call_expr.go
generated
vendored
36
vendor/github.com/d5/tengo/compiler/ast/call_expr.go
generated
vendored
@ -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, ", ") + ")"
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/char_lit.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/char_lit.go
generated
vendored
@ -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
|
|
||||||
}
|
|
30
vendor/github.com/d5/tengo/compiler/ast/cond_expr.go
generated
vendored
30
vendor/github.com/d5/tengo/compiler/ast/cond_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/empty_stmt.go
generated
vendored
@ -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 ";"
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/error_expr.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/error_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
27
vendor/github.com/d5/tengo/compiler/ast/export_stmt.go
generated
vendored
27
vendor/github.com/d5/tengo/compiler/ast/export_stmt.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
7
vendor/github.com/d5/tengo/compiler/ast/expr.go
generated
vendored
7
vendor/github.com/d5/tengo/compiler/ast/expr.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
package ast
|
|
||||||
|
|
||||||
// Expr represents an expression node in the AST.
|
|
||||||
type Expr interface {
|
|
||||||
Node
|
|
||||||
exprNode()
|
|
||||||
}
|
|
24
vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go
generated
vendored
24
vendor/github.com/d5/tengo/compiler/ast/expr_stmt.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/float_lit.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/float_lit.go
generated
vendored
@ -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
|
|
||||||
}
|
|
32
vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go
generated
vendored
32
vendor/github.com/d5/tengo/compiler/ast/for_in_stmt.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
43
vendor/github.com/d5/tengo/compiler/ast/for_stmt.go
generated
vendored
43
vendor/github.com/d5/tengo/compiler/ast/for_stmt.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
25
vendor/github.com/d5/tengo/compiler/ast/func_lit.go
generated
vendored
25
vendor/github.com/d5/tengo/compiler/ast/func_lit.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
25
vendor/github.com/d5/tengo/compiler/ast/func_type.go
generated
vendored
25
vendor/github.com/d5/tengo/compiler/ast/func_type.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/ident.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/ident.go
generated
vendored
@ -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
|
|
||||||
}
|
|
40
vendor/github.com/d5/tengo/compiler/ast/if_stmt.go
generated
vendored
40
vendor/github.com/d5/tengo/compiler/ast/if_stmt.go
generated
vendored
@ -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
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/immutable_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/import_expr.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/import_expr.go
generated
vendored
@ -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 + `")"`
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/inc_dec_stmt.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
32
vendor/github.com/d5/tengo/compiler/ast/index_expr.go
generated
vendored
32
vendor/github.com/d5/tengo/compiler/ast/index_expr.go
generated
vendored
@ -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 + "]"
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/int_lit.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/int_lit.go
generated
vendored
@ -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
|
|
||||||
}
|
|
27
vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go
generated
vendored
27
vendor/github.com/d5/tengo/compiler/ast/map_element_lit.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
35
vendor/github.com/d5/tengo/compiler/ast/map_lit.go
generated
vendored
35
vendor/github.com/d5/tengo/compiler/ast/map_lit.go
generated
vendored
@ -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, ", ") + "}"
|
|
||||||
}
|
|
13
vendor/github.com/d5/tengo/compiler/ast/node.go
generated
vendored
13
vendor/github.com/d5/tengo/compiler/ast/node.go
generated
vendored
@ -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
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/paren_expr.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/paren_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
35
vendor/github.com/d5/tengo/compiler/ast/return_stmt.go
generated
vendored
35
vendor/github.com/d5/tengo/compiler/ast/return_stmt.go
generated
vendored
@ -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"
|
|
||||||
}
|
|
25
vendor/github.com/d5/tengo/compiler/ast/selector_expr.go
generated
vendored
25
vendor/github.com/d5/tengo/compiler/ast/selector_expr.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
36
vendor/github.com/d5/tengo/compiler/ast/slice_expr.go
generated
vendored
36
vendor/github.com/d5/tengo/compiler/ast/slice_expr.go
generated
vendored
@ -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 + "]"
|
|
||||||
}
|
|
7
vendor/github.com/d5/tengo/compiler/ast/stmt.go
generated
vendored
7
vendor/github.com/d5/tengo/compiler/ast/stmt.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
package ast
|
|
||||||
|
|
||||||
// Stmt represents a statement in the AST.
|
|
||||||
type Stmt interface {
|
|
||||||
Node
|
|
||||||
stmtNode()
|
|
||||||
}
|
|
26
vendor/github.com/d5/tengo/compiler/ast/string_lit.go
generated
vendored
26
vendor/github.com/d5/tengo/compiler/ast/string_lit.go
generated
vendored
@ -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
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/compiler/ast/unary_expr.go
generated
vendored
29
vendor/github.com/d5/tengo/compiler/ast/unary_expr.go
generated
vendored
@ -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() + ")"
|
|
||||||
}
|
|
24
vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go
generated
vendored
24
vendor/github.com/d5/tengo/compiler/ast/undefined_lit.go
generated
vendored
@ -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"
|
|
||||||
}
|
|
90
vendor/github.com/d5/tengo/compiler/bytecode.go
generated
vendored
90
vendor/github.com/d5/tengo/compiler/bytecode.go
generated
vendored
@ -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{})
|
|
||||||
}
|
|
97
vendor/github.com/d5/tengo/compiler/bytecode_decode.go
generated
vendored
97
vendor/github.com/d5/tengo/compiler/bytecode_decode.go
generated
vendored
@ -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
|
|
||||||
}
|
|
129
vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
generated
vendored
129
vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
generated
vendored
@ -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 ""
|
|
||||||
}
|
|
11
vendor/github.com/d5/tengo/compiler/compilation_scope.go
generated
vendored
11
vendor/github.com/d5/tengo/compiler/compilation_scope.go
generated
vendored
@ -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
|
|
||||||
}
|
|
846
vendor/github.com/d5/tengo/compiler/compiler.go
generated
vendored
846
vendor/github.com/d5/tengo/compiler/compiler.go
generated
vendored
@ -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("}")
|
|
||||||
}
|
|
133
vendor/github.com/d5/tengo/compiler/compiler_assign.go
generated
vendored
133
vendor/github.com/d5/tengo/compiler/compiler_assign.go
generated
vendored
@ -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
|
|
||||||
}
|
|
181
vendor/github.com/d5/tengo/compiler/compiler_for.go
generated
vendored
181
vendor/github.com/d5/tengo/compiler/compiler_for.go
generated
vendored
@ -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
|
|
||||||
}
|
|
30
vendor/github.com/d5/tengo/compiler/compiler_logical.go
generated
vendored
30
vendor/github.com/d5/tengo/compiler/compiler_logical.go
generated
vendored
@ -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
|
|
||||||
}
|
|
31
vendor/github.com/d5/tengo/compiler/compiler_loops.go
generated
vendored
31
vendor/github.com/d5/tengo/compiler/compiler_loops.go
generated
vendored
@ -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
|
|
||||||
}
|
|
79
vendor/github.com/d5/tengo/compiler/compiler_module.go
generated
vendored
79
vendor/github.com/d5/tengo/compiler/compiler_module.go
generated
vendored
@ -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
|
|
||||||
}
|
|
43
vendor/github.com/d5/tengo/compiler/compiler_scopes.go
generated
vendored
43
vendor/github.com/d5/tengo/compiler/compiler_scopes.go
generated
vendored
@ -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
|
|
||||||
}
|
|
8
vendor/github.com/d5/tengo/compiler/emitted_instruction.go
generated
vendored
8
vendor/github.com/d5/tengo/compiler/emitted_instruction.go
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
package compiler
|
|
||||||
|
|
||||||
// EmittedInstruction represents an opcode
|
|
||||||
// with its emitted position.
|
|
||||||
type EmittedInstruction struct {
|
|
||||||
Opcode Opcode
|
|
||||||
Position int
|
|
||||||
}
|
|
20
vendor/github.com/d5/tengo/compiler/error.go
generated
vendored
20
vendor/github.com/d5/tengo/compiler/error.go
generated
vendored
@ -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)
|
|
||||||
}
|
|
72
vendor/github.com/d5/tengo/compiler/instructions.go
generated
vendored
72
vendor/github.com/d5/tengo/compiler/instructions.go
generated
vendored
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
8
vendor/github.com/d5/tengo/compiler/loop.go
generated
vendored
8
vendor/github.com/d5/tengo/compiler/loop.go
generated
vendored
@ -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
|
|
||||||
}
|
|
4
vendor/github.com/d5/tengo/compiler/module_loader.go
generated
vendored
4
vendor/github.com/d5/tengo/compiler/module_loader.go
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
package compiler
|
|
||||||
|
|
||||||
// ModuleLoader should take a module name and return the module data.
|
|
||||||
type ModuleLoader func(moduleName string) ([]byte, error)
|
|
21
vendor/github.com/d5/tengo/compiler/parser/error.go
generated
vendored
21
vendor/github.com/d5/tengo/compiler/parser/error.go
generated
vendored
@ -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)
|
|
||||||
}
|
|
68
vendor/github.com/d5/tengo/compiler/parser/error_list.go
generated
vendored
68
vendor/github.com/d5/tengo/compiler/parser/error_list.go
generated
vendored
@ -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
|
|
||||||
}
|
|
17
vendor/github.com/d5/tengo/compiler/parser/parse_source.go
generated
vendored
17
vendor/github.com/d5/tengo/compiler/parser/parse_source.go
generated
vendored
@ -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()
|
|
||||||
}
|
|
12
vendor/github.com/d5/tengo/compiler/parser/sync.go
generated
vendored
12
vendor/github.com/d5/tengo/compiler/parser/sync.go
generated
vendored
@ -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,
|
|
||||||
}
|
|
6
vendor/github.com/d5/tengo/compiler/scanner/error_handler.go
generated
vendored
6
vendor/github.com/d5/tengo/compiler/scanner/error_handler.go
generated
vendored
@ -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)
|
|
10
vendor/github.com/d5/tengo/compiler/scanner/mode.go
generated
vendored
10
vendor/github.com/d5/tengo/compiler/scanner/mode.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
package scanner
|
|
||||||
|
|
||||||
// Mode represents a scanner mode.
|
|
||||||
type Mode int
|
|
||||||
|
|
||||||
// List of scanner modes.
|
|
||||||
const (
|
|
||||||
ScanComments Mode = 1 << iota
|
|
||||||
DontInsertSemis
|
|
||||||
)
|
|
110
vendor/github.com/d5/tengo/compiler/source/file.go
generated
vendored
110
vendor/github.com/d5/tengo/compiler/source/file.go
generated
vendored
@ -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
|
|
||||||
}
|
|
47
vendor/github.com/d5/tengo/compiler/source/file_pos.go
generated
vendored
47
vendor/github.com/d5/tengo/compiler/source/file_pos.go
generated
vendored
@ -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
|
|
||||||
}
|
|
96
vendor/github.com/d5/tengo/compiler/source/file_set.go
generated
vendored
96
vendor/github.com/d5/tengo/compiler/source/file_set.go
generated
vendored
@ -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
|
|
||||||
}
|
|
9
vendor/github.com/d5/tengo/compiler/symbol.go
generated
vendored
9
vendor/github.com/d5/tengo/compiler/symbol.go
generated
vendored
@ -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
|
|
||||||
}
|
|
12
vendor/github.com/d5/tengo/compiler/symbol_scopes.go
generated
vendored
12
vendor/github.com/d5/tengo/compiler/symbol_scopes.go
generated
vendored
@ -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"
|
|
||||||
)
|
|
19
vendor/github.com/d5/tengo/compiler/token/keywords.go
generated
vendored
19
vendor/github.com/d5/tengo/compiler/token/keywords.go
generated
vendored
@ -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
|
|
||||||
}
|
|
3
vendor/github.com/d5/tengo/go.mod
generated
vendored
3
vendor/github.com/d5/tengo/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/d5/tengo
|
|
||||||
|
|
||||||
go 1.12
|
|
130
vendor/github.com/d5/tengo/objects/array.go
generated
vendored
130
vendor/github.com/d5/tengo/objects/array.go
generated
vendored
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
57
vendor/github.com/d5/tengo/objects/array_iterator.go
generated
vendored
57
vendor/github.com/d5/tengo/objects/array_iterator.go
generated
vendored
@ -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]
|
|
||||||
}
|
|
64
vendor/github.com/d5/tengo/objects/bool.go
generated
vendored
64
vendor/github.com/d5/tengo/objects/bool.go
generated
vendored
@ -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
|
|
||||||
}
|
|
21
vendor/github.com/d5/tengo/objects/builtin_append.go
generated
vendored
21
vendor/github.com/d5/tengo/objects/builtin_append.go
generated
vendored
@ -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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
169
vendor/github.com/d5/tengo/objects/builtin_convert.go
generated
vendored
169
vendor/github.com/d5/tengo/objects/builtin_convert.go
generated
vendored
@ -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
|
|
||||||
}
|
|
9
vendor/github.com/d5/tengo/objects/builtin_copy.go
generated
vendored
9
vendor/github.com/d5/tengo/objects/builtin_copy.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package objects
|
|
||||||
|
|
||||||
func builtinCopy(args ...Object) (Object, error) {
|
|
||||||
if len(args) != 1 {
|
|
||||||
return nil, ErrWrongNumArguments
|
|
||||||
}
|
|
||||||
|
|
||||||
return args[0].Copy(), nil
|
|
||||||
}
|
|
27
vendor/github.com/d5/tengo/objects/builtin_format.go
generated
vendored
27
vendor/github.com/d5/tengo/objects/builtin_format.go
generated
vendored
@ -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
|
|
||||||
}
|
|
47
vendor/github.com/d5/tengo/objects/builtin_function.go
generated
vendored
47
vendor/github.com/d5/tengo/objects/builtin_function.go
generated
vendored
@ -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...)
|
|
||||||
}
|
|
29
vendor/github.com/d5/tengo/objects/builtin_len.go
generated
vendored
29
vendor/github.com/d5/tengo/objects/builtin_len.go
generated
vendored
@ -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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
23
vendor/github.com/d5/tengo/objects/builtin_module.go
generated
vendored
23
vendor/github.com/d5/tengo/objects/builtin_module.go
generated
vendored
@ -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}
|
|
||||||
}
|
|
9
vendor/github.com/d5/tengo/objects/builtin_type.go
generated
vendored
9
vendor/github.com/d5/tengo/objects/builtin_type.go
generated
vendored
@ -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
|
|
||||||
}
|
|
195
vendor/github.com/d5/tengo/objects/builtin_type_checks.go
generated
vendored
195
vendor/github.com/d5/tengo/objects/builtin_type_checks.go
generated
vendored
@ -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
|
|
||||||
}
|
|
118
vendor/github.com/d5/tengo/objects/builtins.go
generated
vendored
118
vendor/github.com/d5/tengo/objects/builtins.go
generated
vendored
@ -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,
|
|
||||||
},
|
|
||||||
}
|
|
89
vendor/github.com/d5/tengo/objects/bytes.go
generated
vendored
89
vendor/github.com/d5/tengo/objects/bytes.go
generated
vendored
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
57
vendor/github.com/d5/tengo/objects/bytes_iterator.go
generated
vendored
57
vendor/github.com/d5/tengo/objects/bytes_iterator.go
generated
vendored
@ -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])}
|
|
||||||
}
|
|
9
vendor/github.com/d5/tengo/objects/callable.go
generated
vendored
9
vendor/github.com/d5/tengo/objects/callable.go
generated
vendored
@ -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)
|
|
||||||
}
|
|
4
vendor/github.com/d5/tengo/objects/callable_func.go
generated
vendored
4
vendor/github.com/d5/tengo/objects/callable_func.go
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
package objects
|
|
||||||
|
|
||||||
// CallableFunc is a function signature for the callable functions.
|
|
||||||
type CallableFunc = func(args ...Object) (ret Object, err error)
|
|
119
vendor/github.com/d5/tengo/objects/char.go
generated
vendored
119
vendor/github.com/d5/tengo/objects/char.go
generated
vendored
@ -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
|
|
||||||
}
|
|
45
vendor/github.com/d5/tengo/objects/closure.go
generated
vendored
45
vendor/github.com/d5/tengo/objects/closure.go
generated
vendored
@ -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
|
|
||||||
}
|
|
62
vendor/github.com/d5/tengo/objects/compiled_function.go
generated
vendored
62
vendor/github.com/d5/tengo/objects/compiled_function.go
generated
vendored
@ -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
|
|
||||||
}
|
|
31
vendor/github.com/d5/tengo/objects/count_objects.go
generated
vendored
31
vendor/github.com/d5/tengo/objects/count_objects.go
generated
vendored
@ -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
|
|
||||||
}
|
|
47
vendor/github.com/d5/tengo/objects/error.go
generated
vendored
47
vendor/github.com/d5/tengo/objects/error.go
generated
vendored
@ -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
|
|
||||||
}
|
|
38
vendor/github.com/d5/tengo/objects/errors.go
generated
vendored
38
vendor/github.com/d5/tengo/objects/errors.go
generated
vendored
@ -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)
|
|
||||||
}
|
|
146
vendor/github.com/d5/tengo/objects/float.go
generated
vendored
146
vendor/github.com/d5/tengo/objects/float.go
generated
vendored
@ -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
|
|
||||||
}
|
|
109
vendor/github.com/d5/tengo/objects/immutable_array.go
generated
vendored
109
vendor/github.com/d5/tengo/objects/immutable_array.go
generated
vendored
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
105
vendor/github.com/d5/tengo/objects/immutable_map.go
generated
vendored
105
vendor/github.com/d5/tengo/objects/immutable_map.go
generated
vendored
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
7
vendor/github.com/d5/tengo/objects/importable.go
generated
vendored
7
vendor/github.com/d5/tengo/objects/importable.go
generated
vendored
@ -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)
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user