forked from lug/matterbridge
		
	Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e4d73b29a1 | ||
| 
						 | 
					8a875f292e | ||
| 
						 | 
					60a85621ea | ||
| 
						 | 
					115d20373c | ||
| 
						 | 
					cdf33e5748 | ||
| 
						 | 
					01d0a9f412 | ||
| 
						 | 
					8cc2d3b4fe | ||
| 
						 | 
					aba9e4f3be | ||
| 
						 | 
					4d575ba13a | ||
| 
						 | 
					7f0e4ad448 | ||
| 
						 | 
					17cc14a9d2 | ||
| 
						 | 
					1f8016182c | ||
| 
						 | 
					caf9ef2c4b | ||
| 
						 | 
					64b57f2da3 | ||
| 
						 | 
					efd2c99862 | ||
| 
						 | 
					cc05ba8907 | ||
| 
						 | 
					16763b715a | ||
| 
						 | 
					ffaa598796 | ||
| 
						 | 
					858e16d34f | ||
| 
						 | 
					a60e62efb1 | ||
| 
						 | 
					97f9d4be67 | 
@@ -7,7 +7,7 @@ run:
 | 
			
		||||
  # concurrency: 4
 | 
			
		||||
 | 
			
		||||
  # timeout for analysis, e.g. 30s, 5m, default is 1m
 | 
			
		||||
  deadline: 1m
 | 
			
		||||
  deadline: 2m
 | 
			
		||||
 | 
			
		||||
  # exit code when at least one issue was found, default is 1
 | 
			
		||||
  issues-exit-code: 1
 | 
			
		||||
@@ -105,10 +105,6 @@ linters-settings:
 | 
			
		||||
    # with golangci-lint call it on a directory with the changed file.
 | 
			
		||||
    check-exported: false
 | 
			
		||||
  unparam:
 | 
			
		||||
    # call graph construction algorithm (cha, rta). In general, use cha for libraries,
 | 
			
		||||
    # and rta for programs with main packages. Default is cha.
 | 
			
		||||
    algo: rta
 | 
			
		||||
 | 
			
		||||
    # Inspect exported functions, default is false. Set to true if no external program/library imports your code.
 | 
			
		||||
    # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
 | 
			
		||||
    # if it's called for subdir of a project it can't find external interfaces. All text editor integrations
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								.travis.yml
									
									
									
									
									
								
							@@ -1,75 +1,55 @@
 | 
			
		||||
language: go
 | 
			
		||||
go:
 | 
			
		||||
    - 1.11.x
 | 
			
		||||
go_import_path: github.com/42wim/matterbridge
 | 
			
		||||
 | 
			
		||||
# we have everything vendored
 | 
			
		||||
# We have everything vendored so this helps TravisCI not run `go get ...`.
 | 
			
		||||
install: true
 | 
			
		||||
 | 
			
		||||
git:
 | 
			
		||||
  depth: 200
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
    - GOOS=linux GOARCH=amd64
 | 
			
		||||
    - GO111MODULE=on
 | 
			
		||||
    - GOLANGCI_VERSION="v1.14.0"
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  # It's ok if our code fails on unstable development versions of Go.
 | 
			
		||||
  allow_failures:
 | 
			
		||||
    - go: tip
 | 
			
		||||
  # Don't wait for tip tests to finish. Mark the test run green if the
 | 
			
		||||
  # tests pass on the stable versions of Go.
 | 
			
		||||
  fast_finish: true
 | 
			
		||||
 | 
			
		||||
notifications:
 | 
			
		||||
      email: false
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
  # Get version info from tags.
 | 
			
		||||
  - MY_VERSION="$(git describe --tags)"
 | 
			
		||||
  # Retrieve the golangci-lint linter binary.
 | 
			
		||||
  - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ${GOPATH}/bin ${GOLANGCI_VERSION}
 | 
			
		||||
  # Retrieve and prepare CodeClimate's test coverage reporter.
 | 
			
		||||
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
 | 
			
		||||
  - chmod +x ./cc-test-reporter
 | 
			
		||||
  - ./cc-test-reporter before-build
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  # Ensure that the module files are being kept correctly and that vendored dependencies are up-to-date.
 | 
			
		||||
  - go mod tidy
 | 
			
		||||
  - go mod vendor
 | 
			
		||||
  - git diff --exit-code --quiet || (echo "Please run 'go mod tidy' to clean up the 'go.mod' and 'go.sum' files."; false)
 | 
			
		||||
 | 
			
		||||
  # Run the linter.
 | 
			
		||||
  - golangci-lint run
 | 
			
		||||
 | 
			
		||||
  # Run all the tests with the race detector and generate coverage.
 | 
			
		||||
  - go test -v -race -coverprofile c.out ./...
 | 
			
		||||
 | 
			
		||||
  # Run the build script to generate the necessary binaries and images.
 | 
			
		||||
  - /bin/bash ci/bintray.sh
 | 
			
		||||
 | 
			
		||||
after_script:
 | 
			
		||||
  # Upload test coverage to CodeClimate.
 | 
			
		||||
  - ./cc-test-reporter after-build --exit-code ${TRAVIS_TEST_RESULT}
 | 
			
		||||
  email: false
 | 
			
		||||
 | 
			
		||||
branches:
 | 
			
		||||
  only:
 | 
			
		||||
    - master
 | 
			
		||||
  - master
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  include:
 | 
			
		||||
  - stage: lint
 | 
			
		||||
    # Run linting in one Go environment only.
 | 
			
		||||
    script: ./ci/lint.sh
 | 
			
		||||
    go: 1.12.x
 | 
			
		||||
    env:
 | 
			
		||||
    - GO111MODULE=on
 | 
			
		||||
    - GOLANGCI_VERSION="v1.16.0"
 | 
			
		||||
  - stage: test
 | 
			
		||||
    # Run tests in a combination of Go environments.
 | 
			
		||||
    script: ./ci/test.sh
 | 
			
		||||
    go: 1.11.x
 | 
			
		||||
    env:
 | 
			
		||||
    - GO111MODULE=off
 | 
			
		||||
  - script: ./ci/test.sh
 | 
			
		||||
    go: 1.11.x
 | 
			
		||||
    env:
 | 
			
		||||
    - GO111MODULE=on
 | 
			
		||||
  - script: ./ci/test.sh
 | 
			
		||||
    go: 1.12.x
 | 
			
		||||
    env:
 | 
			
		||||
    - GO111MODULE=on
 | 
			
		||||
    - REPORT_COVERAGE=1
 | 
			
		||||
    - BINDEPLOY=1
 | 
			
		||||
 | 
			
		||||
before_deploy: /bin/bash ci/bintray.sh
 | 
			
		||||
 | 
			
		||||
deploy:
 | 
			
		||||
  on:
 | 
			
		||||
     all_branches: true
 | 
			
		||||
  provider: bintray
 | 
			
		||||
  on:
 | 
			
		||||
    all_branches: true
 | 
			
		||||
    condition: $BINDEPLOY = 1
 | 
			
		||||
  provider: bintray
 | 
			
		||||
  edge:
 | 
			
		||||
    branch: v1.8.47
 | 
			
		||||
  file: ci/deploy.json
 | 
			
		||||
  user: 42wim
 | 
			
		||||
  on:
 | 
			
		||||
     all_branches: true
 | 
			
		||||
  key:
 | 
			
		||||
     secure: "CeXXe6JOmt7HYR81MdWLua0ltQHhDdkIeRGBFbgd7hkb1wi8eF9DgpAcQrTso8NIlHNZmSAP46uhFgsRvkuezzX0ygalZ7DCJyAyn3sAMEh+UQSHV1WGThRehTtidqRGjetzsIGSwdrJOWil+XTfbO1Z8DGzfakhSuAZka8CM4BAoe3YeP9rYK8h+84x0GHfczvsLtXZ3mWLvQuwe4pK6+ItBCUg0ae7O7ZUpWHy0xQQkkWztY/6RAzXfaG7DuGjIw+20fhx3WOXRNpHCtZ6Bc3qERCpk0s1HhlQWlrN9wDaFTBWYwlvSnNgvxxMbNXJ6RrRJ0l0bA7FUswYwyroxhzrGLdzWDg8dHaQkypocngdalfhpsnoO9j3ApJhomUFJ3UoEq5nOGRUrKn8MPi+dP0zE4kNQ3e4VNa1ufNrvfpWolMg3xh8OXuhQdD5wIM5zFAbRJLqWSCVAjPq4DDPecmvXBOlIial7oa312lN5qnBnUjvAcxszZ+FUyDHT1Grxzna4tMwxY9obPzZUzm7359AOCCwIQFVB8GLqD2nwIstcXS0zGRz+fhviPipHuBa02q5bGUZwmkvrSNab0s8Jo7pCrel2Rz3nWPKaiCfq2WjbW1CLheSMkOQrjsdUd1hhbqNWFPUjJPInTc77NAKCfm5runv5uyowRLh4NNd0sI="
 | 
			
		||||
    secure: "CeXXe6JOmt7HYR81MdWLua0ltQHhDdkIeRGBFbgd7hkb1wi8eF9DgpAcQrTso8NIlHNZmSAP46uhFgsRvkuezzX0ygalZ7DCJyAyn3sAMEh+UQSHV1WGThRehTtidqRGjetzsIGSwdrJOWil+XTfbO1Z8DGzfakhSuAZka8CM4BAoe3YeP9rYK8h+84x0GHfczvsLtXZ3mWLvQuwe4pK6+ItBCUg0ae7O7ZUpWHy0xQQkkWztY/6RAzXfaG7DuGjIw+20fhx3WOXRNpHCtZ6Bc3qERCpk0s1HhlQWlrN9wDaFTBWYwlvSnNgvxxMbNXJ6RrRJ0l0bA7FUswYwyroxhzrGLdzWDg8dHaQkypocngdalfhpsnoO9j3ApJhomUFJ3UoEq5nOGRUrKn8MPi+dP0zE4kNQ3e4VNa1ufNrvfpWolMg3xh8OXuhQdD5wIM5zFAbRJLqWSCVAjPq4DDPecmvXBOlIial7oa312lN5qnBnUjvAcxszZ+FUyDHT1Grxzna4tMwxY9obPzZUzm7359AOCCwIQFVB8GLqD2nwIstcXS0zGRz+fhviPipHuBa02q5bGUZwmkvrSNab0s8Jo7pCrel2Rz3nWPKaiCfq2WjbW1CLheSMkOQrjsdUd1hhbqNWFPUjJPInTc77NAKCfm5runv5uyowRLh4NNd0sI="
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							@@ -35,6 +35,12 @@
 | 
			
		||||
 | 
			
		||||
**Note:** Matter<em>most</em> isn't required to run matter<em>bridge</em>.</sup></div>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
  <a href="https://www.digitalocean.com/">
 | 
			
		||||
    <img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/PoweredByDO/DO_Powered_by_Badge_blue.svg" width="201px">
 | 
			
		||||
  </a>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
### Table of Contents
 | 
			
		||||
 * [Features](https://github.com/42wim/matterbridge/wiki/Features)
 | 
			
		||||
   * [Natively supported](#natively-supported)
 | 
			
		||||
@@ -123,7 +129,7 @@ See https://github.com/42wim/matterbridge/wiki
 | 
			
		||||
 | 
			
		||||
## Installing
 | 
			
		||||
### Binaries
 | 
			
		||||
* Latest stable release [v1.14.0](https://github.com/42wim/matterbridge/releases/latest)
 | 
			
		||||
* Latest stable release [v1.14.2](https://github.com/42wim/matterbridge/releases/latest)
 | 
			
		||||
* Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)
 | 
			
		||||
 | 
			
		||||
### Packages
 | 
			
		||||
@@ -264,7 +270,13 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ)
 | 
			
		||||
* https://daniele.tech/2019/02/how-to-use-matterbridge-to-connect-2-different-slack-workspaces/
 | 
			
		||||
 | 
			
		||||
## Thanks
 | 
			
		||||
[](https://www.digitalocean.com/) for sponsoring demo/testing droplets.
 | 
			
		||||
 | 
			
		||||
<p>This project is supported by:</p>
 | 
			
		||||
<p>
 | 
			
		||||
  <a href="https://www.digitalocean.com/">
 | 
			
		||||
    <img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
 | 
			
		||||
  </a>
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
Matterbridge wouldn't exist without these libraries:
 | 
			
		||||
* discord - https://github.com/bwmarrin/discordgo
 | 
			
		||||
 
 | 
			
		||||
@@ -92,10 +92,6 @@ func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		b.Log.Debugf("<= Sending JOIN_LEAVE event from %s to gateway", b.Account)
 | 
			
		||||
		// QUIT isn't channel bound, happens for all channels on the bridge
 | 
			
		||||
		if event.Command == "QUIT" {
 | 
			
		||||
			channel = ""
 | 
			
		||||
		}
 | 
			
		||||
		msg := config.Message{Username: "system", Text: event.Source.Name + " " + strings.ToLower(event.Command) + "s", Channel: channel, Account: b.Account, Event: config.EventJoinLeave}
 | 
			
		||||
		b.Log.Debugf("<= Message is %#v", msg)
 | 
			
		||||
		b.Remote <- msg
 | 
			
		||||
 
 | 
			
		||||
@@ -137,6 +137,7 @@ func (b *Birc) Send(msg config.Message) (string, error) {
 | 
			
		||||
	// we can be in between reconnects #385
 | 
			
		||||
	if !b.i.IsConnected() {
 | 
			
		||||
		b.Log.Error("Not connected to server, dropping message")
 | 
			
		||||
		return "", nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Execute a command
 | 
			
		||||
@@ -231,7 +232,7 @@ func (b *Birc) getClient() (*girc.Client, error) {
 | 
			
		||||
	// fix strict user handling of girc
 | 
			
		||||
	user := b.GetString("Nick")
 | 
			
		||||
	for !girc.IsValidUser(user) {
 | 
			
		||||
		if len(user) == 1 {
 | 
			
		||||
		if len(user) == 1 || len(user) == 0 {
 | 
			
		||||
			user = "matterbridge"
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -95,7 +95,7 @@ func (b *Brocketchat) getChannelID(name string) string {
 | 
			
		||||
	b.RLock()
 | 
			
		||||
	defer b.RUnlock()
 | 
			
		||||
	for k, v := range b.channelMap {
 | 
			
		||||
		if v == name {
 | 
			
		||||
		if v == name || v == "#"+name {
 | 
			
		||||
			return k
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -130,12 +130,18 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// It seems ev.SubMessage.Edited == nil when slack unfurls.
 | 
			
		||||
	// Do not forward these messages. See Github issue #266.
 | 
			
		||||
	if ev.SubMessage != nil &&
 | 
			
		||||
		ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp &&
 | 
			
		||||
		ev.SubMessage.Edited == nil {
 | 
			
		||||
		return true
 | 
			
		||||
	if ev.SubMessage != nil {
 | 
			
		||||
		// It seems ev.SubMessage.Edited == nil when slack unfurls.
 | 
			
		||||
		// Do not forward these messages. See Github issue #266.
 | 
			
		||||
		if ev.SubMessage.ThreadTimestamp != ev.SubMessage.Timestamp &&
 | 
			
		||||
			ev.SubMessage.Edited == nil {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		// see hidden subtypes at https://api.slack.com/events/message
 | 
			
		||||
		// these messages are sent when we add a message to a thread #709
 | 
			
		||||
		if ev.SubType == "message_replied" && ev.Hidden {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ev.Files) > 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,6 @@ func (b *users) populateUser(userID string) {
 | 
			
		||||
			// in case the previous query failed for some reason.
 | 
			
		||||
		} else {
 | 
			
		||||
			b.usersSyncPoints[userID] = make(chan struct{})
 | 
			
		||||
			b.usersMutex.Unlock()
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,11 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
 | 
			
		||||
		// handle groups
 | 
			
		||||
		message = b.handleGroups(&rmsg, message, update)
 | 
			
		||||
 | 
			
		||||
		if message == nil {
 | 
			
		||||
			b.Log.Error("message is nil, this shouldn't happen.")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// set the ID's from the channel or group message
 | 
			
		||||
		rmsg.ID = strconv.Itoa(message.MessageID)
 | 
			
		||||
		rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,3 +1,22 @@
 | 
			
		||||
# v1.14.2
 | 
			
		||||
 | 
			
		||||
## Bugfix
 | 
			
		||||
* general: Update tengo vendor and load the stdlib. Fixes #789 (#792)
 | 
			
		||||
* rocketchat: Look up #channel too (rocketchat). Fix #773 (#775)
 | 
			
		||||
* slack: Ignore messagereplied and hidden messages (slack). Fixes #709 (#779)
 | 
			
		||||
* telegram: Handle nil message (telegram). Fixes #777
 | 
			
		||||
* irc: Use default nick if none specified (irc). Fixes #785
 | 
			
		||||
* irc: Return when not connected and drop a message (irc). Fixes #786
 | 
			
		||||
* irc: Revert fix for #722 (Support quits from irc correctly). Closes #781
 | 
			
		||||
 | 
			
		||||
## Contributors
 | 
			
		||||
This release couldn't exist without the following contributors:
 | 
			
		||||
@42wim, @Helcaraxan, @dajohi
 | 
			
		||||
 | 
			
		||||
# v1.14.1
 | 
			
		||||
## Bugfix
 | 
			
		||||
* slack: Fix crash double unlock (slack) (#771)
 | 
			
		||||
 | 
			
		||||
# v1.14.0
 | 
			
		||||
 | 
			
		||||
## Breaking
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
go version | grep go1.11 || exit
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
set -u -e -x -o pipefail
 | 
			
		||||
 | 
			
		||||
go version | grep go1.12 || exit
 | 
			
		||||
 | 
			
		||||
VERSION=$(git describe --tags)
 | 
			
		||||
mkdir ci/binaries
 | 
			
		||||
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o ci/binaries/matterbridge-$VERSION-windows-amd64.exe
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								ci/lint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								ci/lint.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
set -u -e -x -o pipefail
 | 
			
		||||
 | 
			
		||||
if [[ -n "${GOLANGCI_VERSION-}" ]]; then
 | 
			
		||||
  # Retrieve the golangci-lint linter binary.
 | 
			
		||||
  curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ${GOPATH}/bin ${GOLANGCI_VERSION}
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Run the linter.
 | 
			
		||||
golangci-lint run
 | 
			
		||||
 | 
			
		||||
if [[ "${GO111MODULE-off}" == "on" ]]; then
 | 
			
		||||
  # If Go modules are active then check that dependencies are correctly maintained.
 | 
			
		||||
  go mod tidy
 | 
			
		||||
  go mod vendor
 | 
			
		||||
  git diff --exit-code --quiet || (echo "Please run 'go mod tidy' to clean up the 'go.mod' and 'go.sum' files."; false)
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										17
									
								
								ci/test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								ci/test.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
set -u -e -x -o pipefail
 | 
			
		||||
 | 
			
		||||
if [[ -n "${REPORT_COVERAGE+cover}" ]]; then
 | 
			
		||||
  # Retrieve and prepare CodeClimate's test coverage reporter.
 | 
			
		||||
  curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
 | 
			
		||||
  chmod +x ./cc-test-reporter
 | 
			
		||||
  ./cc-test-reporter before-build
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Run all the tests with the race detector and generate coverage.
 | 
			
		||||
go test -v -race -coverprofile c.out ./...
 | 
			
		||||
 | 
			
		||||
if [[ -n "${REPORT_COVERAGE+cover}" && "${TRAVIS_SECURE_ENV_VARS}" == "true" ]]; then
 | 
			
		||||
  # Upload test coverage to CodeClimate.
 | 
			
		||||
  ./cc-test-reporter after-build
 | 
			
		||||
fi
 | 
			
		||||
@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"github.com/42wim/matterbridge/bridge"
 | 
			
		||||
	"github.com/42wim/matterbridge/bridge/config"
 | 
			
		||||
	"github.com/d5/tengo/script"
 | 
			
		||||
	"github.com/d5/tengo/stdlib"
 | 
			
		||||
	lru "github.com/hashicorp/golang-lru"
 | 
			
		||||
	"github.com/peterhellberg/emojilib"
 | 
			
		||||
	"github.com/sirupsen/logrus"
 | 
			
		||||
@@ -211,23 +212,6 @@ func (gw *Gateway) getDestChannel(msg *config.Message, dest bridge.Bridge) []con
 | 
			
		||||
		return channels
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// irc quit is for the whole bridge, isn't a per channel quit.
 | 
			
		||||
	// channel is empty when we quit
 | 
			
		||||
	if msg.Event == config.EventJoinLeave && getProtocol(msg) == "irc" && msg.Channel == "" {
 | 
			
		||||
		// if we only have one channel on this irc bridge it's got to be the sending one.
 | 
			
		||||
		// don't send it back
 | 
			
		||||
		if dest.Account == msg.Account && len(dest.Channels) == 1 && dest.Protocol == "irc" {
 | 
			
		||||
			return channels
 | 
			
		||||
		}
 | 
			
		||||
		for _, channel := range gw.Channels {
 | 
			
		||||
			if channel.Account == dest.Account && strings.Contains(channel.Direction, "out") &&
 | 
			
		||||
				gw.validGatewayDest(msg) {
 | 
			
		||||
				channels = append(channels, *channel)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return channels
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if source channel is in only, do nothing
 | 
			
		||||
	for _, channel := range gw.Channels {
 | 
			
		||||
		// lookup the channel from the message
 | 
			
		||||
@@ -503,6 +487,7 @@ func modifyMessageTengo(filename string, msg *config.Message) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	s := script.New(res)
 | 
			
		||||
	s.SetImports(stdlib.GetModuleMap(stdlib.AllModuleNames()...))
 | 
			
		||||
	_ = s.Add("msgText", msg.Text)
 | 
			
		||||
	_ = s.Add("msgUsername", msg.Username)
 | 
			
		||||
	_ = s.Add("msgAccount", msg.Account)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -7,7 +7,7 @@ require (
 | 
			
		||||
	github.com/Jeffail/gabs v1.1.1 // indirect
 | 
			
		||||
	github.com/Philipp15b/go-steam v1.0.1-0.20180818081528-681bd9573329
 | 
			
		||||
	github.com/bwmarrin/discordgo v0.19.0
 | 
			
		||||
	github.com/d5/tengo v1.12.1
 | 
			
		||||
	github.com/d5/tengo v1.20.0
 | 
			
		||||
	github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.4.7
 | 
			
		||||
	github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20181225215658-ec221ba9ea45+incompatible
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							@@ -15,8 +15,8 @@ github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVO
 | 
			
		||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 | 
			
		||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 | 
			
		||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 | 
			
		||||
github.com/d5/tengo v1.12.1 h1:libKkDM95CsZgYs6E5eiEaM9sbcw2EzJRSkr9o5NO4s=
 | 
			
		||||
github.com/d5/tengo v1.12.1/go.mod h1:gsbjo7lBXzBIWBd6NQp1lRKqqiDDANqBOyhW8rTlFsY=
 | 
			
		||||
github.com/d5/tengo v1.20.0 h1:lFmktzEGR6khlZu2MHUWJ5oDWS4l3jNRV/OhclZgcYc=
 | 
			
		||||
github.com/d5/tengo v1.20.0/go.mod h1:gsbjo7lBXzBIWBd6NQp1lRKqqiDDANqBOyhW8rTlFsY=
 | 
			
		||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	version = "1.14.0"
 | 
			
		||||
	version = "1.14.2"
 | 
			
		||||
	githash string
 | 
			
		||||
 | 
			
		||||
	flagConfig  = flag.String("conf", "matterbridge.toml", "config file")
 | 
			
		||||
 
 | 
			
		||||
@@ -1051,6 +1051,8 @@ SkipTLSVerify=true
 | 
			
		||||
#Useful if username overrides for incoming webhooks isn't enabled on the 
 | 
			
		||||
#rocketchat server. If you set PrefixMessagesWithNick to true, each message 
 | 
			
		||||
#from bridge to rocketchat will by default be prefixed by the RemoteNickFormat setting. i
 | 
			
		||||
#if you're using login/pass you can better enable because of this bug:
 | 
			
		||||
#https://github.com/RocketChat/Rocket.Chat/issues/7549
 | 
			
		||||
#OPTIONAL (default false)
 | 
			
		||||
PrefixMessagesWithNick=false
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,9 @@ func (m *MMClient) GetChannelId(name string, teamId string) string { //nolint:go
 | 
			
		||||
				if res == name {
 | 
			
		||||
					return channel.Id
 | 
			
		||||
				}
 | 
			
		||||
			} else if channel.Name == name {
 | 
			
		||||
				return channel.Id
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
 
 | 
			
		||||
@@ -216,9 +216,14 @@ func (m *MMClient) WsReceiver() {
 | 
			
		||||
			if msg.Post != nil {
 | 
			
		||||
				if msg.Text != "" || len(msg.Post.FileIds) > 0 || msg.Post.Type == "slack_attachment" {
 | 
			
		||||
					m.MessageChan <- msg
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
			switch msg.Raw.Event {
 | 
			
		||||
			case model.WEBSOCKET_EVENT_USER_ADDED, model.WEBSOCKET_EVENT_USER_REMOVED:
 | 
			
		||||
				m.MessageChan <- msg
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var response model.WebSocketResponse
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/d5/tengo/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/d5/tengo/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,10 +1,13 @@
 | 
			
		||||
vet:
 | 
			
		||||
	go vet ./...
 | 
			
		||||
 | 
			
		||||
generate:
 | 
			
		||||
	go generate ./...
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
	golint -set_exit_status ./...
 | 
			
		||||
 | 
			
		||||
test: vet lint
 | 
			
		||||
test: generate vet lint
 | 
			
		||||
	go test -race -cover ./...
 | 
			
		||||
 | 
			
		||||
fmt:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/github.com/d5/tengo/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/d5/tengo/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,7 +7,6 @@
 | 
			
		||||
[](https://godoc.org/github.com/d5/tengo/script)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/d5/tengo)
 | 
			
		||||
[](https://travis-ci.org/d5/tengo)
 | 
			
		||||
[](https://www.patreon.com/tengolang)
 | 
			
		||||
 | 
			
		||||
**Tengo is a small, dynamic, fast, secure script language for Go.** 
 | 
			
		||||
 | 
			
		||||
@@ -16,6 +15,8 @@ Tengo is **[fast](#benchmark)** and secure because it's compiled/executed as byt
 | 
			
		||||
```golang
 | 
			
		||||
/* The Tengo Language */
 | 
			
		||||
 | 
			
		||||
fmt := import("fmt")
 | 
			
		||||
 | 
			
		||||
each := func(seq, fn) {
 | 
			
		||||
    for x in seq { fn(x) }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,11 +26,11 @@ sum := func(init, seq) {
 | 
			
		||||
    return init
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
n := sum(0, [1, 2, 3])   // == 6
 | 
			
		||||
s := sum("", [1, 2, 3])  // == "123"
 | 
			
		||||
fmt.println(sum(0, [1, 2, 3]))   // "6"
 | 
			
		||||
fmt.println(sum("", [1, 2, 3]))  // "123"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> Run this code in the [Playground](https://tengolang.com/?s=d01cf9ed81daba939e26618530eb171f7397d9c9)
 | 
			
		||||
> Run this code in the [Playground](https://tengolang.com/?s=0c8d5d0d88f2795a7093d7f35ae12c3afa17bea3)
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
@@ -41,22 +42,23 @@ s := sum("", [1, 2, 3])  // == "123"
 | 
			
		||||
- [Securely Embeddable](https://github.com/d5/tengo/blob/master/docs/interoperability.md) and [Extensible](https://github.com/d5/tengo/blob/master/docs/objects.md)
 | 
			
		||||
- Compiler/runtime written in native Go _(no external deps or cgo)_
 | 
			
		||||
- Executable as a [standalone](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md) language / REPL
 | 
			
		||||
- Use cases: rules engine, [state machine](https://github.com/d5/go-fsm), [gaming](https://github.com/d5/pbr), data pipeline, [transpiler](https://github.com/d5/tengo2lua)
 | 
			
		||||
 | 
			
		||||
## Benchmark
 | 
			
		||||
 | 
			
		||||
| | fib(35) | fibt(35) |  Type  |
 | 
			
		||||
| :--- |    ---: |     ---: |  :---: |
 | 
			
		||||
| Go | `58ms` | `4ms` | Go (native) |
 | 
			
		||||
| [**Tengo**](https://github.com/d5/tengo) | `4,180ms` | `5ms` | VM on Go |
 | 
			
		||||
| Lua | `1,695ms` | `3ms` | Lua (native) |
 | 
			
		||||
| [go-lua](https://github.com/Shopify/go-lua) | `5,163ms` | `5ms` | Lua VM on Go |
 | 
			
		||||
| [GopherLua](https://github.com/yuin/gopher-lua) | `5,525ms` | `5ms` | Lua VM on Go |
 | 
			
		||||
| Python | `3,097ms` | `27ms` | Python (native) |
 | 
			
		||||
| [starlark-go](https://github.com/google/starlark-go) | `15,307ms` | `5ms` | Python-like Interpreter on Go |
 | 
			
		||||
| [gpython](https://github.com/go-python/gpython) | `17,656ms` | `5ms` | Python Interpreter on Go |
 | 
			
		||||
| [goja](https://github.com/dop251/goja) | `6,876ms` | `5ms` | JS VM on Go |
 | 
			
		||||
| [otto](https://github.com/robertkrimen/otto) | `81,886ms` | `12ms` | JS Interpreter on Go |
 | 
			
		||||
| [Anko](https://github.com/mattn/anko) | `97,517ms` | `14ms` | Interpreter on Go |
 | 
			
		||||
| Go | `48ms` | `3ms` | Go (native) |
 | 
			
		||||
| [**Tengo**](https://github.com/d5/tengo) | `2,349ms` | `5ms` | VM on Go |
 | 
			
		||||
| Lua | `1,416ms` | `3ms` | Lua (native) |
 | 
			
		||||
| [go-lua](https://github.com/Shopify/go-lua) | `4,402ms` | `5ms` | Lua VM on Go |
 | 
			
		||||
| [GopherLua](https://github.com/yuin/gopher-lua) | `4,023ms` | `5ms` | Lua VM on Go |
 | 
			
		||||
| Python | `2,588ms` | `26ms` | Python (native) |
 | 
			
		||||
| [starlark-go](https://github.com/google/starlark-go) | `11,126ms` | `6ms` | Python-like Interpreter on Go |
 | 
			
		||||
| [gpython](https://github.com/go-python/gpython) | `15,035ms` | `4ms` | Python Interpreter on Go |
 | 
			
		||||
| [goja](https://github.com/dop251/goja) | `5,089ms` | `5ms` | JS VM on Go |
 | 
			
		||||
| [otto](https://github.com/robertkrimen/otto) | `68,377ms` | `11ms` | JS Interpreter on Go |
 | 
			
		||||
| [Anko](https://github.com/mattn/anko) | `92,579ms` | `18ms` | Interpreter on Go |
 | 
			
		||||
 | 
			
		||||
_* [fib(35)](https://github.com/d5/tengobench/blob/master/code/fib.tengo): Fibonacci(35)_  
 | 
			
		||||
_* [fibt(35)](https://github.com/d5/tengobench/blob/master/code/fibtc.tengo): [tail-call](https://en.wikipedia.org/wiki/Tail_call) version of Fibonacci(35)_  
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								vendor/github.com/d5/tengo/compiler/bytecode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								vendor/github.com/d5/tengo/compiler/bytecode.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,32 +17,6 @@ type Bytecode struct {
 | 
			
		||||
	Constants    []objects.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decode reads Bytecode data from the reader.
 | 
			
		||||
func (b *Bytecode) Decode(r io.Reader) error {
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// replace Bool and Undefined with known value
 | 
			
		||||
	for i, v := range b.Constants {
 | 
			
		||||
		b.Constants[i] = cleanupObjects(v)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encode writes Bytecode data to the writer.
 | 
			
		||||
func (b *Bytecode) Encode(w io.Writer) error {
 | 
			
		||||
	enc := gob.NewEncoder(w)
 | 
			
		||||
@@ -59,6 +33,17 @@ func (b *Bytecode) Encode(w io.Writer) error {
 | 
			
		||||
	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 {
 | 
			
		||||
@@ -83,51 +68,22 @@ func (b *Bytecode) FormatConstants() (output []string) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cleanupObjects(o objects.Object) objects.Object {
 | 
			
		||||
	switch o := o.(type) {
 | 
			
		||||
	case *objects.Bool:
 | 
			
		||||
		if o.IsFalsy() {
 | 
			
		||||
			return objects.FalseValue
 | 
			
		||||
		}
 | 
			
		||||
		return objects.TrueValue
 | 
			
		||||
	case *objects.Undefined:
 | 
			
		||||
		return objects.UndefinedValue
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		for i, v := range o.Value {
 | 
			
		||||
			o.Value[i] = cleanupObjects(v)
 | 
			
		||||
		}
 | 
			
		||||
	case *objects.Map:
 | 
			
		||||
		for k, v := range o.Value {
 | 
			
		||||
			o.Value[k] = cleanupObjects(v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return o
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	gob.Register(&source.FileSet{})
 | 
			
		||||
	gob.Register(&source.File{})
 | 
			
		||||
	gob.Register(&objects.Array{})
 | 
			
		||||
	gob.Register(&objects.ArrayIterator{})
 | 
			
		||||
	gob.Register(&objects.Bool{})
 | 
			
		||||
	gob.Register(&objects.Break{})
 | 
			
		||||
	gob.Register(&objects.BuiltinFunction{})
 | 
			
		||||
	gob.Register(&objects.Bytes{})
 | 
			
		||||
	gob.Register(&objects.Char{})
 | 
			
		||||
	gob.Register(&objects.Closure{})
 | 
			
		||||
	gob.Register(&objects.CompiledFunction{})
 | 
			
		||||
	gob.Register(&objects.Continue{})
 | 
			
		||||
	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.MapIterator{})
 | 
			
		||||
	gob.Register(&objects.ReturnValue{})
 | 
			
		||||
	gob.Register(&objects.String{})
 | 
			
		||||
	gob.Register(&objects.StringIterator{})
 | 
			
		||||
	gob.Register(&objects.Time{})
 | 
			
		||||
	gob.Register(&objects.Undefined{})
 | 
			
		||||
	gob.Register(&objects.UserFunction{})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								vendor/github.com/d5/tengo/compiler/bytecode_decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/d5/tengo/compiler/bytecode_decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
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
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								vendor/github.com/d5/tengo/compiler/bytecode_optimize.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
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 ""
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/d5/tengo/compiler/compilation_scope.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/d5/tengo/compiler/compilation_scope.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,8 +5,7 @@ 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
 | 
			
		||||
	lastInstructions [2]EmittedInstruction
 | 
			
		||||
	symbolInit       map[string]bool
 | 
			
		||||
	sourceMap        map[int]source.Pos
 | 
			
		||||
	instructions []byte
 | 
			
		||||
	symbolInit   map[string]bool
 | 
			
		||||
	sourceMap    map[int]source.Pos
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										270
									
								
								vendor/github.com/d5/tengo/compiler/compiler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										270
									
								
								vendor/github.com/d5/tengo/compiler/compiler.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,7 +3,10 @@ package compiler
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/compiler/ast"
 | 
			
		||||
@@ -16,14 +19,14 @@ import (
 | 
			
		||||
type Compiler struct {
 | 
			
		||||
	file            *source.File
 | 
			
		||||
	parent          *Compiler
 | 
			
		||||
	moduleName      string
 | 
			
		||||
	modulePath      string
 | 
			
		||||
	constants       []objects.Object
 | 
			
		||||
	symbolTable     *SymbolTable
 | 
			
		||||
	scopes          []CompilationScope
 | 
			
		||||
	scopeIndex      int
 | 
			
		||||
	moduleLoader    ModuleLoader
 | 
			
		||||
	builtinModules  map[string]bool
 | 
			
		||||
	modules         *objects.ModuleMap
 | 
			
		||||
	compiledModules map[string]*objects.CompiledFunction
 | 
			
		||||
	allowFileImport bool
 | 
			
		||||
	loops           []*Loop
 | 
			
		||||
	loopIndex       int
 | 
			
		||||
	trace           io.Writer
 | 
			
		||||
@@ -31,12 +34,7 @@ type Compiler struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCompiler creates a Compiler.
 | 
			
		||||
// User can optionally provide the symbol table if one wants to add or remove
 | 
			
		||||
// some global- or builtin- scope symbols. If not (nil), Compile will create
 | 
			
		||||
// a new symbol table and use the default builtin functions. Likewise, standard
 | 
			
		||||
// modules can be explicitly provided if user wants to add or remove some modules.
 | 
			
		||||
// By default, Compile will use all the standard modules otherwise.
 | 
			
		||||
func NewCompiler(file *source.File, symbolTable *SymbolTable, constants []objects.Object, builtinModules map[string]bool, trace io.Writer) *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),
 | 
			
		||||
@@ -45,15 +43,16 @@ func NewCompiler(file *source.File, symbolTable *SymbolTable, constants []object
 | 
			
		||||
	// symbol table
 | 
			
		||||
	if symbolTable == nil {
 | 
			
		||||
		symbolTable = NewSymbolTable()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		for idx, fn := range objects.Builtins {
 | 
			
		||||
			symbolTable.DefineBuiltin(idx, fn.Name)
 | 
			
		||||
		}
 | 
			
		||||
	// add builtin functions to the symbol table
 | 
			
		||||
	for idx, fn := range objects.Builtins {
 | 
			
		||||
		symbolTable.DefineBuiltin(idx, fn.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// builtin modules
 | 
			
		||||
	if builtinModules == nil {
 | 
			
		||||
		builtinModules = make(map[string]bool)
 | 
			
		||||
	if modules == nil {
 | 
			
		||||
		modules = objects.NewModuleMap()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Compiler{
 | 
			
		||||
@@ -64,7 +63,7 @@ func NewCompiler(file *source.File, symbolTable *SymbolTable, constants []object
 | 
			
		||||
		scopeIndex:      0,
 | 
			
		||||
		loopIndex:       -1,
 | 
			
		||||
		trace:           trace,
 | 
			
		||||
		builtinModules:  builtinModules,
 | 
			
		||||
		modules:         modules,
 | 
			
		||||
		compiledModules: make(map[string]*objects.CompiledFunction),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -120,7 +119,7 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c.emit(node, OpGreaterThan)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Greater))
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		} else if node.Token == token.LessEq {
 | 
			
		||||
@@ -131,7 +130,7 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c.emit(node, OpGreaterThanEqual)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.GreaterEq))
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
@@ -145,35 +144,35 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
 | 
			
		||||
		switch node.Token {
 | 
			
		||||
		case token.Add:
 | 
			
		||||
			c.emit(node, OpAdd)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Add))
 | 
			
		||||
		case token.Sub:
 | 
			
		||||
			c.emit(node, OpSub)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Sub))
 | 
			
		||||
		case token.Mul:
 | 
			
		||||
			c.emit(node, OpMul)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Mul))
 | 
			
		||||
		case token.Quo:
 | 
			
		||||
			c.emit(node, OpDiv)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Quo))
 | 
			
		||||
		case token.Rem:
 | 
			
		||||
			c.emit(node, OpRem)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Rem))
 | 
			
		||||
		case token.Greater:
 | 
			
		||||
			c.emit(node, OpGreaterThan)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Greater))
 | 
			
		||||
		case token.GreaterEq:
 | 
			
		||||
			c.emit(node, OpGreaterThanEqual)
 | 
			
		||||
			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, OpBAnd)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.And))
 | 
			
		||||
		case token.Or:
 | 
			
		||||
			c.emit(node, OpBOr)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Or))
 | 
			
		||||
		case token.Xor:
 | 
			
		||||
			c.emit(node, OpBXor)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Xor))
 | 
			
		||||
		case token.AndNot:
 | 
			
		||||
			c.emit(node, OpBAndNot)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.AndNot))
 | 
			
		||||
		case token.Shl:
 | 
			
		||||
			c.emit(node, OpBShiftLeft)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Shl))
 | 
			
		||||
		case token.Shr:
 | 
			
		||||
			c.emit(node, OpBShiftRight)
 | 
			
		||||
			c.emit(node, OpBinaryOp, int(token.Shr))
 | 
			
		||||
		default:
 | 
			
		||||
			return c.errorf(node, "invalid binary operator: %s", node.Token.String())
 | 
			
		||||
		}
 | 
			
		||||
@@ -293,6 +292,15 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
@@ -405,10 +413,8 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// add OpReturn if function returns nothing
 | 
			
		||||
		if !c.lastInstructionIs(OpReturnValue) && !c.lastInstructionIs(OpReturn) {
 | 
			
		||||
			c.emit(node, OpReturn)
 | 
			
		||||
		}
 | 
			
		||||
		// code optimization
 | 
			
		||||
		c.optimizeFunc(node)
 | 
			
		||||
 | 
			
		||||
		freeSymbols := c.symbolTable.FreeSymbols()
 | 
			
		||||
		numLocals := c.symbolTable.MaxSymbols()
 | 
			
		||||
@@ -461,9 +467,9 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
					s.LocalAssigned = true
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				c.emit(node, OpGetLocal, s.Index)
 | 
			
		||||
				c.emit(node, OpGetLocalPtr, s.Index)
 | 
			
		||||
			case ScopeFree:
 | 
			
		||||
				c.emit(node, OpGetFree, s.Index)
 | 
			
		||||
				c.emit(node, OpGetFreePtr, s.Index)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -487,13 +493,13 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if node.Result == nil {
 | 
			
		||||
			c.emit(node, OpReturn)
 | 
			
		||||
			c.emit(node, OpReturn, 0)
 | 
			
		||||
		} else {
 | 
			
		||||
			if err := c.Compile(node.Result); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c.emit(node, OpReturnValue)
 | 
			
		||||
			c.emit(node, OpReturn, 1)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case *ast.CallExpr:
 | 
			
		||||
@@ -510,21 +516,57 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
		c.emit(node, OpCall, len(node.Args))
 | 
			
		||||
 | 
			
		||||
	case *ast.ImportExpr:
 | 
			
		||||
		if c.builtinModules[node.ModuleName] {
 | 
			
		||||
			if len(node.ModuleName) > tengo.MaxStringLen {
 | 
			
		||||
				return c.error(node, objects.ErrStringLimit)
 | 
			
		||||
			}
 | 
			
		||||
		if node.ModuleName == "" {
 | 
			
		||||
			return c.errorf(node, "empty module name")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			c.emit(node, OpConstant, c.addConstant(&objects.String{Value: node.ModuleName}))
 | 
			
		||||
			c.emit(node, OpGetBuiltinModule)
 | 
			
		||||
		} else {
 | 
			
		||||
			userMod, err := c.compileModule(node)
 | 
			
		||||
		if mod := c.modules.Get(node.ModuleName); mod != nil {
 | 
			
		||||
			v, err := mod.Import(node.ModuleName)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c.emit(node, OpConstant, c.addConstant(userMod))
 | 
			
		||||
			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:
 | 
			
		||||
@@ -543,7 +585,7 @@ func (c *Compiler) Compile(node ast.Node) error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c.emit(node, OpImmutable)
 | 
			
		||||
		c.emit(node, OpReturnValue)
 | 
			
		||||
		c.emit(node, OpReturn, 1)
 | 
			
		||||
 | 
			
		||||
	case *ast.ErrorExpr:
 | 
			
		||||
		if err := c.Compile(node.Expr); err != nil {
 | 
			
		||||
@@ -602,18 +644,16 @@ func (c *Compiler) Bytecode() *Bytecode {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetModuleLoader sets or replaces the current module loader.
 | 
			
		||||
// Note that the module loader is used for user modules,
 | 
			
		||||
// not for the standard modules.
 | 
			
		||||
func (c *Compiler) SetModuleLoader(moduleLoader ModuleLoader) {
 | 
			
		||||
	c.moduleLoader = moduleLoader
 | 
			
		||||
// 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, moduleName string, symbolTable *SymbolTable) *Compiler {
 | 
			
		||||
	child := NewCompiler(file, symbolTable, nil, c.builtinModules, c.trace)
 | 
			
		||||
	child.moduleName = moduleName       // name of the module to compile
 | 
			
		||||
	child.parent = c                    // parent to set to current compiler
 | 
			
		||||
	child.moduleLoader = c.moduleLoader // share module loader
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
@@ -657,33 +697,6 @@ func (c *Compiler) addInstruction(b []byte) int {
 | 
			
		||||
	return posNewIns
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) setLastInstruction(op Opcode, pos int) {
 | 
			
		||||
	c.scopes[c.scopeIndex].lastInstructions[1] = c.scopes[c.scopeIndex].lastInstructions[0]
 | 
			
		||||
 | 
			
		||||
	c.scopes[c.scopeIndex].lastInstructions[0].Opcode = op
 | 
			
		||||
	c.scopes[c.scopeIndex].lastInstructions[0].Position = pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) lastInstructionIs(op Opcode) bool {
 | 
			
		||||
	if len(c.currentInstructions()) == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.scopes[c.scopeIndex].lastInstructions[0].Opcode == op
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) removeLastInstruction() {
 | 
			
		||||
	lastPos := c.scopes[c.scopeIndex].lastInstructions[0].Position
 | 
			
		||||
 | 
			
		||||
	if c.trace != nil {
 | 
			
		||||
		c.printTrace(fmt.Sprintf("DELET %s",
 | 
			
		||||
			FormatInstructions(c.scopes[c.scopeIndex].instructions[lastPos:], lastPos)[0]))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.scopes[c.scopeIndex].instructions = c.currentInstructions()[:lastPos]
 | 
			
		||||
	c.scopes[c.scopeIndex].lastInstructions[0] = c.scopes[c.scopeIndex].lastInstructions[1]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) replaceInstruction(pos int, inst []byte) {
 | 
			
		||||
	copy(c.currentInstructions()[pos:], inst)
 | 
			
		||||
 | 
			
		||||
@@ -700,6 +713,92 @@ func (c *Compiler) changeOperand(opPos int, operand ...int) {
 | 
			
		||||
	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 {
 | 
			
		||||
@@ -709,7 +808,6 @@ func (c *Compiler) emit(node ast.Node, opcode Opcode, operands ...int) int {
 | 
			
		||||
	inst := MakeInstruction(opcode, operands...)
 | 
			
		||||
	pos := c.addInstruction(inst)
 | 
			
		||||
	c.scopes[c.scopeIndex].sourceMap[pos] = filePos
 | 
			
		||||
	c.setLastInstruction(opcode, pos)
 | 
			
		||||
 | 
			
		||||
	if c.trace != nil {
 | 
			
		||||
		c.printTrace(fmt.Sprintf("EMIT  %s",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/d5/tengo/compiler/compiler_assign.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/d5/tengo/compiler/compiler_assign.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -51,27 +51,27 @@ func (c *Compiler) compileAssign(node ast.Node, lhs, rhs []ast.Expr, op token.To
 | 
			
		||||
 | 
			
		||||
	switch op {
 | 
			
		||||
	case token.AddAssign:
 | 
			
		||||
		c.emit(node, OpAdd)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Add))
 | 
			
		||||
	case token.SubAssign:
 | 
			
		||||
		c.emit(node, OpSub)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Sub))
 | 
			
		||||
	case token.MulAssign:
 | 
			
		||||
		c.emit(node, OpMul)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Mul))
 | 
			
		||||
	case token.QuoAssign:
 | 
			
		||||
		c.emit(node, OpDiv)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Quo))
 | 
			
		||||
	case token.RemAssign:
 | 
			
		||||
		c.emit(node, OpRem)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Rem))
 | 
			
		||||
	case token.AndAssign:
 | 
			
		||||
		c.emit(node, OpBAnd)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.And))
 | 
			
		||||
	case token.OrAssign:
 | 
			
		||||
		c.emit(node, OpBOr)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Or))
 | 
			
		||||
	case token.AndNotAssign:
 | 
			
		||||
		c.emit(node, OpBAndNot)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.AndNot))
 | 
			
		||||
	case token.XorAssign:
 | 
			
		||||
		c.emit(node, OpBXor)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Xor))
 | 
			
		||||
	case token.ShlAssign:
 | 
			
		||||
		c.emit(node, OpBShiftLeft)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Shl))
 | 
			
		||||
	case token.ShrAssign:
 | 
			
		||||
		c.emit(node, OpBShiftRight)
 | 
			
		||||
		c.emit(node, OpBinaryOp, int(token.Shr))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// compile selector expressions (right to left)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										91
									
								
								vendor/github.com/d5/tengo/compiler/compiler_module.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/d5/tengo/compiler/compiler_module.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,72 +1,31 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/compiler/ast"
 | 
			
		||||
	"github.com/d5/tengo/compiler/parser"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) compileModule(expr *ast.ImportExpr) (*objects.CompiledFunction, error) {
 | 
			
		||||
	compiledModule, exists := c.loadCompiledModule(expr.ModuleName)
 | 
			
		||||
	if exists {
 | 
			
		||||
		return compiledModule, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	moduleName := expr.ModuleName
 | 
			
		||||
 | 
			
		||||
	// read module source from loader
 | 
			
		||||
	var moduleSrc []byte
 | 
			
		||||
	if c.moduleLoader == nil {
 | 
			
		||||
		// default loader: read from local file
 | 
			
		||||
		if !strings.HasSuffix(moduleName, ".tengo") {
 | 
			
		||||
			moduleName += ".tengo"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := c.checkCyclicImports(expr, moduleName); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		moduleSrc, err = ioutil.ReadFile(moduleName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, c.errorf(expr, "module file read error: %s", err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if err := c.checkCyclicImports(expr, moduleName); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var err error
 | 
			
		||||
		moduleSrc, err = c.moduleLoader(moduleName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	compiledModule, err := c.doCompileModule(moduleName, moduleSrc)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.storeCompiledModule(moduleName, compiledModule)
 | 
			
		||||
 | 
			
		||||
	return compiledModule, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) checkCyclicImports(node ast.Node, moduleName string) error {
 | 
			
		||||
	if c.moduleName == moduleName {
 | 
			
		||||
		return c.errorf(node, "cyclic module import: %s", moduleName)
 | 
			
		||||
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, moduleName)
 | 
			
		||||
		return c.parent.checkCyclicImports(node, modulePath)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) doCompileModule(moduleName string, src []byte) (*objects.CompiledFunction, error) {
 | 
			
		||||
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()
 | 
			
		||||
@@ -85,36 +44,36 @@ func (c *Compiler) doCompileModule(moduleName string, src []byte) (*objects.Comp
 | 
			
		||||
	symbolTable = symbolTable.Fork(false)
 | 
			
		||||
 | 
			
		||||
	// compile module
 | 
			
		||||
	moduleCompiler := c.fork(modFile, moduleName, symbolTable)
 | 
			
		||||
	moduleCompiler := c.fork(modFile, modulePath, symbolTable)
 | 
			
		||||
	if err := moduleCompiler.Compile(file); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// add OpReturn (== export undefined) if export is missing
 | 
			
		||||
	if !moduleCompiler.lastInstructionIs(OpReturnValue) {
 | 
			
		||||
		moduleCompiler.emit(nil, OpReturn)
 | 
			
		||||
	}
 | 
			
		||||
	// code optimization
 | 
			
		||||
	moduleCompiler.optimizeFunc(node)
 | 
			
		||||
 | 
			
		||||
	compiledFunc := moduleCompiler.Bytecode().MainFunction
 | 
			
		||||
	compiledFunc.NumLocals = symbolTable.MaxSymbols()
 | 
			
		||||
 | 
			
		||||
	c.storeCompiledModule(modulePath, compiledFunc)
 | 
			
		||||
 | 
			
		||||
	return compiledFunc, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) loadCompiledModule(moduleName string) (mod *objects.CompiledFunction, ok bool) {
 | 
			
		||||
func (c *Compiler) loadCompiledModule(modulePath string) (mod *objects.CompiledFunction, ok bool) {
 | 
			
		||||
	if c.parent != nil {
 | 
			
		||||
		return c.parent.loadCompiledModule(moduleName)
 | 
			
		||||
		return c.parent.loadCompiledModule(modulePath)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mod, ok = c.compiledModules[moduleName]
 | 
			
		||||
	mod, ok = c.compiledModules[modulePath]
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Compiler) storeCompiledModule(moduleName string, module *objects.CompiledFunction) {
 | 
			
		||||
func (c *Compiler) storeCompiledModule(modulePath string, module *objects.CompiledFunction) {
 | 
			
		||||
	if c.parent != nil {
 | 
			
		||||
		c.parent.storeCompiledModule(moduleName, module)
 | 
			
		||||
		c.parent.storeCompiledModule(modulePath, module)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.compiledModules[moduleName] = module
 | 
			
		||||
	c.compiledModules[modulePath] = module
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/github.com/d5/tengo/compiler/instructions.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/d5/tengo/compiler/instructions.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -57,3 +57,16 @@ func FormatInstructions(b []byte, posOffset int) []string {
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										282
									
								
								vendor/github.com/d5/tengo/compiler/opcodes.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										282
									
								
								vendor/github.com/d5/tengo/compiler/opcodes.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,173 +5,137 @@ type Opcode = byte
 | 
			
		||||
 | 
			
		||||
// List of opcodes
 | 
			
		||||
const (
 | 
			
		||||
	OpConstant         Opcode = iota // Load constant
 | 
			
		||||
	OpAdd                            // Add
 | 
			
		||||
	OpSub                            // Sub
 | 
			
		||||
	OpMul                            // Multiply
 | 
			
		||||
	OpDiv                            // Divide
 | 
			
		||||
	OpRem                            // Remainder
 | 
			
		||||
	OpBAnd                           // bitwise AND
 | 
			
		||||
	OpBOr                            // bitwise OR
 | 
			
		||||
	OpBXor                           // bitwise XOR
 | 
			
		||||
	OpBShiftLeft                     // bitwise shift left
 | 
			
		||||
	OpBShiftRight                    // bitwise shift right
 | 
			
		||||
	OpBAndNot                        // bitwise AND NOT
 | 
			
		||||
	OpBComplement                    // bitwise complement
 | 
			
		||||
	OpPop                            // Pop
 | 
			
		||||
	OpTrue                           // Push true
 | 
			
		||||
	OpFalse                          // Push false
 | 
			
		||||
	OpEqual                          // Equal ==
 | 
			
		||||
	OpNotEqual                       // Not equal !=
 | 
			
		||||
	OpGreaterThan                    // Greater than >=
 | 
			
		||||
	OpGreaterThanEqual               // Greater than or equal to >=
 | 
			
		||||
	OpMinus                          // Minus -
 | 
			
		||||
	OpLNot                           // Logical not !
 | 
			
		||||
	OpJumpFalsy                      // Jump if falsy
 | 
			
		||||
	OpAndJump                        // Logical AND jump
 | 
			
		||||
	OpOrJump                         // Logical OR jump
 | 
			
		||||
	OpJump                           // Jump
 | 
			
		||||
	OpNull                           // Push null
 | 
			
		||||
	OpArray                          // Array object
 | 
			
		||||
	OpMap                            // Map object
 | 
			
		||||
	OpError                          // Error object
 | 
			
		||||
	OpImmutable                      // Immutable object
 | 
			
		||||
	OpIndex                          // Index operation
 | 
			
		||||
	OpSliceIndex                     // Slice operation
 | 
			
		||||
	OpCall                           // Call function
 | 
			
		||||
	OpReturn                         // Return
 | 
			
		||||
	OpReturnValue                    // Return value
 | 
			
		||||
	OpGetGlobal                      // Get global variable
 | 
			
		||||
	OpSetGlobal                      // Set global variable
 | 
			
		||||
	OpSetSelGlobal                   // Set global variable using selectors
 | 
			
		||||
	OpGetLocal                       // Get local variable
 | 
			
		||||
	OpSetLocal                       // Set local variable
 | 
			
		||||
	OpDefineLocal                    // Define local variable
 | 
			
		||||
	OpSetSelLocal                    // Set local variable using selectors
 | 
			
		||||
	OpGetFree                        // Get free variables
 | 
			
		||||
	OpSetFree                        // Set free variables
 | 
			
		||||
	OpSetSelFree                     // Set free variables using selectors
 | 
			
		||||
	OpGetBuiltin                     // Get builtin function
 | 
			
		||||
	OpGetBuiltinModule               // Get builtin module
 | 
			
		||||
	OpClosure                        // Push closure
 | 
			
		||||
	OpIteratorInit                   // Iterator init
 | 
			
		||||
	OpIteratorNext                   // Iterator next
 | 
			
		||||
	OpIteratorKey                    // Iterator key
 | 
			
		||||
	OpIteratorValue                  // Iterator value
 | 
			
		||||
	OpConstant      Opcode = iota // Load constant
 | 
			
		||||
	OpBComplement                 // bitwise complement
 | 
			
		||||
	OpPop                         // Pop
 | 
			
		||||
	OpTrue                        // Push true
 | 
			
		||||
	OpFalse                       // Push false
 | 
			
		||||
	OpEqual                       // Equal ==
 | 
			
		||||
	OpNotEqual                    // Not equal !=
 | 
			
		||||
	OpMinus                       // Minus -
 | 
			
		||||
	OpLNot                        // Logical not !
 | 
			
		||||
	OpJumpFalsy                   // Jump if falsy
 | 
			
		||||
	OpAndJump                     // Logical AND jump
 | 
			
		||||
	OpOrJump                      // Logical OR jump
 | 
			
		||||
	OpJump                        // Jump
 | 
			
		||||
	OpNull                        // Push null
 | 
			
		||||
	OpArray                       // Array object
 | 
			
		||||
	OpMap                         // Map object
 | 
			
		||||
	OpError                       // Error object
 | 
			
		||||
	OpImmutable                   // Immutable object
 | 
			
		||||
	OpIndex                       // Index operation
 | 
			
		||||
	OpSliceIndex                  // Slice operation
 | 
			
		||||
	OpCall                        // Call function
 | 
			
		||||
	OpReturn                      // Return
 | 
			
		||||
	OpGetGlobal                   // Get global variable
 | 
			
		||||
	OpSetGlobal                   // Set global variable
 | 
			
		||||
	OpSetSelGlobal                // Set global variable using selectors
 | 
			
		||||
	OpGetLocal                    // Get local variable
 | 
			
		||||
	OpSetLocal                    // Set local variable
 | 
			
		||||
	OpDefineLocal                 // Define local variable
 | 
			
		||||
	OpSetSelLocal                 // Set local variable using selectors
 | 
			
		||||
	OpGetFreePtr                  // Get free variable pointer object
 | 
			
		||||
	OpGetFree                     // Get free variables
 | 
			
		||||
	OpSetFree                     // Set free variables
 | 
			
		||||
	OpGetLocalPtr                 // Get local variable as a pointer
 | 
			
		||||
	OpSetSelFree                  // Set free variables using selectors
 | 
			
		||||
	OpGetBuiltin                  // Get builtin function
 | 
			
		||||
	OpClosure                     // Push closure
 | 
			
		||||
	OpIteratorInit                // Iterator init
 | 
			
		||||
	OpIteratorNext                // Iterator next
 | 
			
		||||
	OpIteratorKey                 // Iterator key
 | 
			
		||||
	OpIteratorValue               // Iterator value
 | 
			
		||||
	OpBinaryOp                    // Binary Operation
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// OpcodeNames is opcode names.
 | 
			
		||||
var OpcodeNames = [...]string{
 | 
			
		||||
	OpConstant:         "CONST",
 | 
			
		||||
	OpPop:              "POP",
 | 
			
		||||
	OpTrue:             "TRUE",
 | 
			
		||||
	OpFalse:            "FALSE",
 | 
			
		||||
	OpAdd:              "ADD",
 | 
			
		||||
	OpSub:              "SUB",
 | 
			
		||||
	OpMul:              "MUL",
 | 
			
		||||
	OpDiv:              "DIV",
 | 
			
		||||
	OpRem:              "REM",
 | 
			
		||||
	OpBAnd:             "AND",
 | 
			
		||||
	OpBOr:              "OR",
 | 
			
		||||
	OpBXor:             "XOR",
 | 
			
		||||
	OpBAndNot:          "ANDN",
 | 
			
		||||
	OpBShiftLeft:       "SHL",
 | 
			
		||||
	OpBShiftRight:      "SHR",
 | 
			
		||||
	OpBComplement:      "NEG",
 | 
			
		||||
	OpEqual:            "EQL",
 | 
			
		||||
	OpNotEqual:         "NEQ",
 | 
			
		||||
	OpGreaterThan:      "GTR",
 | 
			
		||||
	OpGreaterThanEqual: "GEQ",
 | 
			
		||||
	OpMinus:            "NEG",
 | 
			
		||||
	OpLNot:             "NOT",
 | 
			
		||||
	OpJumpFalsy:        "JMPF",
 | 
			
		||||
	OpAndJump:          "ANDJMP",
 | 
			
		||||
	OpOrJump:           "ORJMP",
 | 
			
		||||
	OpJump:             "JMP",
 | 
			
		||||
	OpNull:             "NULL",
 | 
			
		||||
	OpGetGlobal:        "GETG",
 | 
			
		||||
	OpSetGlobal:        "SETG",
 | 
			
		||||
	OpSetSelGlobal:     "SETSG",
 | 
			
		||||
	OpArray:            "ARR",
 | 
			
		||||
	OpMap:              "MAP",
 | 
			
		||||
	OpError:            "ERROR",
 | 
			
		||||
	OpImmutable:        "IMMUT",
 | 
			
		||||
	OpIndex:            "INDEX",
 | 
			
		||||
	OpSliceIndex:       "SLICE",
 | 
			
		||||
	OpCall:             "CALL",
 | 
			
		||||
	OpReturn:           "RET",
 | 
			
		||||
	OpReturnValue:      "RETVAL",
 | 
			
		||||
	OpGetLocal:         "GETL",
 | 
			
		||||
	OpSetLocal:         "SETL",
 | 
			
		||||
	OpDefineLocal:      "DEFL",
 | 
			
		||||
	OpSetSelLocal:      "SETSL",
 | 
			
		||||
	OpGetBuiltin:       "BUILTIN",
 | 
			
		||||
	OpGetBuiltinModule: "BLTMOD",
 | 
			
		||||
	OpClosure:          "CLOSURE",
 | 
			
		||||
	OpGetFree:          "GETF",
 | 
			
		||||
	OpSetFree:          "SETF",
 | 
			
		||||
	OpSetSelFree:       "SETSF",
 | 
			
		||||
	OpIteratorInit:     "ITER",
 | 
			
		||||
	OpIteratorNext:     "ITNXT",
 | 
			
		||||
	OpIteratorKey:      "ITKEY",
 | 
			
		||||
	OpIteratorValue:    "ITVAL",
 | 
			
		||||
	OpConstant:      "CONST",
 | 
			
		||||
	OpPop:           "POP",
 | 
			
		||||
	OpTrue:          "TRUE",
 | 
			
		||||
	OpFalse:         "FALSE",
 | 
			
		||||
	OpBComplement:   "NEG",
 | 
			
		||||
	OpEqual:         "EQL",
 | 
			
		||||
	OpNotEqual:      "NEQ",
 | 
			
		||||
	OpMinus:         "NEG",
 | 
			
		||||
	OpLNot:          "NOT",
 | 
			
		||||
	OpJumpFalsy:     "JMPF",
 | 
			
		||||
	OpAndJump:       "ANDJMP",
 | 
			
		||||
	OpOrJump:        "ORJMP",
 | 
			
		||||
	OpJump:          "JMP",
 | 
			
		||||
	OpNull:          "NULL",
 | 
			
		||||
	OpGetGlobal:     "GETG",
 | 
			
		||||
	OpSetGlobal:     "SETG",
 | 
			
		||||
	OpSetSelGlobal:  "SETSG",
 | 
			
		||||
	OpArray:         "ARR",
 | 
			
		||||
	OpMap:           "MAP",
 | 
			
		||||
	OpError:         "ERROR",
 | 
			
		||||
	OpImmutable:     "IMMUT",
 | 
			
		||||
	OpIndex:         "INDEX",
 | 
			
		||||
	OpSliceIndex:    "SLICE",
 | 
			
		||||
	OpCall:          "CALL",
 | 
			
		||||
	OpReturn:        "RET",
 | 
			
		||||
	OpGetLocal:      "GETL",
 | 
			
		||||
	OpSetLocal:      "SETL",
 | 
			
		||||
	OpDefineLocal:   "DEFL",
 | 
			
		||||
	OpSetSelLocal:   "SETSL",
 | 
			
		||||
	OpGetBuiltin:    "BUILTIN",
 | 
			
		||||
	OpClosure:       "CLOSURE",
 | 
			
		||||
	OpGetFreePtr:    "GETFP",
 | 
			
		||||
	OpGetFree:       "GETF",
 | 
			
		||||
	OpSetFree:       "SETF",
 | 
			
		||||
	OpGetLocalPtr:   "GETLP",
 | 
			
		||||
	OpSetSelFree:    "SETSF",
 | 
			
		||||
	OpIteratorInit:  "ITER",
 | 
			
		||||
	OpIteratorNext:  "ITNXT",
 | 
			
		||||
	OpIteratorKey:   "ITKEY",
 | 
			
		||||
	OpIteratorValue: "ITVAL",
 | 
			
		||||
	OpBinaryOp:      "BINARYOP",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OpcodeOperands is the number of operands.
 | 
			
		||||
var OpcodeOperands = [...][]int{
 | 
			
		||||
	OpConstant:         {2},
 | 
			
		||||
	OpPop:              {},
 | 
			
		||||
	OpTrue:             {},
 | 
			
		||||
	OpFalse:            {},
 | 
			
		||||
	OpAdd:              {},
 | 
			
		||||
	OpSub:              {},
 | 
			
		||||
	OpMul:              {},
 | 
			
		||||
	OpDiv:              {},
 | 
			
		||||
	OpRem:              {},
 | 
			
		||||
	OpBAnd:             {},
 | 
			
		||||
	OpBOr:              {},
 | 
			
		||||
	OpBXor:             {},
 | 
			
		||||
	OpBAndNot:          {},
 | 
			
		||||
	OpBShiftLeft:       {},
 | 
			
		||||
	OpBShiftRight:      {},
 | 
			
		||||
	OpBComplement:      {},
 | 
			
		||||
	OpEqual:            {},
 | 
			
		||||
	OpNotEqual:         {},
 | 
			
		||||
	OpGreaterThan:      {},
 | 
			
		||||
	OpGreaterThanEqual: {},
 | 
			
		||||
	OpMinus:            {},
 | 
			
		||||
	OpLNot:             {},
 | 
			
		||||
	OpJumpFalsy:        {2},
 | 
			
		||||
	OpAndJump:          {2},
 | 
			
		||||
	OpOrJump:           {2},
 | 
			
		||||
	OpJump:             {2},
 | 
			
		||||
	OpNull:             {},
 | 
			
		||||
	OpGetGlobal:        {2},
 | 
			
		||||
	OpSetGlobal:        {2},
 | 
			
		||||
	OpSetSelGlobal:     {2, 1},
 | 
			
		||||
	OpArray:            {2},
 | 
			
		||||
	OpMap:              {2},
 | 
			
		||||
	OpError:            {},
 | 
			
		||||
	OpImmutable:        {},
 | 
			
		||||
	OpIndex:            {},
 | 
			
		||||
	OpSliceIndex:       {},
 | 
			
		||||
	OpCall:             {1},
 | 
			
		||||
	OpReturn:           {},
 | 
			
		||||
	OpReturnValue:      {},
 | 
			
		||||
	OpGetLocal:         {1},
 | 
			
		||||
	OpSetLocal:         {1},
 | 
			
		||||
	OpDefineLocal:      {1},
 | 
			
		||||
	OpSetSelLocal:      {1, 1},
 | 
			
		||||
	OpGetBuiltin:       {1},
 | 
			
		||||
	OpGetBuiltinModule: {},
 | 
			
		||||
	OpClosure:          {2, 1},
 | 
			
		||||
	OpGetFree:          {1},
 | 
			
		||||
	OpSetFree:          {1},
 | 
			
		||||
	OpSetSelFree:       {1, 1},
 | 
			
		||||
	OpIteratorInit:     {},
 | 
			
		||||
	OpIteratorNext:     {},
 | 
			
		||||
	OpIteratorKey:      {},
 | 
			
		||||
	OpIteratorValue:    {},
 | 
			
		||||
	OpConstant:      {2},
 | 
			
		||||
	OpPop:           {},
 | 
			
		||||
	OpTrue:          {},
 | 
			
		||||
	OpFalse:         {},
 | 
			
		||||
	OpBComplement:   {},
 | 
			
		||||
	OpEqual:         {},
 | 
			
		||||
	OpNotEqual:      {},
 | 
			
		||||
	OpMinus:         {},
 | 
			
		||||
	OpLNot:          {},
 | 
			
		||||
	OpJumpFalsy:     {2},
 | 
			
		||||
	OpAndJump:       {2},
 | 
			
		||||
	OpOrJump:        {2},
 | 
			
		||||
	OpJump:          {2},
 | 
			
		||||
	OpNull:          {},
 | 
			
		||||
	OpGetGlobal:     {2},
 | 
			
		||||
	OpSetGlobal:     {2},
 | 
			
		||||
	OpSetSelGlobal:  {2, 1},
 | 
			
		||||
	OpArray:         {2},
 | 
			
		||||
	OpMap:           {2},
 | 
			
		||||
	OpError:         {},
 | 
			
		||||
	OpImmutable:     {},
 | 
			
		||||
	OpIndex:         {},
 | 
			
		||||
	OpSliceIndex:    {},
 | 
			
		||||
	OpCall:          {1},
 | 
			
		||||
	OpReturn:        {1},
 | 
			
		||||
	OpGetLocal:      {1},
 | 
			
		||||
	OpSetLocal:      {1},
 | 
			
		||||
	OpDefineLocal:   {1},
 | 
			
		||||
	OpSetSelLocal:   {1, 1},
 | 
			
		||||
	OpGetBuiltin:    {1},
 | 
			
		||||
	OpClosure:       {2, 1},
 | 
			
		||||
	OpGetFreePtr:    {1},
 | 
			
		||||
	OpGetFree:       {1},
 | 
			
		||||
	OpSetFree:       {1},
 | 
			
		||||
	OpGetLocalPtr:   {1},
 | 
			
		||||
	OpSetSelFree:    {1, 1},
 | 
			
		||||
	OpIteratorInit:  {},
 | 
			
		||||
	OpIteratorNext:  {},
 | 
			
		||||
	OpIteratorKey:   {},
 | 
			
		||||
	OpIteratorValue: {},
 | 
			
		||||
	OpBinaryOp:      {1},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ReadOperands reads operands from the bytecode.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/d5/tengo/compiler/symbol_table.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/d5/tengo/compiler/symbol_table.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -64,9 +64,7 @@ func (t *SymbolTable) Resolve(name string) (symbol *Symbol, depth int, ok bool)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !t.block {
 | 
			
		||||
			depth++
 | 
			
		||||
		}
 | 
			
		||||
		depth++
 | 
			
		||||
 | 
			
		||||
		// if symbol is defined in parent table and if it's not global/builtin
 | 
			
		||||
		// then it's free variable.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/d5/tengo/objects/break.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/d5/tengo/objects/break.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,37 +0,0 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/compiler/token"
 | 
			
		||||
 | 
			
		||||
// Break represents a break statement.
 | 
			
		||||
type Break struct{}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
func (o *Break) TypeName() string {
 | 
			
		||||
	return "break"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Break) String() string {
 | 
			
		||||
	return "<break>"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BinaryOp returns another object that is the result of
 | 
			
		||||
// a given binary operator and a right-hand side object.
 | 
			
		||||
func (o *Break) BinaryOp(op token.Token, rhs Object) (Object, error) {
 | 
			
		||||
	return nil, ErrInvalidOperator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy returns a copy of the type.
 | 
			
		||||
func (o *Break) Copy() Object {
 | 
			
		||||
	return &Break{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFalsy returns true if the value of the type is falsy.
 | 
			
		||||
func (o *Break) IsFalsy() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns true if the value of the type
 | 
			
		||||
// is equal to the value of another object.
 | 
			
		||||
func (o *Break) Equals(x Object) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								vendor/github.com/d5/tengo/objects/builtin_json.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/d5/tengo/objects/builtin_json.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,60 +0,0 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// to_json(v object) => bytes
 | 
			
		||||
func builtinToJSON(args ...Object) (Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := json.Marshal(objectToInterface(args[0]))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &Error{Value: &String{Value: err.Error()}}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(res) > tengo.MaxBytesLen {
 | 
			
		||||
		return nil, ErrBytesLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Bytes{Value: res}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// from_json(data string/bytes) => object
 | 
			
		||||
func builtinFromJSON(args ...Object) (Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var target interface{}
 | 
			
		||||
 | 
			
		||||
	switch o := args[0].(type) {
 | 
			
		||||
	case *Bytes:
 | 
			
		||||
		err := json.Unmarshal(o.Value, &target)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &Error{Value: &String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
	case *String:
 | 
			
		||||
		err := json.Unmarshal([]byte(o.Value), &target)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &Error{Value: &String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "bytes/string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := FromInterface(target)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/d5/tengo/objects/builtin_module.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/d5/tengo/objects/builtin_module.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
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}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								vendor/github.com/d5/tengo/objects/builtin_print.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/d5/tengo/objects/builtin_print.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,83 +0,0 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// print(args...)
 | 
			
		||||
func builtinPrint(args ...Object) (Object, error) {
 | 
			
		||||
	for _, arg := range args {
 | 
			
		||||
		if str, ok := arg.(*String); ok {
 | 
			
		||||
			fmt.Println(str.Value)
 | 
			
		||||
		} else {
 | 
			
		||||
			fmt.Println(arg.String())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// printf("format", args...)
 | 
			
		||||
func builtinPrintf(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 {
 | 
			
		||||
		fmt.Print(format)
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	formatArgs := make([]interface{}, numArgs-1, numArgs-1)
 | 
			
		||||
	for idx, arg := range args[1:] {
 | 
			
		||||
		formatArgs[idx] = objectToInterface(arg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Printf(format.Value, formatArgs...)
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sprintf("format", args...)
 | 
			
		||||
func builtinSprintf(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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	formatArgs := make([]interface{}, numArgs-1, numArgs-1)
 | 
			
		||||
	for idx, arg := range args[1:] {
 | 
			
		||||
		formatArgs[idx] = objectToInterface(arg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s := fmt.Sprintf(format.Value, formatArgs...)
 | 
			
		||||
 | 
			
		||||
	if len(s) > tengo.MaxStringLen {
 | 
			
		||||
		return nil, ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &String{Value: s}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/github.com/d5/tengo/objects/builtin_type_checks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/d5/tengo/objects/builtin_type_checks.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -181,3 +181,15 @@ func builtinIsCallable(args ...Object) (Object, error) {
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								vendor/github.com/d5/tengo/objects/builtins.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/d5/tengo/objects/builtins.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -2,19 +2,7 @@ package objects
 | 
			
		||||
 | 
			
		||||
// Builtins contains all default builtin functions.
 | 
			
		||||
// Use GetBuiltinFunctions instead of accessing Builtins directly.
 | 
			
		||||
var Builtins = []BuiltinFunction{
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "print",
 | 
			
		||||
		Value: builtinPrint,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "printf",
 | 
			
		||||
		Value: builtinPrintf,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "sprintf",
 | 
			
		||||
		Value: builtinSprintf,
 | 
			
		||||
	},
 | 
			
		||||
var Builtins = []*BuiltinFunction{
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "len",
 | 
			
		||||
		Value: builtinLen,
 | 
			
		||||
@@ -95,6 +83,10 @@ var Builtins = []BuiltinFunction{
 | 
			
		||||
		Name:  "is_immutable_map",
 | 
			
		||||
		Value: builtinIsImmutableMap,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "is_iterable",
 | 
			
		||||
		Value: builtinIsIterable,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "is_time",
 | 
			
		||||
		Value: builtinIsTime,
 | 
			
		||||
@@ -115,50 +107,8 @@ var Builtins = []BuiltinFunction{
 | 
			
		||||
		Name:  "is_callable",
 | 
			
		||||
		Value: builtinIsCallable,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "to_json",
 | 
			
		||||
		Value: builtinToJSON,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "from_json",
 | 
			
		||||
		Value: builtinFromJSON,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		Name:  "type_name",
 | 
			
		||||
		Value: builtinTypeName,
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllBuiltinFunctionNames returns a list of all default builtin function names.
 | 
			
		||||
func AllBuiltinFunctionNames() []string {
 | 
			
		||||
	var names []string
 | 
			
		||||
	for _, bf := range Builtins {
 | 
			
		||||
		names = append(names, bf.Name)
 | 
			
		||||
	}
 | 
			
		||||
	return names
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetBuiltinFunctions returns a slice of builtin function objects.
 | 
			
		||||
// GetBuiltinFunctions removes the duplicate names, and, the returned builtin functions
 | 
			
		||||
// are not guaranteed to be in the same order as names.
 | 
			
		||||
func GetBuiltinFunctions(names ...string) []*BuiltinFunction {
 | 
			
		||||
	include := make(map[string]bool)
 | 
			
		||||
	for _, name := range names {
 | 
			
		||||
		include[name] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var builtinFuncs []*BuiltinFunction
 | 
			
		||||
	for _, bf := range Builtins {
 | 
			
		||||
		if include[bf.Name] {
 | 
			
		||||
			bf := bf
 | 
			
		||||
			builtinFuncs = append(builtinFuncs, &bf)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return builtinFuncs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllBuiltinFunctions returns all builtin functions.
 | 
			
		||||
func GetAllBuiltinFunctions() []*BuiltinFunction {
 | 
			
		||||
	return GetBuiltinFunctions(AllBuiltinFunctionNames()...)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/d5/tengo/objects/bytes.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/d5/tengo/objects/bytes.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -79,3 +79,11 @@ func (o *Bytes) IndexGet(index Object) (res Object, err error) {
 | 
			
		||||
 | 
			
		||||
	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
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/d5/tengo/objects/bytes_iterator.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
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])}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/d5/tengo/objects/closure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/d5/tengo/objects/closure.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ import (
 | 
			
		||||
// Closure represents a function closure.
 | 
			
		||||
type Closure struct {
 | 
			
		||||
	Fn   *CompiledFunction
 | 
			
		||||
	Free []*Object
 | 
			
		||||
	Free []*ObjectPtr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
@@ -29,7 +29,7 @@ func (o *Closure) BinaryOp(op token.Token, rhs Object) (Object, error) {
 | 
			
		||||
func (o *Closure) Copy() Object {
 | 
			
		||||
	return &Closure{
 | 
			
		||||
		Fn:   o.Fn.Copy().(*CompiledFunction),
 | 
			
		||||
		Free: append([]*Object{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
 | 
			
		||||
		Free: append([]*ObjectPtr{}, o.Free...), // DO NOT Copy() of elements; these are variable pointers
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/d5/tengo/objects/compiled_function.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/d5/tengo/objects/compiled_function.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -47,3 +47,14 @@ func (o *CompiledFunction) IsFalsy() bool {
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/github.com/d5/tengo/objects/continue.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/d5/tengo/objects/continue.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,38 +0,0 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/compiler/token"
 | 
			
		||||
 | 
			
		||||
// Continue represents a continue statement.
 | 
			
		||||
type Continue struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
func (o *Continue) TypeName() string {
 | 
			
		||||
	return "continue"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Continue) String() string {
 | 
			
		||||
	return "<continue>"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BinaryOp returns another object that is the result of
 | 
			
		||||
// a given binary operator and a right-hand side object.
 | 
			
		||||
func (o *Continue) BinaryOp(op token.Token, rhs Object) (Object, error) {
 | 
			
		||||
	return nil, ErrInvalidOperator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy returns a copy of the type.
 | 
			
		||||
func (o *Continue) Copy() Object {
 | 
			
		||||
	return &Continue{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFalsy returns true if the value of the type is falsy.
 | 
			
		||||
func (o *Continue) IsFalsy() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns true if the value of the type
 | 
			
		||||
// is equal to the value of another object.
 | 
			
		||||
func (o *Continue) Equals(x Object) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/d5/tengo/objects/conversion.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/d5/tengo/objects/conversion.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,7 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -158,8 +159,8 @@ func ToTime(o Object) (v time.Time, ok bool) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// objectToInterface attempts to convert an object o to an interface{} value
 | 
			
		||||
func objectToInterface(o Object) (res interface{}) {
 | 
			
		||||
// ToInterface attempts to convert an object o to an interface{} value
 | 
			
		||||
func ToInterface(o Object) (res interface{}) {
 | 
			
		||||
	switch o := o.(type) {
 | 
			
		||||
	case *Int:
 | 
			
		||||
		res = o.Value
 | 
			
		||||
@@ -176,13 +177,29 @@ func objectToInterface(o Object) (res interface{}) {
 | 
			
		||||
	case *Array:
 | 
			
		||||
		res = make([]interface{}, len(o.Value))
 | 
			
		||||
		for i, val := range o.Value {
 | 
			
		||||
			res.([]interface{})[i] = objectToInterface(val)
 | 
			
		||||
			res.([]interface{})[i] = ToInterface(val)
 | 
			
		||||
		}
 | 
			
		||||
	case *ImmutableArray:
 | 
			
		||||
		res = make([]interface{}, len(o.Value))
 | 
			
		||||
		for i, val := range o.Value {
 | 
			
		||||
			res.([]interface{})[i] = ToInterface(val)
 | 
			
		||||
		}
 | 
			
		||||
	case *Map:
 | 
			
		||||
		res = make(map[string]interface{})
 | 
			
		||||
		for key, v := range o.Value {
 | 
			
		||||
			res.(map[string]interface{})[key] = objectToInterface(v)
 | 
			
		||||
			res.(map[string]interface{})[key] = ToInterface(v)
 | 
			
		||||
		}
 | 
			
		||||
	case *ImmutableMap:
 | 
			
		||||
		res = make(map[string]interface{})
 | 
			
		||||
		for key, v := range o.Value {
 | 
			
		||||
			res.(map[string]interface{})[key] = ToInterface(v)
 | 
			
		||||
		}
 | 
			
		||||
	case *Time:
 | 
			
		||||
		res = o.Value
 | 
			
		||||
	case *Error:
 | 
			
		||||
		res = errors.New(o.String())
 | 
			
		||||
	case *Undefined:
 | 
			
		||||
		res = nil
 | 
			
		||||
	case Object:
 | 
			
		||||
		return o
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								vendor/github.com/d5/tengo/objects/count_objects.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/d5/tengo/objects/count_objects.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/d5/tengo/objects/importable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/d5/tengo/objects/importable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								vendor/github.com/d5/tengo/objects/module_map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/d5/tengo/objects/module_map.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
// ModuleMap represents a set of named modules.
 | 
			
		||||
// Use NewModuleMap to create a new module map.
 | 
			
		||||
type ModuleMap struct {
 | 
			
		||||
	m map[string]Importable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewModuleMap creates a new module map.
 | 
			
		||||
func NewModuleMap() *ModuleMap {
 | 
			
		||||
	return &ModuleMap{
 | 
			
		||||
		m: make(map[string]Importable),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add adds an import module.
 | 
			
		||||
func (m *ModuleMap) Add(name string, module Importable) {
 | 
			
		||||
	m.m[name] = module
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddBuiltinModule adds a builtin module.
 | 
			
		||||
func (m *ModuleMap) AddBuiltinModule(name string, attrs map[string]Object) {
 | 
			
		||||
	m.m[name] = &BuiltinModule{Attrs: attrs}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddSourceModule adds a source module.
 | 
			
		||||
func (m *ModuleMap) AddSourceModule(name string, src []byte) {
 | 
			
		||||
	m.m[name] = &SourceModule{Src: src}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove removes a named module.
 | 
			
		||||
func (m *ModuleMap) Remove(name string) {
 | 
			
		||||
	delete(m.m, name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns an import module identified by name.
 | 
			
		||||
// It returns if the name is not found.
 | 
			
		||||
func (m *ModuleMap) Get(name string) Importable {
 | 
			
		||||
	return m.m[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetBuiltinModule returns a builtin module identified by name.
 | 
			
		||||
// It returns if the name is not found or the module is not a builtin module.
 | 
			
		||||
func (m *ModuleMap) GetBuiltinModule(name string) *BuiltinModule {
 | 
			
		||||
	mod, _ := m.m[name].(*BuiltinModule)
 | 
			
		||||
	return mod
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetSourceModule returns a source module identified by name.
 | 
			
		||||
// It returns if the name is not found or the module is not a source module.
 | 
			
		||||
func (m *ModuleMap) GetSourceModule(name string) *SourceModule {
 | 
			
		||||
	mod, _ := m.m[name].(*SourceModule)
 | 
			
		||||
	return mod
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy creates a copy of the module map.
 | 
			
		||||
func (m *ModuleMap) Copy() *ModuleMap {
 | 
			
		||||
	c := &ModuleMap{
 | 
			
		||||
		m: make(map[string]Importable),
 | 
			
		||||
	}
 | 
			
		||||
	for name, mod := range m.m {
 | 
			
		||||
		c.m[name] = mod
 | 
			
		||||
	}
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Len returns the number of named modules.
 | 
			
		||||
func (m *ModuleMap) Len() int {
 | 
			
		||||
	return len(m.m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddMap adds named modules from another module map.
 | 
			
		||||
func (m *ModuleMap) AddMap(o *ModuleMap) {
 | 
			
		||||
	for name, mod := range o.m {
 | 
			
		||||
		m.m[name] = mod
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/github.com/d5/tengo/objects/object_ptr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/d5/tengo/objects/object_ptr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/d5/tengo/compiler/token"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ObjectPtr represents a free variable.
 | 
			
		||||
type ObjectPtr struct {
 | 
			
		||||
	Value *Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *ObjectPtr) String() string {
 | 
			
		||||
	return "free-var"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
func (o *ObjectPtr) TypeName() string {
 | 
			
		||||
	return "<free-var>"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BinaryOp returns another object that is the result of
 | 
			
		||||
// a given binary operator and a right-hand side object.
 | 
			
		||||
func (o *ObjectPtr) BinaryOp(op token.Token, rhs Object) (Object, error) {
 | 
			
		||||
	return nil, ErrInvalidOperator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy returns a copy of the type.
 | 
			
		||||
func (o *ObjectPtr) Copy() Object {
 | 
			
		||||
	return o
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFalsy returns true if the value of the type is falsy.
 | 
			
		||||
func (o *ObjectPtr) IsFalsy() bool {
 | 
			
		||||
	return o.Value == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns true if the value of the type
 | 
			
		||||
// is equal to the value of another object.
 | 
			
		||||
func (o *ObjectPtr) Equals(x Object) bool {
 | 
			
		||||
	return o == x
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/d5/tengo/objects/return_value.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/d5/tengo/objects/return_value.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,39 +0,0 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/compiler/token"
 | 
			
		||||
 | 
			
		||||
// ReturnValue represents a value that is being returned.
 | 
			
		||||
type ReturnValue struct {
 | 
			
		||||
	Value Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
func (o *ReturnValue) TypeName() string {
 | 
			
		||||
	return "return-value"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *ReturnValue) String() string {
 | 
			
		||||
	return "<return-value>"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BinaryOp returns another object that is the result of
 | 
			
		||||
// a given binary operator and a right-hand side object.
 | 
			
		||||
func (o *ReturnValue) BinaryOp(op token.Token, rhs Object) (Object, error) {
 | 
			
		||||
	return nil, ErrInvalidOperator
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy returns a copy of the type.
 | 
			
		||||
func (o *ReturnValue) Copy() Object {
 | 
			
		||||
	return &ReturnValue{Value: o.Copy()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFalsy returns true if the value of the type is falsy.
 | 
			
		||||
func (o *ReturnValue) IsFalsy() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns true if the value of the type
 | 
			
		||||
// is equal to the value of another object.
 | 
			
		||||
func (o *ReturnValue) Equals(x Object) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/d5/tengo/objects/source_module.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/d5/tengo/objects/source_module.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package objects
 | 
			
		||||
 | 
			
		||||
// SourceModule is an importable module that's written in Tengo.
 | 
			
		||||
type SourceModule struct {
 | 
			
		||||
	Src []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Import returns a module source code.
 | 
			
		||||
func (m *SourceModule) Import(_ string) (interface{}, error) {
 | 
			
		||||
	return m.Src, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/d5/tengo/objects/user_function.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/d5/tengo/objects/user_function.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,8 +6,9 @@ import (
 | 
			
		||||
 | 
			
		||||
// UserFunction represents a user function.
 | 
			
		||||
type UserFunction struct {
 | 
			
		||||
	Name  string
 | 
			
		||||
	Value CallableFunc
 | 
			
		||||
	Name       string
 | 
			
		||||
	Value      CallableFunc
 | 
			
		||||
	EncodingID string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TypeName returns the name of the type.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/d5/tengo/runtime/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/d5/tengo/runtime/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,3 +6,6 @@ import (
 | 
			
		||||
 | 
			
		||||
// ErrStackOverflow is a stack overflow error.
 | 
			
		||||
var ErrStackOverflow = errors.New("stack overflow")
 | 
			
		||||
 | 
			
		||||
// ErrObjectAllocLimit is an objects allocation limit error.
 | 
			
		||||
var ErrObjectAllocLimit = errors.New("object allocation limit exceeded")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/d5/tengo/runtime/frame.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/d5/tengo/runtime/frame.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ import (
 | 
			
		||||
// Frame represents a function call frame.
 | 
			
		||||
type Frame struct {
 | 
			
		||||
	fn          *objects.CompiledFunction
 | 
			
		||||
	freeVars    []*objects.Object
 | 
			
		||||
	freeVars    []*objects.ObjectPtr
 | 
			
		||||
	ip          int
 | 
			
		||||
	basePointer int
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										774
									
								
								vendor/github.com/d5/tengo/runtime/vm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										774
									
								
								vendor/github.com/d5/tengo/runtime/vm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										102
									
								
								vendor/github.com/d5/tengo/script/compiled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/d5/tengo/script/compiled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,6 +3,7 @@ package script
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/compiler"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
@@ -12,26 +13,39 @@ import (
 | 
			
		||||
// Compiled is a compiled instance of the user script.
 | 
			
		||||
// Use Script.Compile() to create Compiled object.
 | 
			
		||||
type Compiled struct {
 | 
			
		||||
	symbolTable *compiler.SymbolTable
 | 
			
		||||
	machine     *runtime.VM
 | 
			
		||||
	globalIndexes map[string]int // global symbol name to index
 | 
			
		||||
	bytecode      *compiler.Bytecode
 | 
			
		||||
	globals       []objects.Object
 | 
			
		||||
	maxAllocs     int64
 | 
			
		||||
	lock          sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run executes the compiled script in the virtual machine.
 | 
			
		||||
func (c *Compiled) Run() error {
 | 
			
		||||
	return c.machine.Run()
 | 
			
		||||
	c.lock.Lock()
 | 
			
		||||
	defer c.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	v := runtime.NewVM(c.bytecode, c.globals, c.maxAllocs)
 | 
			
		||||
 | 
			
		||||
	return v.Run()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RunContext is like Run but includes a context.
 | 
			
		||||
func (c *Compiled) RunContext(ctx context.Context) (err error) {
 | 
			
		||||
	c.lock.Lock()
 | 
			
		||||
	defer c.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	v := runtime.NewVM(c.bytecode, c.globals, c.maxAllocs)
 | 
			
		||||
 | 
			
		||||
	ch := make(chan error, 1)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		ch <- c.machine.Run()
 | 
			
		||||
		ch <- v.Run()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	select {
 | 
			
		||||
	case <-ctx.Done():
 | 
			
		||||
		c.machine.Abort()
 | 
			
		||||
		v.Abort()
 | 
			
		||||
		<-ch
 | 
			
		||||
		err = ctx.Err()
 | 
			
		||||
	case err = <-ch:
 | 
			
		||||
@@ -40,30 +54,58 @@ func (c *Compiled) RunContext(ctx context.Context) (err error) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Clone creates a new copy of Compiled.
 | 
			
		||||
// Cloned copies are safe for concurrent use by multiple goroutines.
 | 
			
		||||
func (c *Compiled) Clone() *Compiled {
 | 
			
		||||
	c.lock.Lock()
 | 
			
		||||
	defer c.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	clone := &Compiled{
 | 
			
		||||
		globalIndexes: c.globalIndexes,
 | 
			
		||||
		bytecode:      c.bytecode,
 | 
			
		||||
		globals:       make([]objects.Object, len(c.globals)),
 | 
			
		||||
		maxAllocs:     c.maxAllocs,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// copy global objects
 | 
			
		||||
	for idx, g := range c.globals {
 | 
			
		||||
		if g != nil {
 | 
			
		||||
			clone.globals[idx] = g
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return clone
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsDefined returns true if the variable name is defined (has value) before or after the execution.
 | 
			
		||||
func (c *Compiled) IsDefined(name string) bool {
 | 
			
		||||
	symbol, _, ok := c.symbolTable.Resolve(name)
 | 
			
		||||
	c.lock.RLock()
 | 
			
		||||
	defer c.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	idx, ok := c.globalIndexes[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v := c.machine.Globals()[symbol.Index]
 | 
			
		||||
	v := c.globals[idx]
 | 
			
		||||
	if v == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return *v != objects.UndefinedValue
 | 
			
		||||
	return v != objects.UndefinedValue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns a variable identified by the name.
 | 
			
		||||
func (c *Compiled) Get(name string) *Variable {
 | 
			
		||||
	value := &objects.UndefinedValue
 | 
			
		||||
	c.lock.RLock()
 | 
			
		||||
	defer c.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
	symbol, _, ok := c.symbolTable.Resolve(name)
 | 
			
		||||
	if ok && symbol.Scope == compiler.ScopeGlobal {
 | 
			
		||||
		value = c.machine.Globals()[symbol.Index]
 | 
			
		||||
	value := objects.UndefinedValue
 | 
			
		||||
 | 
			
		||||
	if idx, ok := c.globalIndexes[name]; ok {
 | 
			
		||||
		value = c.globals[idx]
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			value = &objects.UndefinedValue
 | 
			
		||||
			value = objects.UndefinedValue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -75,20 +117,21 @@ func (c *Compiled) Get(name string) *Variable {
 | 
			
		||||
 | 
			
		||||
// GetAll returns all the variables that are defined by the compiled script.
 | 
			
		||||
func (c *Compiled) GetAll() []*Variable {
 | 
			
		||||
	var vars []*Variable
 | 
			
		||||
	for _, name := range c.symbolTable.Names() {
 | 
			
		||||
		symbol, _, ok := c.symbolTable.Resolve(name)
 | 
			
		||||
		if ok && symbol.Scope == compiler.ScopeGlobal {
 | 
			
		||||
			value := c.machine.Globals()[symbol.Index]
 | 
			
		||||
			if value == nil {
 | 
			
		||||
				value = &objects.UndefinedValue
 | 
			
		||||
			}
 | 
			
		||||
	c.lock.RLock()
 | 
			
		||||
	defer c.lock.RUnlock()
 | 
			
		||||
 | 
			
		||||
			vars = append(vars, &Variable{
 | 
			
		||||
				name:  name,
 | 
			
		||||
				value: value,
 | 
			
		||||
			})
 | 
			
		||||
	var vars []*Variable
 | 
			
		||||
 | 
			
		||||
	for name, idx := range c.globalIndexes {
 | 
			
		||||
		value := c.globals[idx]
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			value = objects.UndefinedValue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vars = append(vars, &Variable{
 | 
			
		||||
			name:  name,
 | 
			
		||||
			value: value,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vars
 | 
			
		||||
@@ -97,17 +140,20 @@ func (c *Compiled) GetAll() []*Variable {
 | 
			
		||||
// Set replaces the value of a global variable identified by the name.
 | 
			
		||||
// An error will be returned if the name was not defined during compilation.
 | 
			
		||||
func (c *Compiled) Set(name string, value interface{}) error {
 | 
			
		||||
	c.lock.Lock()
 | 
			
		||||
	defer c.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	obj, err := objects.FromInterface(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	symbol, _, ok := c.symbolTable.Resolve(name)
 | 
			
		||||
	if !ok || symbol.Scope != compiler.ScopeGlobal {
 | 
			
		||||
	idx, ok := c.globalIndexes[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("'%s' is not defined", name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.machine.Globals()[symbol.Index] = &obj
 | 
			
		||||
	c.globals[idx] = obj
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/github.com/d5/tengo/script/conversion.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/d5/tengo/script/conversion.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,33 +0,0 @@
 | 
			
		||||
package script
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func objectToInterface(o objects.Object) interface{} {
 | 
			
		||||
	switch val := o.(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Map:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Int:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Float:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Bool:
 | 
			
		||||
		if val == objects.TrueValue {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		return false
 | 
			
		||||
	case *objects.Char:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.String:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Bytes:
 | 
			
		||||
		return val.Value
 | 
			
		||||
	case *objects.Undefined:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return o
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										127
									
								
								vendor/github.com/d5/tengo/script/script.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										127
									
								
								vendor/github.com/d5/tengo/script/script.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -14,17 +14,20 @@ import (
 | 
			
		||||
// Script can simplify compilation and execution of embedded scripts.
 | 
			
		||||
type Script struct {
 | 
			
		||||
	variables        map[string]*Variable
 | 
			
		||||
	builtinFuncs     []objects.Object
 | 
			
		||||
	builtinModules   map[string]*objects.Object
 | 
			
		||||
	userModuleLoader compiler.ModuleLoader
 | 
			
		||||
	modules          *objects.ModuleMap
 | 
			
		||||
	input            []byte
 | 
			
		||||
	maxAllocs        int64
 | 
			
		||||
	maxConstObjects  int
 | 
			
		||||
	enableFileImport bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New creates a Script instance with an input script.
 | 
			
		||||
func New(input []byte) *Script {
 | 
			
		||||
	return &Script{
 | 
			
		||||
		variables: make(map[string]*Variable),
 | 
			
		||||
		input:     input,
 | 
			
		||||
		variables:       make(map[string]*Variable),
 | 
			
		||||
		input:           input,
 | 
			
		||||
		maxAllocs:       -1,
 | 
			
		||||
		maxConstObjects: -1,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +40,7 @@ func (s *Script) Add(name string, value interface{}) error {
 | 
			
		||||
 | 
			
		||||
	s.variables[name] = &Variable{
 | 
			
		||||
		name:  name,
 | 
			
		||||
		value: &obj,
 | 
			
		||||
		value: obj,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
@@ -55,38 +58,31 @@ func (s *Script) Remove(name string) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetBuiltinFunctions allows to define builtin functions.
 | 
			
		||||
func (s *Script) SetBuiltinFunctions(funcs []*objects.BuiltinFunction) {
 | 
			
		||||
	if funcs != nil {
 | 
			
		||||
		s.builtinFuncs = make([]objects.Object, len(funcs))
 | 
			
		||||
		for idx, fn := range funcs {
 | 
			
		||||
			s.builtinFuncs[idx] = fn
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		s.builtinFuncs = []objects.Object{}
 | 
			
		||||
	}
 | 
			
		||||
// SetImports sets import modules.
 | 
			
		||||
func (s *Script) SetImports(modules *objects.ModuleMap) {
 | 
			
		||||
	s.modules = modules
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetBuiltinModules allows to define builtin modules.
 | 
			
		||||
func (s *Script) SetBuiltinModules(modules map[string]*objects.ImmutableMap) {
 | 
			
		||||
	if modules != nil {
 | 
			
		||||
		s.builtinModules = make(map[string]*objects.Object, len(modules))
 | 
			
		||||
		for k, mod := range modules {
 | 
			
		||||
			s.builtinModules[k] = objectPtr(mod)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		s.builtinModules = map[string]*objects.Object{}
 | 
			
		||||
	}
 | 
			
		||||
// SetMaxAllocs sets the maximum number of objects allocations during the run time.
 | 
			
		||||
// Compiled script will return runtime.ErrObjectAllocLimit error if it exceeds this limit.
 | 
			
		||||
func (s *Script) SetMaxAllocs(n int64) {
 | 
			
		||||
	s.maxAllocs = n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetUserModuleLoader sets the user module loader for the compiler.
 | 
			
		||||
func (s *Script) SetUserModuleLoader(loader compiler.ModuleLoader) {
 | 
			
		||||
	s.userModuleLoader = loader
 | 
			
		||||
// SetMaxConstObjects sets the maximum number of objects in the compiled constants.
 | 
			
		||||
func (s *Script) SetMaxConstObjects(n int) {
 | 
			
		||||
	s.maxConstObjects = n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableFileImport enables or disables module loading from local files.
 | 
			
		||||
// Local file modules are disabled by default.
 | 
			
		||||
func (s *Script) EnableFileImport(enable bool) {
 | 
			
		||||
	s.enableFileImport = enable
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compile compiles the script with all the defined variables, and, returns Compiled object.
 | 
			
		||||
func (s *Script) Compile() (*Compiled, error) {
 | 
			
		||||
	symbolTable, builtinModules, globals, err := s.prepCompile()
 | 
			
		||||
	symbolTable, globals, err := s.prepCompile()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -100,19 +96,41 @@ func (s *Script) Compile() (*Compiled, error) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c := compiler.NewCompiler(srcFile, symbolTable, nil, builtinModules, nil)
 | 
			
		||||
 | 
			
		||||
	if s.userModuleLoader != nil {
 | 
			
		||||
		c.SetModuleLoader(s.userModuleLoader)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c := compiler.NewCompiler(srcFile, symbolTable, nil, s.modules, nil)
 | 
			
		||||
	c.EnableFileImport(s.enableFileImport)
 | 
			
		||||
	if err := c.Compile(file); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// reduce globals size
 | 
			
		||||
	globals = globals[:symbolTable.MaxSymbols()+1]
 | 
			
		||||
 | 
			
		||||
	// global symbol names to indexes
 | 
			
		||||
	globalIndexes := make(map[string]int, len(globals))
 | 
			
		||||
	for _, name := range symbolTable.Names() {
 | 
			
		||||
		symbol, _, _ := symbolTable.Resolve(name)
 | 
			
		||||
		if symbol.Scope == compiler.ScopeGlobal {
 | 
			
		||||
			globalIndexes[name] = symbol.Index
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// remove duplicates from constants
 | 
			
		||||
	bytecode := c.Bytecode()
 | 
			
		||||
	bytecode.RemoveDuplicates()
 | 
			
		||||
 | 
			
		||||
	// check the constant objects limit
 | 
			
		||||
	if s.maxConstObjects >= 0 {
 | 
			
		||||
		cnt := bytecode.CountObjects()
 | 
			
		||||
		if cnt > s.maxConstObjects {
 | 
			
		||||
			return nil, fmt.Errorf("exceeding constant objects limit: %d", cnt)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Compiled{
 | 
			
		||||
		symbolTable: symbolTable,
 | 
			
		||||
		machine:     runtime.NewVM(c.Bytecode(), globals, s.builtinFuncs, s.builtinModules),
 | 
			
		||||
		globalIndexes: globalIndexes,
 | 
			
		||||
		bytecode:      bytecode,
 | 
			
		||||
		globals:       globals,
 | 
			
		||||
		maxAllocs:     s.maxAllocs,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -141,39 +159,18 @@ func (s *Script) RunContext(ctx context.Context) (compiled *Compiled, err error)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Script) prepCompile() (symbolTable *compiler.SymbolTable, builtinModules map[string]bool, globals []*objects.Object, err error) {
 | 
			
		||||
func (s *Script) prepCompile() (symbolTable *compiler.SymbolTable, globals []objects.Object, err error) {
 | 
			
		||||
	var names []string
 | 
			
		||||
	for name := range s.variables {
 | 
			
		||||
		names = append(names, name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	symbolTable = compiler.NewSymbolTable()
 | 
			
		||||
 | 
			
		||||
	if s.builtinFuncs == nil {
 | 
			
		||||
		s.builtinFuncs = make([]objects.Object, len(objects.Builtins))
 | 
			
		||||
		for idx, fn := range objects.Builtins {
 | 
			
		||||
			s.builtinFuncs[idx] = &objects.BuiltinFunction{
 | 
			
		||||
				Name:  fn.Name,
 | 
			
		||||
				Value: fn.Value,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	for idx, fn := range objects.Builtins {
 | 
			
		||||
		symbolTable.DefineBuiltin(idx, fn.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if s.builtinModules == nil {
 | 
			
		||||
		s.builtinModules = make(map[string]*objects.Object)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for idx, fn := range s.builtinFuncs {
 | 
			
		||||
		f := fn.(*objects.BuiltinFunction)
 | 
			
		||||
		symbolTable.DefineBuiltin(idx, f.Name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	builtinModules = make(map[string]bool)
 | 
			
		||||
	for name := range s.builtinModules {
 | 
			
		||||
		builtinModules[name] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	globals = make([]*objects.Object, runtime.GlobalsSize, runtime.GlobalsSize)
 | 
			
		||||
	globals = make([]objects.Object, runtime.GlobalsSize)
 | 
			
		||||
 | 
			
		||||
	for idx, name := range names {
 | 
			
		||||
		symbol := symbolTable.Define(name)
 | 
			
		||||
@@ -195,7 +192,3 @@ func (s *Script) copyVariables() map[string]*Variable {
 | 
			
		||||
 | 
			
		||||
	return vars
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func objectPtr(o objects.Object) *objects.Object {
 | 
			
		||||
	return &o
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								vendor/github.com/d5/tengo/script/variable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/d5/tengo/script/variable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -9,7 +9,7 @@ import (
 | 
			
		||||
// Variable is a user-defined variable for the script.
 | 
			
		||||
type Variable struct {
 | 
			
		||||
	name  string
 | 
			
		||||
	value *objects.Object
 | 
			
		||||
	value objects.Object
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewVariable creates a Variable.
 | 
			
		||||
@@ -21,7 +21,7 @@ func NewVariable(name string, value interface{}) (*Variable, error) {
 | 
			
		||||
 | 
			
		||||
	return &Variable{
 | 
			
		||||
		name:  name,
 | 
			
		||||
		value: &obj,
 | 
			
		||||
		value: obj,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -32,18 +32,18 @@ func (v *Variable) Name() string {
 | 
			
		||||
 | 
			
		||||
// Value returns an empty interface of the variable value.
 | 
			
		||||
func (v *Variable) Value() interface{} {
 | 
			
		||||
	return objectToInterface(*v.value)
 | 
			
		||||
	return objects.ToInterface(v.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ValueType returns the name of the value type.
 | 
			
		||||
func (v *Variable) ValueType() string {
 | 
			
		||||
	return (*v.value).TypeName()
 | 
			
		||||
	return v.value.TypeName()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int returns int value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to int.
 | 
			
		||||
func (v *Variable) Int() int {
 | 
			
		||||
	c, _ := objects.ToInt(*v.value)
 | 
			
		||||
	c, _ := objects.ToInt(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -51,7 +51,7 @@ func (v *Variable) Int() int {
 | 
			
		||||
// Int64 returns int64 value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to int64.
 | 
			
		||||
func (v *Variable) Int64() int64 {
 | 
			
		||||
	c, _ := objects.ToInt64(*v.value)
 | 
			
		||||
	c, _ := objects.ToInt64(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -59,7 +59,7 @@ func (v *Variable) Int64() int64 {
 | 
			
		||||
// Float returns float64 value of the variable value.
 | 
			
		||||
// It returns 0.0 if the value is not convertible to float64.
 | 
			
		||||
func (v *Variable) Float() float64 {
 | 
			
		||||
	c, _ := objects.ToFloat64(*v.value)
 | 
			
		||||
	c, _ := objects.ToFloat64(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -67,7 +67,7 @@ func (v *Variable) Float() float64 {
 | 
			
		||||
// Char returns rune value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to rune.
 | 
			
		||||
func (v *Variable) Char() rune {
 | 
			
		||||
	c, _ := objects.ToRune(*v.value)
 | 
			
		||||
	c, _ := objects.ToRune(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -75,7 +75,7 @@ func (v *Variable) Char() rune {
 | 
			
		||||
// Bool returns bool value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to bool.
 | 
			
		||||
func (v *Variable) Bool() bool {
 | 
			
		||||
	c, _ := objects.ToBool(*v.value)
 | 
			
		||||
	c, _ := objects.ToBool(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -83,11 +83,11 @@ func (v *Variable) Bool() bool {
 | 
			
		||||
// Array returns []interface value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to []interface.
 | 
			
		||||
func (v *Variable) Array() []interface{} {
 | 
			
		||||
	switch val := (*v.value).(type) {
 | 
			
		||||
	switch val := v.value.(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		var arr []interface{}
 | 
			
		||||
		for _, e := range val.Value {
 | 
			
		||||
			arr = append(arr, objectToInterface(e))
 | 
			
		||||
			arr = append(arr, objects.ToInterface(e))
 | 
			
		||||
		}
 | 
			
		||||
		return arr
 | 
			
		||||
	}
 | 
			
		||||
@@ -98,11 +98,11 @@ func (v *Variable) Array() []interface{} {
 | 
			
		||||
// Map returns map[string]interface{} value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to map[string]interface{}.
 | 
			
		||||
func (v *Variable) Map() map[string]interface{} {
 | 
			
		||||
	switch val := (*v.value).(type) {
 | 
			
		||||
	switch val := v.value.(type) {
 | 
			
		||||
	case *objects.Map:
 | 
			
		||||
		kv := make(map[string]interface{})
 | 
			
		||||
		for mk, mv := range val.Value {
 | 
			
		||||
			kv[mk] = objectToInterface(mv)
 | 
			
		||||
			kv[mk] = objects.ToInterface(mv)
 | 
			
		||||
		}
 | 
			
		||||
		return kv
 | 
			
		||||
	}
 | 
			
		||||
@@ -113,7 +113,7 @@ func (v *Variable) Map() map[string]interface{} {
 | 
			
		||||
// String returns string value of the variable value.
 | 
			
		||||
// It returns 0 if the value is not convertible to string.
 | 
			
		||||
func (v *Variable) String() string {
 | 
			
		||||
	c, _ := objects.ToString(*v.value)
 | 
			
		||||
	c, _ := objects.ToString(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -121,7 +121,7 @@ func (v *Variable) String() string {
 | 
			
		||||
// Bytes returns a byte slice of the variable value.
 | 
			
		||||
// It returns nil if the value is not convertible to byte slice.
 | 
			
		||||
func (v *Variable) Bytes() []byte {
 | 
			
		||||
	c, _ := objects.ToByteSlice(*v.value)
 | 
			
		||||
	c, _ := objects.ToByteSlice(v.value)
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
@@ -129,7 +129,7 @@ func (v *Variable) Bytes() []byte {
 | 
			
		||||
// Error returns an error if the underlying value is error object.
 | 
			
		||||
// If not, this returns nil.
 | 
			
		||||
func (v *Variable) Error() error {
 | 
			
		||||
	err, ok := (*v.value).(*objects.Error)
 | 
			
		||||
	err, ok := v.value.(*objects.Error)
 | 
			
		||||
	if ok {
 | 
			
		||||
		return errors.New(err.String())
 | 
			
		||||
	}
 | 
			
		||||
@@ -140,10 +140,10 @@ func (v *Variable) Error() error {
 | 
			
		||||
// Object returns an underlying Object of the variable value.
 | 
			
		||||
// Note that returned Object is a copy of an actual Object used in the script.
 | 
			
		||||
func (v *Variable) Object() objects.Object {
 | 
			
		||||
	return *v.value
 | 
			
		||||
	return v.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsUndefined returns true if the underlying value is undefined.
 | 
			
		||||
func (v *Variable) IsUndefined() bool {
 | 
			
		||||
	return *v.value == objects.UndefinedValue
 | 
			
		||||
	return v.value == objects.UndefinedValue
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/d5/tengo/stdlib/builtin_modules.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/d5/tengo/stdlib/builtin_modules.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/objects"
 | 
			
		||||
 | 
			
		||||
// BuiltinModules are builtin type standard library modules.
 | 
			
		||||
var BuiltinModules = map[string]map[string]objects.Object{
 | 
			
		||||
	"math":  mathModule,
 | 
			
		||||
	"os":    osModule,
 | 
			
		||||
	"text":  textModule,
 | 
			
		||||
	"times": timesModule,
 | 
			
		||||
	"rand":  randModule,
 | 
			
		||||
	"fmt":   fmtModule,
 | 
			
		||||
	"json":  jsonModule,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/d5/tengo/stdlib/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/d5/tengo/stdlib/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/objects"
 | 
			
		||||
 | 
			
		||||
func wrapError(err error) objects.Object {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return objects.TrueValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.Error{Value: &objects.String{Value: err.Error()}}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										116
									
								
								vendor/github.com/d5/tengo/stdlib/fmt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								vendor/github.com/d5/tengo/stdlib/fmt.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var fmtModule = map[string]objects.Object{
 | 
			
		||||
	"print":   &objects.UserFunction{Name: "print", Value: fmtPrint},
 | 
			
		||||
	"printf":  &objects.UserFunction{Name: "printf", Value: fmtPrintf},
 | 
			
		||||
	"println": &objects.UserFunction{Name: "println", Value: fmtPrintln},
 | 
			
		||||
	"sprintf": &objects.UserFunction{Name: "sprintf", Value: fmtSprintf},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fmtPrint(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	printArgs, err := getPrintArgs(args...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, _ = fmt.Print(printArgs...)
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fmtPrintf(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	numArgs := len(args)
 | 
			
		||||
	if numArgs == 0 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	format, ok := args[0].(*objects.String)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "format",
 | 
			
		||||
			Expected: "string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if numArgs == 1 {
 | 
			
		||||
		fmt.Print(format)
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	formatArgs := make([]interface{}, numArgs-1, numArgs-1)
 | 
			
		||||
	for idx, arg := range args[1:] {
 | 
			
		||||
		formatArgs[idx] = objects.ToInterface(arg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Printf(format.Value, formatArgs...)
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fmtPrintln(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	printArgs, err := getPrintArgs(args...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printArgs = append(printArgs, "\n")
 | 
			
		||||
	_, _ = fmt.Print(printArgs...)
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fmtSprintf(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	numArgs := len(args)
 | 
			
		||||
	if numArgs == 0 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	format, ok := args[0].(*objects.String)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "format",
 | 
			
		||||
			Expected: "string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if numArgs == 1 {
 | 
			
		||||
		return format, nil // okay to return 'format' directly as String is immutable
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	formatArgs := make([]interface{}, numArgs-1, numArgs-1)
 | 
			
		||||
	for idx, arg := range args[1:] {
 | 
			
		||||
		formatArgs[idx] = objects.ToInterface(arg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s := fmt.Sprintf(format.Value, formatArgs...)
 | 
			
		||||
 | 
			
		||||
	if len(s) > tengo.MaxStringLen {
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.String{Value: s}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPrintArgs(args ...objects.Object) ([]interface{}, error) {
 | 
			
		||||
	var printArgs []interface{}
 | 
			
		||||
	l := 0
 | 
			
		||||
	for _, arg := range args {
 | 
			
		||||
		s, _ := objects.ToString(arg)
 | 
			
		||||
		slen := len(s)
 | 
			
		||||
		if l+slen > tengo.MaxStringLen { // make sure length does not exceed the limit
 | 
			
		||||
			return nil, objects.ErrStringLimit
 | 
			
		||||
		}
 | 
			
		||||
		l += slen
 | 
			
		||||
 | 
			
		||||
		printArgs = append(printArgs, s)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return printArgs, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1125
									
								
								vendor/github.com/d5/tengo/stdlib/func_typedefs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1125
									
								
								vendor/github.com/d5/tengo/stdlib/func_typedefs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										53
									
								
								vendor/github.com/d5/tengo/stdlib/gensrcmods.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/d5/tengo/stdlib/gensrcmods.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
// +build ignore
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tengoModFileRE = regexp.MustCompile(`^srcmod_(\w+).tengo$`)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	modules := make(map[string]string)
 | 
			
		||||
 | 
			
		||||
	// enumerate all Tengo module files
 | 
			
		||||
	files, err := ioutil.ReadDir(".")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	for _, file := range files {
 | 
			
		||||
		m := tengoModFileRE.FindStringSubmatch(file.Name())
 | 
			
		||||
		if m != nil {
 | 
			
		||||
			modName := m[1]
 | 
			
		||||
 | 
			
		||||
			src, err := ioutil.ReadFile(file.Name())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Fatalf("file '%s' read error: %s", file.Name(), err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			modules[modName] = string(src)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var out bytes.Buffer
 | 
			
		||||
	out.WriteString(`// Code generated using gensrcmods.go; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
// SourceModules are source type standard library modules.
 | 
			
		||||
var SourceModules = map[string]string{` + "\n")
 | 
			
		||||
	for modName, modSrc := range modules {
 | 
			
		||||
		out.WriteString("\t\"" + modName + "\": " + strconv.Quote(modSrc) + ",\n")
 | 
			
		||||
	}
 | 
			
		||||
	out.WriteString("}\n")
 | 
			
		||||
 | 
			
		||||
	const target = "source_modules.go"
 | 
			
		||||
	if err := ioutil.WriteFile(target, out.Bytes(), 0644); err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										126
									
								
								vendor/github.com/d5/tengo/stdlib/json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/d5/tengo/stdlib/json.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	gojson "encoding/json"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
	"github.com/d5/tengo/stdlib/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var jsonModule = map[string]objects.Object{
 | 
			
		||||
	"decode":      &objects.UserFunction{Name: "decode", Value: jsonDecode},
 | 
			
		||||
	"encode":      &objects.UserFunction{Name: "encode", Value: jsonEncode},
 | 
			
		||||
	"indent":      &objects.UserFunction{Name: "encode", Value: jsonIndent},
 | 
			
		||||
	"html_escape": &objects.UserFunction{Name: "html_escape", Value: jsonHTMLEscape},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func jsonDecode(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch o := args[0].(type) {
 | 
			
		||||
	case *objects.Bytes:
 | 
			
		||||
		v, err := json.Decode(o.Value)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
		return v, nil
 | 
			
		||||
	case *objects.String:
 | 
			
		||||
		v, err := json.Decode([]byte(o.Value))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
		return v, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "bytes/string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func jsonEncode(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b, err := json.Encode(args[0])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.Bytes{Value: b}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func jsonIndent(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 3 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prefix, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "prefix",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	indent, ok := objects.ToString(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "indent",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch o := args[0].(type) {
 | 
			
		||||
	case *objects.Bytes:
 | 
			
		||||
		var dst bytes.Buffer
 | 
			
		||||
		err := gojson.Indent(&dst, o.Value, prefix, indent)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
		return &objects.Bytes{Value: dst.Bytes()}, nil
 | 
			
		||||
	case *objects.String:
 | 
			
		||||
		var dst bytes.Buffer
 | 
			
		||||
		err := gojson.Indent(&dst, []byte(o.Value), prefix, indent)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return &objects.Error{Value: &objects.String{Value: err.Error()}}, nil
 | 
			
		||||
		}
 | 
			
		||||
		return &objects.Bytes{Value: dst.Bytes()}, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "bytes/string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func jsonHTMLEscape(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch o := args[0].(type) {
 | 
			
		||||
	case *objects.Bytes:
 | 
			
		||||
		var dst bytes.Buffer
 | 
			
		||||
		gojson.HTMLEscape(&dst, o.Value)
 | 
			
		||||
		return &objects.Bytes{Value: dst.Bytes()}, nil
 | 
			
		||||
	case *objects.String:
 | 
			
		||||
		var dst bytes.Buffer
 | 
			
		||||
		gojson.HTMLEscape(&dst, []byte(o.Value))
 | 
			
		||||
		return &objects.Bytes{Value: dst.Bytes()}, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "bytes/string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										374
									
								
								vendor/github.com/d5/tengo/stdlib/json/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								vendor/github.com/d5/tengo/stdlib/json/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,374 @@
 | 
			
		||||
// A modified version of Go's JSON implementation.
 | 
			
		||||
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"unicode"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Decode parses the JSON-encoded data and returns the result object.
 | 
			
		||||
func Decode(data []byte) (objects.Object, error) {
 | 
			
		||||
	var d decodeState
 | 
			
		||||
	err := checkValid(data, &d.scan)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d.init(data)
 | 
			
		||||
	d.scan.reset()
 | 
			
		||||
	d.scanWhile(scanSkipSpace)
 | 
			
		||||
 | 
			
		||||
	return d.value()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decodeState represents the state while decoding a JSON value.
 | 
			
		||||
type decodeState struct {
 | 
			
		||||
	data   []byte
 | 
			
		||||
	off    int // next read offset in data
 | 
			
		||||
	opcode int // last read result
 | 
			
		||||
	scan   scanner
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readIndex returns the position of the last byte read.
 | 
			
		||||
func (d *decodeState) readIndex() int {
 | 
			
		||||
	return d.off - 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
 | 
			
		||||
 | 
			
		||||
func (d *decodeState) init(data []byte) *decodeState {
 | 
			
		||||
	d.data = data
 | 
			
		||||
	d.off = 0
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// scanNext processes the byte at d.data[d.off].
 | 
			
		||||
func (d *decodeState) scanNext() {
 | 
			
		||||
	if d.off < len(d.data) {
 | 
			
		||||
		d.opcode = d.scan.step(&d.scan, d.data[d.off])
 | 
			
		||||
		d.off++
 | 
			
		||||
	} else {
 | 
			
		||||
		d.opcode = d.scan.eof()
 | 
			
		||||
		d.off = len(d.data) + 1 // mark processed EOF with len+1
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// scanWhile processes bytes in d.data[d.off:] until it
 | 
			
		||||
// receives a scan code not equal to op.
 | 
			
		||||
func (d *decodeState) scanWhile(op int) {
 | 
			
		||||
	s, data, i := &d.scan, d.data, d.off
 | 
			
		||||
	for i < len(data) {
 | 
			
		||||
		newOp := s.step(s, data[i])
 | 
			
		||||
		i++
 | 
			
		||||
		if newOp != op {
 | 
			
		||||
			d.opcode = newOp
 | 
			
		||||
			d.off = i
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d.off = len(data) + 1 // mark processed EOF with len+1
 | 
			
		||||
	d.opcode = d.scan.eof()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decodeState) value() (objects.Object, error) {
 | 
			
		||||
	switch d.opcode {
 | 
			
		||||
	default:
 | 
			
		||||
		panic(phasePanicMsg)
 | 
			
		||||
 | 
			
		||||
	case scanBeginArray:
 | 
			
		||||
		o, err := d.array()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		d.scanNext()
 | 
			
		||||
 | 
			
		||||
		return o, nil
 | 
			
		||||
 | 
			
		||||
	case scanBeginObject:
 | 
			
		||||
		o, err := d.object()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		d.scanNext()
 | 
			
		||||
 | 
			
		||||
		return o, nil
 | 
			
		||||
 | 
			
		||||
	case scanBeginLiteral:
 | 
			
		||||
		return d.literal()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decodeState) array() (objects.Object, error) {
 | 
			
		||||
	var arr []objects.Object
 | 
			
		||||
	for {
 | 
			
		||||
		// Look ahead for ] - can only happen on first iteration.
 | 
			
		||||
		d.scanWhile(scanSkipSpace)
 | 
			
		||||
		if d.opcode == scanEndArray {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		o, err := d.value()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		arr = append(arr, o)
 | 
			
		||||
 | 
			
		||||
		// Next token must be , or ].
 | 
			
		||||
		if d.opcode == scanSkipSpace {
 | 
			
		||||
			d.scanWhile(scanSkipSpace)
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode == scanEndArray {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode != scanArrayValue {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.Array{Value: arr}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decodeState) object() (objects.Object, error) {
 | 
			
		||||
	m := make(map[string]objects.Object)
 | 
			
		||||
	for {
 | 
			
		||||
		// Read opening " of string key or closing }.
 | 
			
		||||
		d.scanWhile(scanSkipSpace)
 | 
			
		||||
		if d.opcode == scanEndObject {
 | 
			
		||||
			// closing } - can only happen on first iteration.
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode != scanBeginLiteral {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Read string key.
 | 
			
		||||
		start := d.readIndex()
 | 
			
		||||
		d.scanWhile(scanContinue)
 | 
			
		||||
		item := d.data[start:d.readIndex()]
 | 
			
		||||
		key, ok := unquote(item)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Read : before value.
 | 
			
		||||
		if d.opcode == scanSkipSpace {
 | 
			
		||||
			d.scanWhile(scanSkipSpace)
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode != scanObjectKey {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
		d.scanWhile(scanSkipSpace)
 | 
			
		||||
 | 
			
		||||
		// Read value.
 | 
			
		||||
		o, err := d.value()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m[key] = o
 | 
			
		||||
 | 
			
		||||
		// Next token must be , or }.
 | 
			
		||||
		if d.opcode == scanSkipSpace {
 | 
			
		||||
			d.scanWhile(scanSkipSpace)
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode == scanEndObject {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if d.opcode != scanObjectValue {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.Map{Value: m}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *decodeState) literal() (objects.Object, error) {
 | 
			
		||||
	// All bytes inside literal return scanContinue op code.
 | 
			
		||||
	start := d.readIndex()
 | 
			
		||||
	d.scanWhile(scanContinue)
 | 
			
		||||
 | 
			
		||||
	item := d.data[start:d.readIndex()]
 | 
			
		||||
 | 
			
		||||
	switch c := item[0]; c {
 | 
			
		||||
	case 'n': // null
 | 
			
		||||
		return objects.UndefinedValue, nil
 | 
			
		||||
 | 
			
		||||
	case 't', 'f': // true, false
 | 
			
		||||
		if c == 't' {
 | 
			
		||||
			return objects.TrueValue, nil
 | 
			
		||||
		}
 | 
			
		||||
		return objects.FalseValue, nil
 | 
			
		||||
 | 
			
		||||
	case '"': // string
 | 
			
		||||
		s, ok := unquote(item)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
		return &objects.String{Value: s}, nil
 | 
			
		||||
 | 
			
		||||
	default: // number
 | 
			
		||||
		if c != '-' && (c < '0' || c > '9') {
 | 
			
		||||
			panic(phasePanicMsg)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		n, _ := strconv.ParseFloat(string(item), 10)
 | 
			
		||||
		return &objects.Float{Value: n}, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
 | 
			
		||||
// or it returns -1.
 | 
			
		||||
func getu4(s []byte) rune {
 | 
			
		||||
	if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
 | 
			
		||||
		return -1
 | 
			
		||||
	}
 | 
			
		||||
	var r rune
 | 
			
		||||
	for _, c := range s[2:6] {
 | 
			
		||||
		switch {
 | 
			
		||||
		case '0' <= c && c <= '9':
 | 
			
		||||
			c = c - '0'
 | 
			
		||||
		case 'a' <= c && c <= 'f':
 | 
			
		||||
			c = c - 'a' + 10
 | 
			
		||||
		case 'A' <= c && c <= 'F':
 | 
			
		||||
			c = c - 'A' + 10
 | 
			
		||||
		default:
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		r = r*16 + rune(c)
 | 
			
		||||
	}
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// unquote converts a quoted JSON string literal s into an actual string t.
 | 
			
		||||
// The rules are different than for Go, so cannot use strconv.Unquote.
 | 
			
		||||
func unquote(s []byte) (t string, ok bool) {
 | 
			
		||||
	s, ok = unquoteBytes(s)
 | 
			
		||||
	t = string(s)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func unquoteBytes(s []byte) (t []byte, ok bool) {
 | 
			
		||||
	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	s = s[1 : len(s)-1]
 | 
			
		||||
 | 
			
		||||
	// Check for unusual characters. If there are none,
 | 
			
		||||
	// then no unquoting is needed, so return a slice of the
 | 
			
		||||
	// original bytes.
 | 
			
		||||
	r := 0
 | 
			
		||||
	for r < len(s) {
 | 
			
		||||
		c := s[r]
 | 
			
		||||
		if c == '\\' || c == '"' || c < ' ' {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if c < utf8.RuneSelf {
 | 
			
		||||
			r++
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		rr, size := utf8.DecodeRune(s[r:])
 | 
			
		||||
		if rr == utf8.RuneError && size == 1 {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		r += size
 | 
			
		||||
	}
 | 
			
		||||
	if r == len(s) {
 | 
			
		||||
		return s, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b := make([]byte, len(s)+2*utf8.UTFMax)
 | 
			
		||||
	w := copy(b, s[0:r])
 | 
			
		||||
	for r < len(s) {
 | 
			
		||||
		// Out of room? Can only happen if s is full of
 | 
			
		||||
		// malformed UTF-8 and we're replacing each
 | 
			
		||||
		// byte with RuneError.
 | 
			
		||||
		if w >= len(b)-2*utf8.UTFMax {
 | 
			
		||||
			nb := make([]byte, (len(b)+utf8.UTFMax)*2)
 | 
			
		||||
			copy(nb, b[0:w])
 | 
			
		||||
			b = nb
 | 
			
		||||
		}
 | 
			
		||||
		switch c := s[r]; {
 | 
			
		||||
		case c == '\\':
 | 
			
		||||
			r++
 | 
			
		||||
			if r >= len(s) {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			switch s[r] {
 | 
			
		||||
			default:
 | 
			
		||||
				return
 | 
			
		||||
			case '"', '\\', '/', '\'':
 | 
			
		||||
				b[w] = s[r]
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 'b':
 | 
			
		||||
				b[w] = '\b'
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 'f':
 | 
			
		||||
				b[w] = '\f'
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 'n':
 | 
			
		||||
				b[w] = '\n'
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 'r':
 | 
			
		||||
				b[w] = '\r'
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 't':
 | 
			
		||||
				b[w] = '\t'
 | 
			
		||||
				r++
 | 
			
		||||
				w++
 | 
			
		||||
			case 'u':
 | 
			
		||||
				r--
 | 
			
		||||
				rr := getu4(s[r:])
 | 
			
		||||
				if rr < 0 {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				r += 6
 | 
			
		||||
				if utf16.IsSurrogate(rr) {
 | 
			
		||||
					rr1 := getu4(s[r:])
 | 
			
		||||
					if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
 | 
			
		||||
						// A valid pair; consume.
 | 
			
		||||
						r += 6
 | 
			
		||||
						w += utf8.EncodeRune(b[w:], dec)
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
					// Invalid surrogate; fall back to replacement rune.
 | 
			
		||||
					rr = unicode.ReplacementChar
 | 
			
		||||
				}
 | 
			
		||||
				w += utf8.EncodeRune(b[w:], rr)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		// Quote, control characters are invalid.
 | 
			
		||||
		case c == '"', c < ' ':
 | 
			
		||||
			return
 | 
			
		||||
 | 
			
		||||
		// ASCII
 | 
			
		||||
		case c < utf8.RuneSelf:
 | 
			
		||||
			b[w] = c
 | 
			
		||||
			r++
 | 
			
		||||
			w++
 | 
			
		||||
 | 
			
		||||
		// Coerce to well-formed UTF-8.
 | 
			
		||||
		default:
 | 
			
		||||
			rr, size := utf8.DecodeRune(s[r:])
 | 
			
		||||
			r += size
 | 
			
		||||
			w += utf8.EncodeRune(b[w:], rr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return b[0:w], true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										147
									
								
								vendor/github.com/d5/tengo/stdlib/json/encode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								vendor/github.com/d5/tengo/stdlib/json/encode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
			
		||||
// A modified version of Go's JSON implementation.
 | 
			
		||||
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Encode returns the JSON encoding of the object.
 | 
			
		||||
func Encode(o objects.Object) ([]byte, error) {
 | 
			
		||||
	var b []byte
 | 
			
		||||
 | 
			
		||||
	switch o := o.(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		b = append(b, '[')
 | 
			
		||||
		len1 := len(o.Value) - 1
 | 
			
		||||
		for idx, elem := range o.Value {
 | 
			
		||||
			eb, err := Encode(elem)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = append(b, eb...)
 | 
			
		||||
			if idx < len1 {
 | 
			
		||||
				b = append(b, ',')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, ']')
 | 
			
		||||
	case *objects.ImmutableArray:
 | 
			
		||||
		b = append(b, '[')
 | 
			
		||||
		len1 := len(o.Value) - 1
 | 
			
		||||
		for idx, elem := range o.Value {
 | 
			
		||||
			eb, err := Encode(elem)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = append(b, eb...)
 | 
			
		||||
			if idx < len1 {
 | 
			
		||||
				b = append(b, ',')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, ']')
 | 
			
		||||
	case *objects.Map:
 | 
			
		||||
		b = append(b, '{')
 | 
			
		||||
		len1 := len(o.Value) - 1
 | 
			
		||||
		idx := 0
 | 
			
		||||
		for key, value := range o.Value {
 | 
			
		||||
			b = strconv.AppendQuote(b, key)
 | 
			
		||||
			b = append(b, ':')
 | 
			
		||||
			eb, err := Encode(value)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = append(b, eb...)
 | 
			
		||||
			if idx < len1 {
 | 
			
		||||
				b = append(b, ',')
 | 
			
		||||
			}
 | 
			
		||||
			idx++
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, '}')
 | 
			
		||||
	case *objects.ImmutableMap:
 | 
			
		||||
		b = append(b, '{')
 | 
			
		||||
		len1 := len(o.Value) - 1
 | 
			
		||||
		idx := 0
 | 
			
		||||
		for key, value := range o.Value {
 | 
			
		||||
			b = strconv.AppendQuote(b, key)
 | 
			
		||||
			b = append(b, ':')
 | 
			
		||||
			eb, err := Encode(value)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			b = append(b, eb...)
 | 
			
		||||
			if idx < len1 {
 | 
			
		||||
				b = append(b, ',')
 | 
			
		||||
			}
 | 
			
		||||
			idx++
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, '}')
 | 
			
		||||
	case *objects.Bool:
 | 
			
		||||
		if o.IsFalsy() {
 | 
			
		||||
			b = strconv.AppendBool(b, false)
 | 
			
		||||
		} else {
 | 
			
		||||
			b = strconv.AppendBool(b, true)
 | 
			
		||||
		}
 | 
			
		||||
	case *objects.Bytes:
 | 
			
		||||
		b = append(b, '"')
 | 
			
		||||
		encodedLen := base64.StdEncoding.EncodedLen(len(o.Value))
 | 
			
		||||
		dst := make([]byte, encodedLen)
 | 
			
		||||
		base64.StdEncoding.Encode(dst, o.Value)
 | 
			
		||||
		b = append(b, dst...)
 | 
			
		||||
		b = append(b, '"')
 | 
			
		||||
	case *objects.Char:
 | 
			
		||||
		b = strconv.AppendInt(b, int64(o.Value), 10)
 | 
			
		||||
	case *objects.Float:
 | 
			
		||||
		var y []byte
 | 
			
		||||
 | 
			
		||||
		f := o.Value
 | 
			
		||||
		if math.IsInf(f, 0) || math.IsNaN(f) {
 | 
			
		||||
			return nil, errors.New("unsupported float value")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Convert as if by ES6 number to string conversion.
 | 
			
		||||
		// This matches most other JSON generators.
 | 
			
		||||
		abs := math.Abs(f)
 | 
			
		||||
		fmt := byte('f')
 | 
			
		||||
		if abs != 0 {
 | 
			
		||||
			if abs < 1e-6 || abs >= 1e21 {
 | 
			
		||||
				fmt = 'e'
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		y = strconv.AppendFloat(y, f, fmt, -1, 64)
 | 
			
		||||
		if fmt == 'e' {
 | 
			
		||||
			// clean up e-09 to e-9
 | 
			
		||||
			n := len(y)
 | 
			
		||||
			if n >= 4 && y[n-4] == 'e' && y[n-3] == '-' && y[n-2] == '0' {
 | 
			
		||||
				y[n-2] = y[n-1]
 | 
			
		||||
				y = y[:n-1]
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		b = append(b, y...)
 | 
			
		||||
	case *objects.Int:
 | 
			
		||||
		b = strconv.AppendInt(b, o.Value, 10)
 | 
			
		||||
	case *objects.String:
 | 
			
		||||
		b = strconv.AppendQuote(b, o.Value)
 | 
			
		||||
	case *objects.Time:
 | 
			
		||||
		y, err := o.Value.MarshalJSON()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		b = append(b, y...)
 | 
			
		||||
	case *objects.Undefined:
 | 
			
		||||
		b = append(b, "null"...)
 | 
			
		||||
	default:
 | 
			
		||||
		// unknown type: ignore
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										559
									
								
								vendor/github.com/d5/tengo/stdlib/json/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										559
									
								
								vendor/github.com/d5/tengo/stdlib/json/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,559 @@
 | 
			
		||||
// A modified version of Go's JSON implementation.
 | 
			
		||||
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package json
 | 
			
		||||
 | 
			
		||||
import "strconv"
 | 
			
		||||
 | 
			
		||||
func checkValid(data []byte, scan *scanner) error {
 | 
			
		||||
	scan.reset()
 | 
			
		||||
	for _, c := range data {
 | 
			
		||||
		scan.bytes++
 | 
			
		||||
		if scan.step(scan, c) == scanError {
 | 
			
		||||
			return scan.err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if scan.eof() == scanError {
 | 
			
		||||
		return scan.err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A SyntaxError is a description of a JSON syntax error.
 | 
			
		||||
type SyntaxError struct {
 | 
			
		||||
	msg    string // description of error
 | 
			
		||||
	Offset int64  // error occurred after reading Offset bytes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SyntaxError) Error() string { return e.msg }
 | 
			
		||||
 | 
			
		||||
// A scanner is a JSON scanning state machine.
 | 
			
		||||
// Callers call scan.reset() and then pass bytes in one at a time
 | 
			
		||||
// by calling scan.step(&scan, c) for each byte.
 | 
			
		||||
// The return value, referred to as an opcode, tells the
 | 
			
		||||
// caller about significant parsing events like beginning
 | 
			
		||||
// and ending literals, objects, and arrays, so that the
 | 
			
		||||
// caller can follow along if it wishes.
 | 
			
		||||
// The return value scanEnd indicates that a single top-level
 | 
			
		||||
// JSON value has been completed, *before* the byte that
 | 
			
		||||
// just got passed in.  (The indication must be delayed in order
 | 
			
		||||
// to recognize the end of numbers: is 123 a whole value or
 | 
			
		||||
// the beginning of 12345e+6?).
 | 
			
		||||
type scanner struct {
 | 
			
		||||
	// The step is a func to be called to execute the next transition.
 | 
			
		||||
	// Also tried using an integer constant and a single func
 | 
			
		||||
	// with a switch, but using the func directly was 10% faster
 | 
			
		||||
	// on a 64-bit Mac Mini, and it's nicer to read.
 | 
			
		||||
	step func(*scanner, byte) int
 | 
			
		||||
 | 
			
		||||
	// Reached end of top-level value.
 | 
			
		||||
	endTop bool
 | 
			
		||||
 | 
			
		||||
	// Stack of what we're in the middle of - array values, object keys, object values.
 | 
			
		||||
	parseState []int
 | 
			
		||||
 | 
			
		||||
	// Error that happened, if any.
 | 
			
		||||
	err error
 | 
			
		||||
 | 
			
		||||
	// total bytes consumed, updated by decoder.Decode
 | 
			
		||||
	bytes int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// These values are returned by the state transition functions
 | 
			
		||||
// assigned to scanner.state and the method scanner.eof.
 | 
			
		||||
// They give details about the current state of the scan that
 | 
			
		||||
// callers might be interested to know about.
 | 
			
		||||
// It is okay to ignore the return value of any particular
 | 
			
		||||
// call to scanner.state: if one call returns scanError,
 | 
			
		||||
// every subsequent call will return scanError too.
 | 
			
		||||
const (
 | 
			
		||||
	// Continue.
 | 
			
		||||
	scanContinue     = iota // uninteresting byte
 | 
			
		||||
	scanBeginLiteral        // end implied by next result != scanContinue
 | 
			
		||||
	scanBeginObject         // begin object
 | 
			
		||||
	scanObjectKey           // just finished object key (string)
 | 
			
		||||
	scanObjectValue         // just finished non-last object value
 | 
			
		||||
	scanEndObject           // end object (implies scanObjectValue if possible)
 | 
			
		||||
	scanBeginArray          // begin array
 | 
			
		||||
	scanArrayValue          // just finished array value
 | 
			
		||||
	scanEndArray            // end array (implies scanArrayValue if possible)
 | 
			
		||||
	scanSkipSpace           // space byte; can skip; known to be last "continue" result
 | 
			
		||||
 | 
			
		||||
	// Stop.
 | 
			
		||||
	scanEnd   // top-level value ended *before* this byte; known to be first "stop" result
 | 
			
		||||
	scanError // hit an error, scanner.err.
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// These values are stored in the parseState stack.
 | 
			
		||||
// They give the current state of a composite value
 | 
			
		||||
// being scanned. If the parser is inside a nested value
 | 
			
		||||
// the parseState describes the nested state, outermost at entry 0.
 | 
			
		||||
const (
 | 
			
		||||
	parseObjectKey   = iota // parsing object key (before colon)
 | 
			
		||||
	parseObjectValue        // parsing object value (after colon)
 | 
			
		||||
	parseArrayValue         // parsing array value
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// reset prepares the scanner for use.
 | 
			
		||||
// It must be called before calling s.step.
 | 
			
		||||
func (s *scanner) reset() {
 | 
			
		||||
	s.step = stateBeginValue
 | 
			
		||||
	s.parseState = s.parseState[0:0]
 | 
			
		||||
	s.err = nil
 | 
			
		||||
	s.endTop = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// eof tells the scanner that the end of input has been reached.
 | 
			
		||||
// It returns a scan status just as s.step does.
 | 
			
		||||
func (s *scanner) eof() int {
 | 
			
		||||
	if s.err != nil {
 | 
			
		||||
		return scanError
 | 
			
		||||
	}
 | 
			
		||||
	if s.endTop {
 | 
			
		||||
		return scanEnd
 | 
			
		||||
	}
 | 
			
		||||
	s.step(s, ' ')
 | 
			
		||||
	if s.endTop {
 | 
			
		||||
		return scanEnd
 | 
			
		||||
	}
 | 
			
		||||
	if s.err == nil {
 | 
			
		||||
		s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
 | 
			
		||||
	}
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pushParseState pushes a new parse state p onto the parse stack.
 | 
			
		||||
func (s *scanner) pushParseState(p int) {
 | 
			
		||||
	s.parseState = append(s.parseState, p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// popParseState pops a parse state (already obtained) off the stack
 | 
			
		||||
// and updates s.step accordingly.
 | 
			
		||||
func (s *scanner) popParseState() {
 | 
			
		||||
	n := len(s.parseState) - 1
 | 
			
		||||
	s.parseState = s.parseState[0:n]
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		s.step = stateEndTop
 | 
			
		||||
		s.endTop = true
 | 
			
		||||
	} else {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isSpace(c byte) bool {
 | 
			
		||||
	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginValueOrEmpty is the state after reading `[`.
 | 
			
		||||
func stateBeginValueOrEmpty(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == ']' {
 | 
			
		||||
		return stateEndValue(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	return stateBeginValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginValue is the state at the beginning of the input.
 | 
			
		||||
func stateBeginValue(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	switch c {
 | 
			
		||||
	case '{':
 | 
			
		||||
		s.step = stateBeginStringOrEmpty
 | 
			
		||||
		s.pushParseState(parseObjectKey)
 | 
			
		||||
		return scanBeginObject
 | 
			
		||||
	case '[':
 | 
			
		||||
		s.step = stateBeginValueOrEmpty
 | 
			
		||||
		s.pushParseState(parseArrayValue)
 | 
			
		||||
		return scanBeginArray
 | 
			
		||||
	case '"':
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case '-':
 | 
			
		||||
		s.step = stateNeg
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case '0': // beginning of 0.123
 | 
			
		||||
		s.step = state0
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 't': // beginning of true
 | 
			
		||||
		s.step = stateT
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 'f': // beginning of false
 | 
			
		||||
		s.step = stateF
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	case 'n': // beginning of null
 | 
			
		||||
		s.step = stateN
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	if '1' <= c && c <= '9' { // beginning of 1234.5
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "looking for beginning of value")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginStringOrEmpty is the state after reading `{`.
 | 
			
		||||
func stateBeginStringOrEmpty(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == '}' {
 | 
			
		||||
		n := len(s.parseState)
 | 
			
		||||
		s.parseState[n-1] = parseObjectValue
 | 
			
		||||
		return stateEndValue(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	return stateBeginString(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateBeginString is the state after reading `{"key": value,`.
 | 
			
		||||
func stateBeginString(s *scanner, c byte) int {
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanBeginLiteral
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "looking for beginning of object key string")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateEndValue is the state after completing a value,
 | 
			
		||||
// such as after reading `{}` or `true` or `["x"`.
 | 
			
		||||
func stateEndValue(s *scanner, c byte) int {
 | 
			
		||||
	n := len(s.parseState)
 | 
			
		||||
	if n == 0 {
 | 
			
		||||
		// Completed top-level before the current byte.
 | 
			
		||||
		s.step = stateEndTop
 | 
			
		||||
		s.endTop = true
 | 
			
		||||
		return stateEndTop(s, c)
 | 
			
		||||
	}
 | 
			
		||||
	if c <= ' ' && isSpace(c) {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanSkipSpace
 | 
			
		||||
	}
 | 
			
		||||
	ps := s.parseState[n-1]
 | 
			
		||||
	switch ps {
 | 
			
		||||
	case parseObjectKey:
 | 
			
		||||
		if c == ':' {
 | 
			
		||||
			s.parseState[n-1] = parseObjectValue
 | 
			
		||||
			s.step = stateBeginValue
 | 
			
		||||
			return scanObjectKey
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after object key")
 | 
			
		||||
	case parseObjectValue:
 | 
			
		||||
		if c == ',' {
 | 
			
		||||
			s.parseState[n-1] = parseObjectKey
 | 
			
		||||
			s.step = stateBeginString
 | 
			
		||||
			return scanObjectValue
 | 
			
		||||
		}
 | 
			
		||||
		if c == '}' {
 | 
			
		||||
			s.popParseState()
 | 
			
		||||
			return scanEndObject
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after object key:value pair")
 | 
			
		||||
	case parseArrayValue:
 | 
			
		||||
		if c == ',' {
 | 
			
		||||
			s.step = stateBeginValue
 | 
			
		||||
			return scanArrayValue
 | 
			
		||||
		}
 | 
			
		||||
		if c == ']' {
 | 
			
		||||
			s.popParseState()
 | 
			
		||||
			return scanEndArray
 | 
			
		||||
		}
 | 
			
		||||
		return s.error(c, "after array element")
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateEndTop is the state after finishing the top-level value,
 | 
			
		||||
// such as after reading `{}` or `[1,2,3]`.
 | 
			
		||||
// Only space characters should be seen now.
 | 
			
		||||
func stateEndTop(s *scanner, c byte) int {
 | 
			
		||||
	if !isSpace(c) {
 | 
			
		||||
		// Complain about non-space byte on next call.
 | 
			
		||||
		s.error(c, "after top-level value")
 | 
			
		||||
	}
 | 
			
		||||
	return scanEnd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInString is the state after reading `"`.
 | 
			
		||||
func stateInString(s *scanner, c byte) int {
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == '\\' {
 | 
			
		||||
		s.step = stateInStringEsc
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c < 0x20 {
 | 
			
		||||
		return s.error(c, "in string literal")
 | 
			
		||||
	}
 | 
			
		||||
	return scanContinue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEsc is the state after reading `"\` during a quoted string.
 | 
			
		||||
func stateInStringEsc(s *scanner, c byte) int {
 | 
			
		||||
	switch c {
 | 
			
		||||
	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	case 'u':
 | 
			
		||||
		s.step = stateInStringEscU
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in string escape code")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU is the state after reading `"\u` during a quoted string.
 | 
			
		||||
func stateInStringEscU(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
 | 
			
		||||
func stateInStringEscU1(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU12
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
 | 
			
		||||
func stateInStringEscU12(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInStringEscU123
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
 | 
			
		||||
func stateInStringEscU123(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 | 
			
		||||
		s.step = stateInString
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	// numbers
 | 
			
		||||
	return s.error(c, "in \\u hexadecimal character escape")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNeg is the state after reading `-` during a number.
 | 
			
		||||
func stateNeg(s *scanner, c byte) int {
 | 
			
		||||
	if c == '0' {
 | 
			
		||||
		s.step = state0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if '1' <= c && c <= '9' {
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state1 is the state after reading a non-zero integer during a number,
 | 
			
		||||
// such as after reading `1` or `100` but not `0`.
 | 
			
		||||
func state1(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = state1
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return state0(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state0 is the state after reading `0` during a number.
 | 
			
		||||
func state0(s *scanner, c byte) int {
 | 
			
		||||
	if c == '.' {
 | 
			
		||||
		s.step = stateDot
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == 'e' || c == 'E' {
 | 
			
		||||
		s.step = stateE
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateDot is the state after reading the integer and decimal point in a number,
 | 
			
		||||
// such as after reading `1.`.
 | 
			
		||||
func stateDot(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = stateDot0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "after decimal point in numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateDot0 is the state after reading the integer, decimal point, and subsequent
 | 
			
		||||
// digits of a number, such as after reading `3.14`.
 | 
			
		||||
func stateDot0(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	if c == 'e' || c == 'E' {
 | 
			
		||||
		s.step = stateE
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateE is the state after reading the mantissa and e in a number,
 | 
			
		||||
// such as after reading `314e` or `0.314e`.
 | 
			
		||||
func stateE(s *scanner, c byte) int {
 | 
			
		||||
	if c == '+' || c == '-' {
 | 
			
		||||
		s.step = stateESign
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateESign(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateESign is the state after reading the mantissa, e, and sign in a number,
 | 
			
		||||
// such as after reading `314e-` or `0.314e+`.
 | 
			
		||||
func stateESign(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		s.step = stateE0
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in exponent of numeric literal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateE0 is the state after reading the mantissa, e, optional sign,
 | 
			
		||||
// and at least one digit of the exponent in a number,
 | 
			
		||||
// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
 | 
			
		||||
func stateE0(s *scanner, c byte) int {
 | 
			
		||||
	if '0' <= c && c <= '9' {
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return stateEndValue(s, c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateT is the state after reading `t`.
 | 
			
		||||
func stateT(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'r' {
 | 
			
		||||
		s.step = stateTr
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'r')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateTr is the state after reading `tr`.
 | 
			
		||||
func stateTr(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'u' {
 | 
			
		||||
		s.step = stateTru
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'u')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateTru is the state after reading `tru`.
 | 
			
		||||
func stateTru(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'e' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal true (expecting 'e')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateF is the state after reading `f`.
 | 
			
		||||
func stateF(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'a' {
 | 
			
		||||
		s.step = stateFa
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'a')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFa is the state after reading `fa`.
 | 
			
		||||
func stateFa(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateFal
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFal is the state after reading `fal`.
 | 
			
		||||
func stateFal(s *scanner, c byte) int {
 | 
			
		||||
	if c == 's' {
 | 
			
		||||
		s.step = stateFals
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 's')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateFals is the state after reading `fals`.
 | 
			
		||||
func stateFals(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'e' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal false (expecting 'e')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateN is the state after reading `n`.
 | 
			
		||||
func stateN(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'u' {
 | 
			
		||||
		s.step = stateNu
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'u')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNu is the state after reading `nu`.
 | 
			
		||||
func stateNu(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateNul
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateNul is the state after reading `nul`.
 | 
			
		||||
func stateNul(s *scanner, c byte) int {
 | 
			
		||||
	if c == 'l' {
 | 
			
		||||
		s.step = stateEndValue
 | 
			
		||||
		return scanContinue
 | 
			
		||||
	}
 | 
			
		||||
	return s.error(c, "in literal null (expecting 'l')")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// stateError is the state after reaching a syntax error,
 | 
			
		||||
// such as after reading `[1}` or `5.1.2`.
 | 
			
		||||
func stateError(s *scanner, c byte) int {
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// error records an error and switches to the error state.
 | 
			
		||||
func (s *scanner) error(c byte, context string) int {
 | 
			
		||||
	s.step = stateError
 | 
			
		||||
	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
 | 
			
		||||
	return scanError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// quoteChar formats c as a quoted character literal
 | 
			
		||||
func quoteChar(c byte) string {
 | 
			
		||||
	// special cases - different from quoted strings
 | 
			
		||||
	if c == '\'' {
 | 
			
		||||
		return `'\''`
 | 
			
		||||
	}
 | 
			
		||||
	if c == '"' {
 | 
			
		||||
		return `'"'`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// use quoted string with different quotation marks
 | 
			
		||||
	s := strconv.Quote(string(c))
 | 
			
		||||
	return "'" + s[1:len(s)-1] + "'"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								vendor/github.com/d5/tengo/stdlib/math.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/d5/tengo/stdlib/math.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var mathModule = map[string]objects.Object{
 | 
			
		||||
	"e":         &objects.Float{Value: math.E},
 | 
			
		||||
	"pi":        &objects.Float{Value: math.Pi},
 | 
			
		||||
	"phi":       &objects.Float{Value: math.Phi},
 | 
			
		||||
	"sqrt2":     &objects.Float{Value: math.Sqrt2},
 | 
			
		||||
	"sqrtE":     &objects.Float{Value: math.SqrtE},
 | 
			
		||||
	"sqrtPi":    &objects.Float{Value: math.SqrtPi},
 | 
			
		||||
	"sqrtPhi":   &objects.Float{Value: math.SqrtPhi},
 | 
			
		||||
	"ln2":       &objects.Float{Value: math.Ln2},
 | 
			
		||||
	"log2E":     &objects.Float{Value: math.Log2E},
 | 
			
		||||
	"ln10":      &objects.Float{Value: math.Ln10},
 | 
			
		||||
	"log10E":    &objects.Float{Value: math.Log10E},
 | 
			
		||||
	"abs":       &objects.UserFunction{Name: "abs", Value: FuncAFRF(math.Abs)},
 | 
			
		||||
	"acos":      &objects.UserFunction{Name: "acos", Value: FuncAFRF(math.Acos)},
 | 
			
		||||
	"acosh":     &objects.UserFunction{Name: "acosh", Value: FuncAFRF(math.Acosh)},
 | 
			
		||||
	"asin":      &objects.UserFunction{Name: "asin", Value: FuncAFRF(math.Asin)},
 | 
			
		||||
	"asinh":     &objects.UserFunction{Name: "asinh", Value: FuncAFRF(math.Asinh)},
 | 
			
		||||
	"atan":      &objects.UserFunction{Name: "atan", Value: FuncAFRF(math.Atan)},
 | 
			
		||||
	"atan2":     &objects.UserFunction{Name: "atan2", Value: FuncAFFRF(math.Atan2)},
 | 
			
		||||
	"atanh":     &objects.UserFunction{Name: "atanh", Value: FuncAFRF(math.Atanh)},
 | 
			
		||||
	"cbrt":      &objects.UserFunction{Name: "cbrt", Value: FuncAFRF(math.Cbrt)},
 | 
			
		||||
	"ceil":      &objects.UserFunction{Name: "ceil", Value: FuncAFRF(math.Ceil)},
 | 
			
		||||
	"copysign":  &objects.UserFunction{Name: "copysign", Value: FuncAFFRF(math.Copysign)},
 | 
			
		||||
	"cos":       &objects.UserFunction{Name: "cos", Value: FuncAFRF(math.Cos)},
 | 
			
		||||
	"cosh":      &objects.UserFunction{Name: "cosh", Value: FuncAFRF(math.Cosh)},
 | 
			
		||||
	"dim":       &objects.UserFunction{Name: "dim", Value: FuncAFFRF(math.Dim)},
 | 
			
		||||
	"erf":       &objects.UserFunction{Name: "erf", Value: FuncAFRF(math.Erf)},
 | 
			
		||||
	"erfc":      &objects.UserFunction{Name: "erfc", Value: FuncAFRF(math.Erfc)},
 | 
			
		||||
	"exp":       &objects.UserFunction{Name: "exp", Value: FuncAFRF(math.Exp)},
 | 
			
		||||
	"exp2":      &objects.UserFunction{Name: "exp2", Value: FuncAFRF(math.Exp2)},
 | 
			
		||||
	"expm1":     &objects.UserFunction{Name: "expm1", Value: FuncAFRF(math.Expm1)},
 | 
			
		||||
	"floor":     &objects.UserFunction{Name: "floor", Value: FuncAFRF(math.Floor)},
 | 
			
		||||
	"gamma":     &objects.UserFunction{Name: "gamma", Value: FuncAFRF(math.Gamma)},
 | 
			
		||||
	"hypot":     &objects.UserFunction{Name: "hypot", Value: FuncAFFRF(math.Hypot)},
 | 
			
		||||
	"ilogb":     &objects.UserFunction{Name: "ilogb", Value: FuncAFRI(math.Ilogb)},
 | 
			
		||||
	"inf":       &objects.UserFunction{Name: "inf", Value: FuncAIRF(math.Inf)},
 | 
			
		||||
	"is_inf":    &objects.UserFunction{Name: "is_inf", Value: FuncAFIRB(math.IsInf)},
 | 
			
		||||
	"is_nan":    &objects.UserFunction{Name: "is_nan", Value: FuncAFRB(math.IsNaN)},
 | 
			
		||||
	"j0":        &objects.UserFunction{Name: "j0", Value: FuncAFRF(math.J0)},
 | 
			
		||||
	"j1":        &objects.UserFunction{Name: "j1", Value: FuncAFRF(math.J1)},
 | 
			
		||||
	"jn":        &objects.UserFunction{Name: "jn", Value: FuncAIFRF(math.Jn)},
 | 
			
		||||
	"ldexp":     &objects.UserFunction{Name: "ldexp", Value: FuncAFIRF(math.Ldexp)},
 | 
			
		||||
	"log":       &objects.UserFunction{Name: "log", Value: FuncAFRF(math.Log)},
 | 
			
		||||
	"log10":     &objects.UserFunction{Name: "log10", Value: FuncAFRF(math.Log10)},
 | 
			
		||||
	"log1p":     &objects.UserFunction{Name: "log1p", Value: FuncAFRF(math.Log1p)},
 | 
			
		||||
	"log2":      &objects.UserFunction{Name: "log2", Value: FuncAFRF(math.Log2)},
 | 
			
		||||
	"logb":      &objects.UserFunction{Name: "logb", Value: FuncAFRF(math.Logb)},
 | 
			
		||||
	"max":       &objects.UserFunction{Name: "max", Value: FuncAFFRF(math.Max)},
 | 
			
		||||
	"min":       &objects.UserFunction{Name: "min", Value: FuncAFFRF(math.Min)},
 | 
			
		||||
	"mod":       &objects.UserFunction{Name: "mod", Value: FuncAFFRF(math.Mod)},
 | 
			
		||||
	"nan":       &objects.UserFunction{Name: "nan", Value: FuncARF(math.NaN)},
 | 
			
		||||
	"nextafter": &objects.UserFunction{Name: "nextafter", Value: FuncAFFRF(math.Nextafter)},
 | 
			
		||||
	"pow":       &objects.UserFunction{Name: "pow", Value: FuncAFFRF(math.Pow)},
 | 
			
		||||
	"pow10":     &objects.UserFunction{Name: "pow10", Value: FuncAIRF(math.Pow10)},
 | 
			
		||||
	"remainder": &objects.UserFunction{Name: "remainder", Value: FuncAFFRF(math.Remainder)},
 | 
			
		||||
	"signbit":   &objects.UserFunction{Name: "signbit", Value: FuncAFRB(math.Signbit)},
 | 
			
		||||
	"sin":       &objects.UserFunction{Name: "sin", Value: FuncAFRF(math.Sin)},
 | 
			
		||||
	"sinh":      &objects.UserFunction{Name: "sinh", Value: FuncAFRF(math.Sinh)},
 | 
			
		||||
	"sqrt":      &objects.UserFunction{Name: "sqrt", Value: FuncAFRF(math.Sqrt)},
 | 
			
		||||
	"tan":       &objects.UserFunction{Name: "tan", Value: FuncAFRF(math.Tan)},
 | 
			
		||||
	"tanh":      &objects.UserFunction{Name: "tanh", Value: FuncAFRF(math.Tanh)},
 | 
			
		||||
	"trunc":     &objects.UserFunction{Name: "trunc", Value: FuncAFRF(math.Trunc)},
 | 
			
		||||
	"y0":        &objects.UserFunction{Name: "y0", Value: FuncAFRF(math.Y0)},
 | 
			
		||||
	"y1":        &objects.UserFunction{Name: "y1", Value: FuncAFRF(math.Y1)},
 | 
			
		||||
	"yn":        &objects.UserFunction{Name: "yn", Value: FuncAIFRF(math.Yn)},
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										492
									
								
								vendor/github.com/d5/tengo/stdlib/os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										492
									
								
								vendor/github.com/d5/tengo/stdlib/os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,492 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var osModule = map[string]objects.Object{
 | 
			
		||||
	"o_rdonly":            &objects.Int{Value: int64(os.O_RDONLY)},
 | 
			
		||||
	"o_wronly":            &objects.Int{Value: int64(os.O_WRONLY)},
 | 
			
		||||
	"o_rdwr":              &objects.Int{Value: int64(os.O_RDWR)},
 | 
			
		||||
	"o_append":            &objects.Int{Value: int64(os.O_APPEND)},
 | 
			
		||||
	"o_create":            &objects.Int{Value: int64(os.O_CREATE)},
 | 
			
		||||
	"o_excl":              &objects.Int{Value: int64(os.O_EXCL)},
 | 
			
		||||
	"o_sync":              &objects.Int{Value: int64(os.O_SYNC)},
 | 
			
		||||
	"o_trunc":             &objects.Int{Value: int64(os.O_TRUNC)},
 | 
			
		||||
	"mode_dir":            &objects.Int{Value: int64(os.ModeDir)},
 | 
			
		||||
	"mode_append":         &objects.Int{Value: int64(os.ModeAppend)},
 | 
			
		||||
	"mode_exclusive":      &objects.Int{Value: int64(os.ModeExclusive)},
 | 
			
		||||
	"mode_temporary":      &objects.Int{Value: int64(os.ModeTemporary)},
 | 
			
		||||
	"mode_symlink":        &objects.Int{Value: int64(os.ModeSymlink)},
 | 
			
		||||
	"mode_device":         &objects.Int{Value: int64(os.ModeDevice)},
 | 
			
		||||
	"mode_named_pipe":     &objects.Int{Value: int64(os.ModeNamedPipe)},
 | 
			
		||||
	"mode_socket":         &objects.Int{Value: int64(os.ModeSocket)},
 | 
			
		||||
	"mode_setuid":         &objects.Int{Value: int64(os.ModeSetuid)},
 | 
			
		||||
	"mode_setgui":         &objects.Int{Value: int64(os.ModeSetgid)},
 | 
			
		||||
	"mode_char_device":    &objects.Int{Value: int64(os.ModeCharDevice)},
 | 
			
		||||
	"mode_sticky":         &objects.Int{Value: int64(os.ModeSticky)},
 | 
			
		||||
	"mode_type":           &objects.Int{Value: int64(os.ModeType)},
 | 
			
		||||
	"mode_perm":           &objects.Int{Value: int64(os.ModePerm)},
 | 
			
		||||
	"path_separator":      &objects.Char{Value: os.PathSeparator},
 | 
			
		||||
	"path_list_separator": &objects.Char{Value: os.PathListSeparator},
 | 
			
		||||
	"dev_null":            &objects.String{Value: os.DevNull},
 | 
			
		||||
	"seek_set":            &objects.Int{Value: int64(io.SeekStart)},
 | 
			
		||||
	"seek_cur":            &objects.Int{Value: int64(io.SeekCurrent)},
 | 
			
		||||
	"seek_end":            &objects.Int{Value: int64(io.SeekEnd)},
 | 
			
		||||
	"args":                &objects.UserFunction{Name: "args", Value: osArgs},                             // args() => array(string)
 | 
			
		||||
	"chdir":               &objects.UserFunction{Name: "chdir", Value: FuncASRE(os.Chdir)},                // chdir(dir string) => error
 | 
			
		||||
	"chmod":               osFuncASFmRE("chmod", os.Chmod),                                                // chmod(name string, mode int) => error
 | 
			
		||||
	"chown":               &objects.UserFunction{Name: "chown", Value: FuncASIIRE(os.Chown)},              // chown(name string, uid int, gid int) => error
 | 
			
		||||
	"clearenv":            &objects.UserFunction{Name: "clearenv", Value: FuncAR(os.Clearenv)},            // clearenv()
 | 
			
		||||
	"environ":             &objects.UserFunction{Name: "environ", Value: FuncARSs(os.Environ)},            // environ() => array(string)
 | 
			
		||||
	"exit":                &objects.UserFunction{Name: "exit", Value: FuncAIR(os.Exit)},                   // exit(code int)
 | 
			
		||||
	"expand_env":          &objects.UserFunction{Name: "expand_env", Value: osExpandEnv},                  // expand_env(s string) => string
 | 
			
		||||
	"getegid":             &objects.UserFunction{Name: "getegid", Value: FuncARI(os.Getegid)},             // getegid() => int
 | 
			
		||||
	"getenv":              &objects.UserFunction{Name: "getenv", Value: FuncASRS(os.Getenv)},              // getenv(s string) => string
 | 
			
		||||
	"geteuid":             &objects.UserFunction{Name: "geteuid", Value: FuncARI(os.Geteuid)},             // geteuid() => int
 | 
			
		||||
	"getgid":              &objects.UserFunction{Name: "getgid", Value: FuncARI(os.Getgid)},               // getgid() => int
 | 
			
		||||
	"getgroups":           &objects.UserFunction{Name: "getgroups", Value: FuncARIsE(os.Getgroups)},       // getgroups() => array(string)/error
 | 
			
		||||
	"getpagesize":         &objects.UserFunction{Name: "getpagesize", Value: FuncARI(os.Getpagesize)},     // getpagesize() => int
 | 
			
		||||
	"getpid":              &objects.UserFunction{Name: "getpid", Value: FuncARI(os.Getpid)},               // getpid() => int
 | 
			
		||||
	"getppid":             &objects.UserFunction{Name: "getppid", Value: FuncARI(os.Getppid)},             // getppid() => int
 | 
			
		||||
	"getuid":              &objects.UserFunction{Name: "getuid", Value: FuncARI(os.Getuid)},               // getuid() => int
 | 
			
		||||
	"getwd":               &objects.UserFunction{Name: "getwd", Value: FuncARSE(os.Getwd)},                // getwd() => string/error
 | 
			
		||||
	"hostname":            &objects.UserFunction{Name: "hostname", Value: FuncARSE(os.Hostname)},          // hostname() => string/error
 | 
			
		||||
	"lchown":              &objects.UserFunction{Name: "lchown", Value: FuncASIIRE(os.Lchown)},            // lchown(name string, uid int, gid int) => error
 | 
			
		||||
	"link":                &objects.UserFunction{Name: "link", Value: FuncASSRE(os.Link)},                 // link(oldname string, newname string) => error
 | 
			
		||||
	"lookup_env":          &objects.UserFunction{Name: "lookup_env", Value: osLookupEnv},                  // lookup_env(key string) => string/false
 | 
			
		||||
	"mkdir":               osFuncASFmRE("mkdir", os.Mkdir),                                                // mkdir(name string, perm int) => error
 | 
			
		||||
	"mkdir_all":           osFuncASFmRE("mkdir_all", os.MkdirAll),                                         // mkdir_all(name string, perm int) => error
 | 
			
		||||
	"readlink":            &objects.UserFunction{Name: "readlink", Value: FuncASRSE(os.Readlink)},         // readlink(name string) => string/error
 | 
			
		||||
	"remove":              &objects.UserFunction{Name: "remove", Value: FuncASRE(os.Remove)},              // remove(name string) => error
 | 
			
		||||
	"remove_all":          &objects.UserFunction{Name: "remove_all", Value: FuncASRE(os.RemoveAll)},       // remove_all(name string) => error
 | 
			
		||||
	"rename":              &objects.UserFunction{Name: "rename", Value: FuncASSRE(os.Rename)},             // rename(oldpath string, newpath string) => error
 | 
			
		||||
	"setenv":              &objects.UserFunction{Name: "setenv", Value: FuncASSRE(os.Setenv)},             // setenv(key string, value string) => error
 | 
			
		||||
	"symlink":             &objects.UserFunction{Name: "symlink", Value: FuncASSRE(os.Symlink)},           // symlink(oldname string newname string) => error
 | 
			
		||||
	"temp_dir":            &objects.UserFunction{Name: "temp_dir", Value: FuncARS(os.TempDir)},            // temp_dir() => string
 | 
			
		||||
	"truncate":            &objects.UserFunction{Name: "truncate", Value: FuncASI64RE(os.Truncate)},       // truncate(name string, size int) => error
 | 
			
		||||
	"unsetenv":            &objects.UserFunction{Name: "unsetenv", Value: FuncASRE(os.Unsetenv)},          // unsetenv(key string) => error
 | 
			
		||||
	"create":              &objects.UserFunction{Name: "create", Value: osCreate},                         // create(name string) => imap(file)/error
 | 
			
		||||
	"open":                &objects.UserFunction{Name: "open", Value: osOpen},                             // open(name string) => imap(file)/error
 | 
			
		||||
	"open_file":           &objects.UserFunction{Name: "open_file", Value: osOpenFile},                    // open_file(name string, flag int, perm int) => imap(file)/error
 | 
			
		||||
	"find_process":        &objects.UserFunction{Name: "find_process", Value: osFindProcess},              // find_process(pid int) => imap(process)/error
 | 
			
		||||
	"start_process":       &objects.UserFunction{Name: "start_process", Value: osStartProcess},            // start_process(name string, argv array(string), dir string, env array(string)) => imap(process)/error
 | 
			
		||||
	"exec_look_path":      &objects.UserFunction{Name: "exec_look_path", Value: FuncASRSE(exec.LookPath)}, // exec_look_path(file) => string/error
 | 
			
		||||
	"exec":                &objects.UserFunction{Name: "exec", Value: osExec},                             // exec(name, args...) => command
 | 
			
		||||
	"stat":                &objects.UserFunction{Name: "stat", Value: osStat},                             // stat(name) => imap(fileinfo)/error
 | 
			
		||||
	"read_file":           &objects.UserFunction{Name: "read_file", Value: osReadFile},                    // readfile(name) => array(byte)/error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osReadFile(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fname, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bytes, err := ioutil.ReadFile(fname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(bytes) > tengo.MaxBytesLen {
 | 
			
		||||
		return nil, objects.ErrBytesLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.Bytes{Value: bytes}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osStat(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fname, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stat, err := os.Stat(fname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fstat := &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			"name":  &objects.String{Value: stat.Name()},
 | 
			
		||||
			"mtime": &objects.Time{Value: stat.ModTime()},
 | 
			
		||||
			"size":  &objects.Int{Value: stat.Size()},
 | 
			
		||||
			"mode":  &objects.Int{Value: int64(stat.Mode())},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if stat.IsDir() {
 | 
			
		||||
		fstat.Value["directory"] = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		fstat.Value["directory"] = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fstat, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osCreate(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := os.Create(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSFile(res), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osOpen(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := os.Open(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSFile(res), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osOpenFile(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 3 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := os.OpenFile(s1, i2, os.FileMode(i3))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSFile(res), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osArgs(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 0 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arr := &objects.Array{}
 | 
			
		||||
	for _, osArg := range os.Args {
 | 
			
		||||
		if len(osArg) > tengo.MaxStringLen {
 | 
			
		||||
			return nil, objects.ErrStringLimit
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		arr.Value = append(arr.Value, &objects.String{Value: osArg})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return arr, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osFuncASFmRE(name string, fn func(string, os.FileMode) error) *objects.UserFunction {
 | 
			
		||||
	return &objects.UserFunction{
 | 
			
		||||
		Name: name,
 | 
			
		||||
		Value: func(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
			if len(args) != 2 {
 | 
			
		||||
				return nil, objects.ErrWrongNumArguments
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			s1, ok := objects.ToString(args[0])
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     "first",
 | 
			
		||||
					Expected: "string(compatible)",
 | 
			
		||||
					Found:    args[0].TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			i2, ok := objects.ToInt64(args[1])
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     "second",
 | 
			
		||||
					Expected: "int(compatible)",
 | 
			
		||||
					Found:    args[1].TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return wrapError(fn(s1, os.FileMode(i2))), nil
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osLookupEnv(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, ok := os.LookupEnv(s1)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return objects.FalseValue, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(res) > tengo.MaxStringLen {
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.String{Value: res}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osExpandEnv(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var vlen int
 | 
			
		||||
	var failed bool
 | 
			
		||||
	s := os.Expand(s1, func(k string) string {
 | 
			
		||||
		if failed {
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		v := os.Getenv(k)
 | 
			
		||||
 | 
			
		||||
		// this does not count the other texts that are not being replaced
 | 
			
		||||
		// but the code checks the final length at the end
 | 
			
		||||
		vlen += len(v)
 | 
			
		||||
		if vlen > tengo.MaxStringLen {
 | 
			
		||||
			failed = true
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return v
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if failed || len(s) > tengo.MaxStringLen {
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.String{Value: s}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osExec(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) == 0 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var execArgs []string
 | 
			
		||||
	for idx, arg := range args[1:] {
 | 
			
		||||
		execArg, ok := objects.ToString(arg)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
				Name:     fmt.Sprintf("args[%d]", idx),
 | 
			
		||||
				Expected: "string(compatible)",
 | 
			
		||||
				Found:    args[1+idx].TypeName(),
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		execArgs = append(execArgs, execArg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSExecCommand(exec.Command(name, execArgs...)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osFindProcess(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proc, err := os.FindProcess(i1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSProcess(proc), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func osStartProcess(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
	if len(args) != 4 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var argv []string
 | 
			
		||||
	var err error
 | 
			
		||||
	switch arg1 := args[1].(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		argv, err = stringArray(arg1.Value, "second")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	case *objects.ImmutableArray:
 | 
			
		||||
		argv, err = stringArray(arg1.Value, "second")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "array",
 | 
			
		||||
			Found:    arg1.TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir, ok := objects.ToString(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var env []string
 | 
			
		||||
	switch arg3 := args[3].(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		env, err = stringArray(arg3.Value, "fourth")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	case *objects.ImmutableArray:
 | 
			
		||||
		env, err = stringArray(arg3.Value, "fourth")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fourth",
 | 
			
		||||
			Expected: "array",
 | 
			
		||||
			Found:    arg3.TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proc, err := os.StartProcess(name, argv, &os.ProcAttr{
 | 
			
		||||
		Dir: dir,
 | 
			
		||||
		Env: env,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return wrapError(err), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return makeOSProcess(proc), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stringArray(arr []objects.Object, argName string) ([]string, error) {
 | 
			
		||||
	var sarr []string
 | 
			
		||||
	for idx, elem := range arr {
 | 
			
		||||
		str, ok := elem.(*objects.String)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
				Name:     fmt.Sprintf("%s[%d]", argName, idx),
 | 
			
		||||
				Expected: "string",
 | 
			
		||||
				Found:    elem.TypeName(),
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sarr = append(sarr, str.Value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sarr, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								vendor/github.com/d5/tengo/stdlib/os_exec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/d5/tengo/stdlib/os_exec.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os/exec"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeOSExecCommand(cmd *exec.Cmd) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			// combined_output() => bytes/error
 | 
			
		||||
			"combined_output": &objects.UserFunction{Name: "combined_output", Value: FuncARYE(cmd.CombinedOutput)}, //
 | 
			
		||||
			// output() => bytes/error
 | 
			
		||||
			"output": &objects.UserFunction{Name: "output", Value: FuncARYE(cmd.Output)}, //
 | 
			
		||||
			// run() => error
 | 
			
		||||
			"run": &objects.UserFunction{Name: "run", Value: FuncARE(cmd.Run)}, //
 | 
			
		||||
			// start() => error
 | 
			
		||||
			"start": &objects.UserFunction{Name: "start", Value: FuncARE(cmd.Start)}, //
 | 
			
		||||
			// wait() => error
 | 
			
		||||
			"wait": &objects.UserFunction{Name: "wait", Value: FuncARE(cmd.Wait)}, //
 | 
			
		||||
			// set_path(path string)
 | 
			
		||||
			"set_path": &objects.UserFunction{
 | 
			
		||||
				Name: "set_path",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					cmd.Path = s1
 | 
			
		||||
 | 
			
		||||
					return objects.UndefinedValue, nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			// set_dir(dir string)
 | 
			
		||||
			"set_dir": &objects.UserFunction{
 | 
			
		||||
				Name: "set_dir",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					cmd.Dir = s1
 | 
			
		||||
 | 
			
		||||
					return objects.UndefinedValue, nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			// set_env(env array(string))
 | 
			
		||||
			"set_env": &objects.UserFunction{
 | 
			
		||||
				Name: "set_env",
 | 
			
		||||
				Value: func(args ...objects.Object) (objects.Object, error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					var env []string
 | 
			
		||||
					var err error
 | 
			
		||||
					switch arg0 := args[0].(type) {
 | 
			
		||||
					case *objects.Array:
 | 
			
		||||
						env, err = stringArray(arg0.Value, "first")
 | 
			
		||||
						if err != nil {
 | 
			
		||||
							return nil, err
 | 
			
		||||
						}
 | 
			
		||||
					case *objects.ImmutableArray:
 | 
			
		||||
						env, err = stringArray(arg0.Value, "first")
 | 
			
		||||
						if err != nil {
 | 
			
		||||
							return nil, err
 | 
			
		||||
						}
 | 
			
		||||
					default:
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "array",
 | 
			
		||||
							Found:    arg0.TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					cmd.Env = env
 | 
			
		||||
 | 
			
		||||
					return objects.UndefinedValue, nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			// process() => imap(process)
 | 
			
		||||
			"process": &objects.UserFunction{
 | 
			
		||||
				Name: "process",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 0 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return makeOSProcess(cmd.Process), nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								vendor/github.com/d5/tengo/stdlib/os_file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								vendor/github.com/d5/tengo/stdlib/os_file.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeOSFile(file *os.File) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			// chdir() => true/error
 | 
			
		||||
			"chdir": &objects.UserFunction{Name: "chdir", Value: FuncARE(file.Chdir)}, //
 | 
			
		||||
			// chown(uid int, gid int) => true/error
 | 
			
		||||
			"chown": &objects.UserFunction{Name: "chown", Value: FuncAIIRE(file.Chown)}, //
 | 
			
		||||
			// close() => error
 | 
			
		||||
			"close": &objects.UserFunction{Name: "close", Value: FuncARE(file.Close)}, //
 | 
			
		||||
			// name() => string
 | 
			
		||||
			"name": &objects.UserFunction{Name: "name", Value: FuncARS(file.Name)}, //
 | 
			
		||||
			// readdirnames(n int) => array(string)/error
 | 
			
		||||
			"readdirnames": &objects.UserFunction{Name: "readdirnames", Value: FuncAIRSsE(file.Readdirnames)}, //
 | 
			
		||||
			// sync() => error
 | 
			
		||||
			"sync": &objects.UserFunction{Name: "sync", Value: FuncARE(file.Sync)}, //
 | 
			
		||||
			// write(bytes) => int/error
 | 
			
		||||
			"write": &objects.UserFunction{Name: "write", Value: FuncAYRIE(file.Write)}, //
 | 
			
		||||
			// write(string) => int/error
 | 
			
		||||
			"write_string": &objects.UserFunction{Name: "write_string", Value: FuncASRIE(file.WriteString)}, //
 | 
			
		||||
			// read(bytes) => int/error
 | 
			
		||||
			"read": &objects.UserFunction{Name: "read", Value: FuncAYRIE(file.Read)}, //
 | 
			
		||||
			// chmod(mode int) => error
 | 
			
		||||
			"chmod": &objects.UserFunction{
 | 
			
		||||
				Name: "chmod",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "int(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return wrapError(file.Chmod(os.FileMode(i1))), nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			// seek(offset int, whence int) => int/error
 | 
			
		||||
			"seek": &objects.UserFunction{
 | 
			
		||||
				Name: "seek",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 2 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "int(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					i2, ok := objects.ToInt(args[1])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "second",
 | 
			
		||||
							Expected: "int(compatible)",
 | 
			
		||||
							Found:    args[1].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					res, err := file.Seek(i1, i2)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return wrapError(err), nil
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return &objects.Int{Value: res}, nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			// stat() => imap(fileinfo)/error
 | 
			
		||||
			"stat": &objects.UserFunction{
 | 
			
		||||
				Name: "start",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 0 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return osStat(&objects.String{Value: file.Name()})
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								vendor/github.com/d5/tengo/stdlib/os_process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/d5/tengo/stdlib/os_process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeOSProcessState(state *os.ProcessState) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			"exited":  &objects.UserFunction{Name: "exited", Value: FuncARB(state.Exited)},   //
 | 
			
		||||
			"pid":     &objects.UserFunction{Name: "pid", Value: FuncARI(state.Pid)},         //
 | 
			
		||||
			"string":  &objects.UserFunction{Name: "string", Value: FuncARS(state.String)},   //
 | 
			
		||||
			"success": &objects.UserFunction{Name: "success", Value: FuncARB(state.Success)}, //
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeOSProcess(proc *os.Process) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			"kill":    &objects.UserFunction{Name: "kill", Value: FuncARE(proc.Kill)},       //
 | 
			
		||||
			"release": &objects.UserFunction{Name: "release", Value: FuncARE(proc.Release)}, //
 | 
			
		||||
			"signal": &objects.UserFunction{
 | 
			
		||||
				Name: "signal",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "int(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return wrapError(proc.Signal(syscall.Signal(i1))), nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			"wait": &objects.UserFunction{
 | 
			
		||||
				Name: "wait",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 0 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					state, err := proc.Wait()
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return wrapError(err), nil
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return makeOSProcessState(state), nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								vendor/github.com/d5/tengo/stdlib/rand.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/d5/tengo/stdlib/rand.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math/rand"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var randModule = map[string]objects.Object{
 | 
			
		||||
	"int":        &objects.UserFunction{Name: "int", Value: FuncARI64(rand.Int63)},
 | 
			
		||||
	"float":      &objects.UserFunction{Name: "float", Value: FuncARF(rand.Float64)},
 | 
			
		||||
	"intn":       &objects.UserFunction{Name: "intn", Value: FuncAI64RI64(rand.Int63n)},
 | 
			
		||||
	"exp_float":  &objects.UserFunction{Name: "exp_float", Value: FuncARF(rand.ExpFloat64)},
 | 
			
		||||
	"norm_float": &objects.UserFunction{Name: "norm_float", Value: FuncARF(rand.NormFloat64)},
 | 
			
		||||
	"perm":       &objects.UserFunction{Name: "perm", Value: FuncAIRIs(rand.Perm)},
 | 
			
		||||
	"seed":       &objects.UserFunction{Name: "seed", Value: FuncAI64R(rand.Seed)},
 | 
			
		||||
	"read": &objects.UserFunction{
 | 
			
		||||
		Name: "read",
 | 
			
		||||
		Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
			if len(args) != 1 {
 | 
			
		||||
				return nil, objects.ErrWrongNumArguments
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			y1, ok := args[0].(*objects.Bytes)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     "first",
 | 
			
		||||
					Expected: "bytes",
 | 
			
		||||
					Found:    args[0].TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			res, err := rand.Read(y1.Value)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				ret = wrapError(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return &objects.Int{Value: int64(res)}, nil
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	"rand": &objects.UserFunction{
 | 
			
		||||
		Name: "rand",
 | 
			
		||||
		Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
			if len(args) != 1 {
 | 
			
		||||
				return nil, objects.ErrWrongNumArguments
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     "first",
 | 
			
		||||
					Expected: "int(compatible)",
 | 
			
		||||
					Found:    args[0].TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			src := rand.NewSource(i1)
 | 
			
		||||
 | 
			
		||||
			return randRand(rand.New(src)), nil
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func randRand(r *rand.Rand) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			"int":        &objects.UserFunction{Name: "int", Value: FuncARI64(r.Int63)},
 | 
			
		||||
			"float":      &objects.UserFunction{Name: "float", Value: FuncARF(r.Float64)},
 | 
			
		||||
			"intn":       &objects.UserFunction{Name: "intn", Value: FuncAI64RI64(r.Int63n)},
 | 
			
		||||
			"exp_float":  &objects.UserFunction{Name: "exp_float", Value: FuncARF(r.ExpFloat64)},
 | 
			
		||||
			"norm_float": &objects.UserFunction{Name: "norm_float", Value: FuncARF(r.NormFloat64)},
 | 
			
		||||
			"perm":       &objects.UserFunction{Name: "perm", Value: FuncAIRIs(r.Perm)},
 | 
			
		||||
			"seed":       &objects.UserFunction{Name: "seed", Value: FuncAI64R(r.Seed)},
 | 
			
		||||
			"read": &objects.UserFunction{
 | 
			
		||||
				Name: "read",
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						return nil, objects.ErrWrongNumArguments
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					y1, ok := args[0].(*objects.Bytes)
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "bytes",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					res, err := r.Read(y1.Value)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						ret = wrapError(err)
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return &objects.Int{Value: int64(res)}, nil
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/d5/tengo/stdlib/source_modules.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/d5/tengo/stdlib/source_modules.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
// Code generated using gensrcmods.go; DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
// SourceModules are source type standard library modules.
 | 
			
		||||
var SourceModules = map[string]string{
 | 
			
		||||
	"enum": "is_enumerable := func(x) {\n  return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)\n}\n\nis_array_like := func(x) {\n  return is_array(x) || is_immutable_array(x)\n}\n\nexport {\n  // all returns true if the given function `fn` evaluates to a truthy value on\n  // all of the items in `x`. It returns undefined if `x` is not enumerable.\n  all: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    for k, v in x {\n      if !fn(k, v) { return false }\n    }\n\n    return true\n  },\n  // any returns true if the given function `fn` evaluates to a truthy value on\n  // any of the items in `x`. It returns undefined if `x` is not enumerable.\n  any: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    for k, v in x {\n      if fn(k, v) { return true }\n    }\n\n    return false\n  },\n  // chunk returns an array of elements split into groups the length of size.\n  // If `x` can't be split evenly, the final chunk will be the remaining elements.\n  // It returns undefined if `x` is not array.\n  chunk: func(x, size) {\n    if !is_array_like(x) || !size { return undefined }\n\n    numElements := len(x)\n    if !numElements { return [] }\n\n    res := []\n    idx := 0\n    for idx < numElements {\n      res = append(res, x[idx:idx+size])\n      idx += size\n    }\n\n    return res\n  },\n  // at returns an element at the given index (if `x` is array) or\n  // key (if `x` is map). It returns undefined if `x` is not enumerable.\n  at: func(x, key) {\n    if !is_enumerable(x) { return undefined }\n\n    if is_array_like(x) {\n        if !is_int(key) { return undefined }\n    } else {\n        if !is_string(key) { return undefined }\n    }\n\n    return x[key]\n  },\n  // each iterates over elements of `x` and invokes `fn` for each element. `fn` is\n  // invoked with two arguments: `key` and `value`. `key` is an int index\n  // if `x` is array. `key` is a string key if `x` is map. It does not iterate\n  // and returns undefined if `x` is not enumerable.\n  each: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    for k, v in x {\n      fn(k, v)\n    }\n  },\n  // filter iterates over elements of `x`, returning an array of all elements `fn`\n  // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n  // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n  // It returns undefined if `x` is not enumerable.\n  filter: func(x, fn) {\n    if !is_array_like(x) { return undefined }\n\n    dst := []\n    for k, v in x {\n      if fn(k, v) { dst = append(dst, v) }\n    }\n\n    return dst\n  },\n  // find iterates over elements of `x`, returning value of the first element `fn`\n  // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.\n  // `key` is an int index if `x` is array. `key` is a string key if `x` is map.\n  // It returns undefined if `x` is not enumerable.\n  find: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    for k, v in x {\n      if fn(k, v) { return v }\n    }\n  },\n  // find_key iterates over elements of `x`, returning key or index of the first\n  // element `fn` returns truthy for. `fn` is invoked with two arguments: `key`\n  // and `value`. `key` is an int index if `x` is array. `key` is a string key if\n  // `x` is map. It returns undefined if `x` is not enumerable.\n  find_key: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    for k, v in x {\n      if fn(k, v) { return k }\n    }\n  },\n  // map creates an array of values by running each element in `x` through `fn`.\n  // `fn` is invoked with two arguments: `key` and `value`. `key` is an int index\n  // if `x` is array. `key` is a string key if `x` is map. It returns undefined\n  // if `x` is not enumerable.\n  map: func(x, fn) {\n    if !is_enumerable(x) { return undefined }\n\n    dst := []\n    for k, v in x {\n      dst = append(dst, fn(k, v))\n    }\n\n    return dst\n  },\n  // key returns the first argument.\n  key: func(k, _) { return k },\n  // value returns the second argument.\n  value: func(_, v) { return v }\n}\n",
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										128
									
								
								vendor/github.com/d5/tengo/stdlib/srcmod_enum.tengo
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								vendor/github.com/d5/tengo/stdlib/srcmod_enum.tengo
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
is_enumerable := func(x) {
 | 
			
		||||
  return is_array(x) || is_map(x) || is_immutable_array(x) || is_immutable_map(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
is_array_like := func(x) {
 | 
			
		||||
  return is_array(x) || is_immutable_array(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  // all returns true if the given function `fn` evaluates to a truthy value on
 | 
			
		||||
  // all of the items in `x`. It returns undefined if `x` is not enumerable.
 | 
			
		||||
  all: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      if !fn(k, v) { return false }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true
 | 
			
		||||
  },
 | 
			
		||||
  // any returns true if the given function `fn` evaluates to a truthy value on
 | 
			
		||||
  // any of the items in `x`. It returns undefined if `x` is not enumerable.
 | 
			
		||||
  any: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      if fn(k, v) { return true }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false
 | 
			
		||||
  },
 | 
			
		||||
  // chunk returns an array of elements split into groups the length of size.
 | 
			
		||||
  // If `x` can't be split evenly, the final chunk will be the remaining elements.
 | 
			
		||||
  // It returns undefined if `x` is not array.
 | 
			
		||||
  chunk: func(x, size) {
 | 
			
		||||
    if !is_array_like(x) || !size { return undefined }
 | 
			
		||||
 | 
			
		||||
    numElements := len(x)
 | 
			
		||||
    if !numElements { return [] }
 | 
			
		||||
 | 
			
		||||
    res := []
 | 
			
		||||
    idx := 0
 | 
			
		||||
    for idx < numElements {
 | 
			
		||||
      res = append(res, x[idx:idx+size])
 | 
			
		||||
      idx += size
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return res
 | 
			
		||||
  },
 | 
			
		||||
  // at returns an element at the given index (if `x` is array) or
 | 
			
		||||
  // key (if `x` is map). It returns undefined if `x` is not enumerable.
 | 
			
		||||
  at: func(x, key) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    if is_array_like(x) {
 | 
			
		||||
        if !is_int(key) { return undefined }
 | 
			
		||||
    } else {
 | 
			
		||||
        if !is_string(key) { return undefined }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x[key]
 | 
			
		||||
  },
 | 
			
		||||
  // each iterates over elements of `x` and invokes `fn` for each element. `fn` is
 | 
			
		||||
  // invoked with two arguments: `key` and `value`. `key` is an int index
 | 
			
		||||
  // if `x` is array. `key` is a string key if `x` is map. It does not iterate
 | 
			
		||||
  // and returns undefined if `x` is not enumerable.
 | 
			
		||||
  each: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      fn(k, v)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // filter iterates over elements of `x`, returning an array of all elements `fn`
 | 
			
		||||
  // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
 | 
			
		||||
  // `key` is an int index if `x` is array. `key` is a string key if `x` is map.
 | 
			
		||||
  // It returns undefined if `x` is not enumerable.
 | 
			
		||||
  filter: func(x, fn) {
 | 
			
		||||
    if !is_array_like(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    dst := []
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      if fn(k, v) { dst = append(dst, v) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return dst
 | 
			
		||||
  },
 | 
			
		||||
  // find iterates over elements of `x`, returning value of the first element `fn`
 | 
			
		||||
  // returns truthy for. `fn` is invoked with two arguments: `key` and `value`.
 | 
			
		||||
  // `key` is an int index if `x` is array. `key` is a string key if `x` is map.
 | 
			
		||||
  // It returns undefined if `x` is not enumerable.
 | 
			
		||||
  find: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      if fn(k, v) { return v }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // find_key iterates over elements of `x`, returning key or index of the first
 | 
			
		||||
  // element `fn` returns truthy for. `fn` is invoked with two arguments: `key`
 | 
			
		||||
  // and `value`. `key` is an int index if `x` is array. `key` is a string key if
 | 
			
		||||
  // `x` is map. It returns undefined if `x` is not enumerable.
 | 
			
		||||
  find_key: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      if fn(k, v) { return k }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // map creates an array of values by running each element in `x` through `fn`.
 | 
			
		||||
  // `fn` is invoked with two arguments: `key` and `value`. `key` is an int index
 | 
			
		||||
  // if `x` is array. `key` is a string key if `x` is map. It returns undefined
 | 
			
		||||
  // if `x` is not enumerable.
 | 
			
		||||
  map: func(x, fn) {
 | 
			
		||||
    if !is_enumerable(x) { return undefined }
 | 
			
		||||
 | 
			
		||||
    dst := []
 | 
			
		||||
    for k, v in x {
 | 
			
		||||
      dst = append(dst, fn(k, v))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return dst
 | 
			
		||||
  },
 | 
			
		||||
  // key returns the first argument.
 | 
			
		||||
  key: func(k, _) { return k },
 | 
			
		||||
  // value returns the second argument.
 | 
			
		||||
  value: func(_, v) { return v }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/github.com/d5/tengo/stdlib/stdlib.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/d5/tengo/stdlib/stdlib.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
//go:generate go run gensrcmods.go
 | 
			
		||||
 | 
			
		||||
import "github.com/d5/tengo/objects"
 | 
			
		||||
 | 
			
		||||
// AllModuleNames returns a list of all default module names.
 | 
			
		||||
func AllModuleNames() []string {
 | 
			
		||||
	var names []string
 | 
			
		||||
	for name := range BuiltinModules {
 | 
			
		||||
		names = append(names, name)
 | 
			
		||||
	}
 | 
			
		||||
	for name := range SourceModules {
 | 
			
		||||
		names = append(names, name)
 | 
			
		||||
	}
 | 
			
		||||
	return names
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetModuleMap returns the module map that includes all modules
 | 
			
		||||
// for the given module names.
 | 
			
		||||
func GetModuleMap(names ...string) *objects.ModuleMap {
 | 
			
		||||
	modules := objects.NewModuleMap()
 | 
			
		||||
 | 
			
		||||
	for _, name := range names {
 | 
			
		||||
		if mod := BuiltinModules[name]; mod != nil {
 | 
			
		||||
			modules.AddBuiltinModule(name, mod)
 | 
			
		||||
		}
 | 
			
		||||
		if mod := SourceModules[name]; mod != "" {
 | 
			
		||||
			modules.AddSourceModule(name, []byte(mod))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return modules
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										737
									
								
								vendor/github.com/d5/tengo/stdlib/text.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										737
									
								
								vendor/github.com/d5/tengo/stdlib/text.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,737 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var textModule = map[string]objects.Object{
 | 
			
		||||
	"re_match":       &objects.UserFunction{Name: "re_match", Value: textREMatch},                           // re_match(pattern, text) => bool/error
 | 
			
		||||
	"re_find":        &objects.UserFunction{Name: "re_find", Value: textREFind},                             // re_find(pattern, text, count) => [[{text:,begin:,end:}]]/undefined
 | 
			
		||||
	"re_replace":     &objects.UserFunction{Name: "re_replace", Value: textREReplace},                       // re_replace(pattern, text, repl) => string/error
 | 
			
		||||
	"re_split":       &objects.UserFunction{Name: "re_split", Value: textRESplit},                           // re_split(pattern, text, count) => [string]/error
 | 
			
		||||
	"re_compile":     &objects.UserFunction{Name: "re_compile", Value: textRECompile},                       // re_compile(pattern) => Regexp/error
 | 
			
		||||
	"compare":        &objects.UserFunction{Name: "compare", Value: FuncASSRI(strings.Compare)},             // compare(a, b) => int
 | 
			
		||||
	"contains":       &objects.UserFunction{Name: "contains", Value: FuncASSRB(strings.Contains)},           // contains(s, substr) => bool
 | 
			
		||||
	"contains_any":   &objects.UserFunction{Name: "contains_any", Value: FuncASSRB(strings.ContainsAny)},    // contains_any(s, chars) => bool
 | 
			
		||||
	"count":          &objects.UserFunction{Name: "count", Value: FuncASSRI(strings.Count)},                 // count(s, substr) => int
 | 
			
		||||
	"equal_fold":     &objects.UserFunction{Name: "equal_fold", Value: FuncASSRB(strings.EqualFold)},        // "equal_fold(s, t) => bool
 | 
			
		||||
	"fields":         &objects.UserFunction{Name: "fields", Value: FuncASRSs(strings.Fields)},               // fields(s) => [string]
 | 
			
		||||
	"has_prefix":     &objects.UserFunction{Name: "has_prefix", Value: FuncASSRB(strings.HasPrefix)},        // has_prefix(s, prefix) => bool
 | 
			
		||||
	"has_suffix":     &objects.UserFunction{Name: "has_suffix", Value: FuncASSRB(strings.HasSuffix)},        // has_suffix(s, suffix) => bool
 | 
			
		||||
	"index":          &objects.UserFunction{Name: "index", Value: FuncASSRI(strings.Index)},                 // index(s, substr) => int
 | 
			
		||||
	"index_any":      &objects.UserFunction{Name: "index_any", Value: FuncASSRI(strings.IndexAny)},          // index_any(s, chars) => int
 | 
			
		||||
	"join":           &objects.UserFunction{Name: "join", Value: textJoin},                                  // join(arr, sep) => string
 | 
			
		||||
	"last_index":     &objects.UserFunction{Name: "last_index", Value: FuncASSRI(strings.LastIndex)},        // last_index(s, substr) => int
 | 
			
		||||
	"last_index_any": &objects.UserFunction{Name: "last_index_any", Value: FuncASSRI(strings.LastIndexAny)}, // last_index_any(s, chars) => int
 | 
			
		||||
	"repeat":         &objects.UserFunction{Name: "repeat", Value: textRepeat},                              // repeat(s, count) => string
 | 
			
		||||
	"replace":        &objects.UserFunction{Name: "replace", Value: textReplace},                            // replace(s, old, new, n) => string
 | 
			
		||||
	"split":          &objects.UserFunction{Name: "split", Value: FuncASSRSs(strings.Split)},                // split(s, sep) => [string]
 | 
			
		||||
	"split_after":    &objects.UserFunction{Name: "split_after", Value: FuncASSRSs(strings.SplitAfter)},     // split_after(s, sep) => [string]
 | 
			
		||||
	"split_after_n":  &objects.UserFunction{Name: "split_after_n", Value: FuncASSIRSs(strings.SplitAfterN)}, // split_after_n(s, sep, n) => [string]
 | 
			
		||||
	"split_n":        &objects.UserFunction{Name: "split_n", Value: FuncASSIRSs(strings.SplitN)},            // split_n(s, sep, n) => [string]
 | 
			
		||||
	"title":          &objects.UserFunction{Name: "title", Value: FuncASRS(strings.Title)},                  // title(s) => string
 | 
			
		||||
	"to_lower":       &objects.UserFunction{Name: "to_lower", Value: FuncASRS(strings.ToLower)},             // to_lower(s) => string
 | 
			
		||||
	"to_title":       &objects.UserFunction{Name: "to_title", Value: FuncASRS(strings.ToTitle)},             // to_title(s) => string
 | 
			
		||||
	"to_upper":       &objects.UserFunction{Name: "to_upper", Value: FuncASRS(strings.ToUpper)},             // to_upper(s) => string
 | 
			
		||||
	"trim_left":      &objects.UserFunction{Name: "trim_left", Value: FuncASSRS(strings.TrimLeft)},          // trim_left(s, cutset) => string
 | 
			
		||||
	"trim_prefix":    &objects.UserFunction{Name: "trim_prefix", Value: FuncASSRS(strings.TrimPrefix)},      // trim_prefix(s, prefix) => string
 | 
			
		||||
	"trim_right":     &objects.UserFunction{Name: "trim_right", Value: FuncASSRS(strings.TrimRight)},        // trim_right(s, cutset) => string
 | 
			
		||||
	"trim_space":     &objects.UserFunction{Name: "trim_space", Value: FuncASRS(strings.TrimSpace)},         // trim_space(s) => string
 | 
			
		||||
	"trim_suffix":    &objects.UserFunction{Name: "trim_suffix", Value: FuncASSRS(strings.TrimSuffix)},      // trim_suffix(s, suffix) => string
 | 
			
		||||
	"atoi":           &objects.UserFunction{Name: "atoi", Value: FuncASRIE(strconv.Atoi)},                   // atoi(str) => int/error
 | 
			
		||||
	"format_bool":    &objects.UserFunction{Name: "format_bool", Value: textFormatBool},                     // format_bool(b) => string
 | 
			
		||||
	"format_float":   &objects.UserFunction{Name: "format_float", Value: textFormatFloat},                   // format_float(f, fmt, prec, bits) => string
 | 
			
		||||
	"format_int":     &objects.UserFunction{Name: "format_int", Value: textFormatInt},                       // format_int(i, base) => string
 | 
			
		||||
	"itoa":           &objects.UserFunction{Name: "itoa", Value: FuncAIRS(strconv.Itoa)},                    // itoa(i) => string
 | 
			
		||||
	"parse_bool":     &objects.UserFunction{Name: "parse_bool", Value: textParseBool},                       // parse_bool(str) => bool/error
 | 
			
		||||
	"parse_float":    &objects.UserFunction{Name: "parse_float", Value: textParseFloat},                     // parse_float(str, bits) => float/error
 | 
			
		||||
	"parse_int":      &objects.UserFunction{Name: "parse_int", Value: textParseInt},                         // parse_int(str, base, bits) => int/error
 | 
			
		||||
	"quote":          &objects.UserFunction{Name: "quote", Value: FuncASRS(strconv.Quote)},                  // quote(str) => string
 | 
			
		||||
	"unquote":        &objects.UserFunction{Name: "unquote", Value: FuncASRSE(strconv.Unquote)},             // unquote(str) => string/error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textREMatch(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	matched, err := regexp.MatchString(s1, s2)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if matched {
 | 
			
		||||
		ret = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textREFind(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	numArgs := len(args)
 | 
			
		||||
	if numArgs != 2 && numArgs != 3 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	re, err := regexp.Compile(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if numArgs < 3 {
 | 
			
		||||
		m := re.FindStringSubmatchIndex(s2)
 | 
			
		||||
		if m == nil {
 | 
			
		||||
			ret = objects.UndefinedValue
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		arr := &objects.Array{}
 | 
			
		||||
		for i := 0; i < len(m); i += 2 {
 | 
			
		||||
			arr.Value = append(arr.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
 | 
			
		||||
				"text":  &objects.String{Value: s2[m[i]:m[i+1]]},
 | 
			
		||||
				"begin": &objects.Int{Value: int64(m[i])},
 | 
			
		||||
				"end":   &objects.Int{Value: int64(m[i+1])},
 | 
			
		||||
			}})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = &objects.Array{Value: []objects.Object{arr}}
 | 
			
		||||
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	m := re.FindAllStringSubmatchIndex(s2, i3)
 | 
			
		||||
	if m == nil {
 | 
			
		||||
		ret = objects.UndefinedValue
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arr := &objects.Array{}
 | 
			
		||||
	for _, m := range m {
 | 
			
		||||
		subMatch := &objects.Array{}
 | 
			
		||||
		for i := 0; i < len(m); i += 2 {
 | 
			
		||||
			subMatch.Value = append(subMatch.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
 | 
			
		||||
				"text":  &objects.String{Value: s2[m[i]:m[i+1]]},
 | 
			
		||||
				"begin": &objects.Int{Value: int64(m[i])},
 | 
			
		||||
				"end":   &objects.Int{Value: int64(m[i+1])},
 | 
			
		||||
			}})
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		arr.Value = append(arr.Value, subMatch)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = arr
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textREReplace(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 3 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s3, ok := objects.ToString(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	re, err := regexp.Compile(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
	} else {
 | 
			
		||||
		s, ok := doTextRegexpReplace(re, s2, s3)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return nil, objects.ErrStringLimit
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = &objects.String{Value: s}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textRESplit(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	numArgs := len(args)
 | 
			
		||||
	if numArgs != 2 && numArgs != 3 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var i3 = -1
 | 
			
		||||
	if numArgs > 2 {
 | 
			
		||||
		i3, ok = objects.ToInt(args[2])
 | 
			
		||||
		if !ok {
 | 
			
		||||
			err = objects.ErrInvalidArgumentType{
 | 
			
		||||
				Name:     "third",
 | 
			
		||||
				Expected: "int(compatible)",
 | 
			
		||||
				Found:    args[2].TypeName(),
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	re, err := regexp.Compile(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arr := &objects.Array{}
 | 
			
		||||
	for _, s := range re.Split(s2, i3) {
 | 
			
		||||
		arr.Value = append(arr.Value, &objects.String{Value: s})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = arr
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textRECompile(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	re, err := regexp.Compile(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = makeTextRegexp(re)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textReplace(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 4 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s3, ok := objects.ToString(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i4, ok := objects.ToInt(args[3])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fourth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[3].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s, ok := doTextReplace(s1, s2, s3, i4)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrStringLimit
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: s}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textRepeat(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(s1)*i2 > tengo.MaxStringLen {
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.String{Value: strings.Repeat(s1, i2)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textJoin(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		return nil, objects.ErrWrongNumArguments
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var slen int
 | 
			
		||||
	var ss1 []string
 | 
			
		||||
	switch arg0 := args[0].(type) {
 | 
			
		||||
	case *objects.Array:
 | 
			
		||||
		for idx, a := range arg0.Value {
 | 
			
		||||
			as, ok := objects.ToString(a)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     fmt.Sprintf("first[%d]", idx),
 | 
			
		||||
					Expected: "string(compatible)",
 | 
			
		||||
					Found:    a.TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			slen += len(as)
 | 
			
		||||
			ss1 = append(ss1, as)
 | 
			
		||||
		}
 | 
			
		||||
	case *objects.ImmutableArray:
 | 
			
		||||
		for idx, a := range arg0.Value {
 | 
			
		||||
			as, ok := objects.ToString(a)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
					Name:     fmt.Sprintf("first[%d]", idx),
 | 
			
		||||
					Expected: "string(compatible)",
 | 
			
		||||
					Found:    a.TypeName(),
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			slen += len(as)
 | 
			
		||||
			ss1 = append(ss1, as)
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "array",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// make sure output length does not exceed the limit
 | 
			
		||||
	if slen+len(s2)*(len(ss1)-1) > tengo.MaxStringLen {
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &objects.String{Value: strings.Join(ss1, s2)}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textFormatBool(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b1, ok := args[0].(*objects.Bool)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "bool",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b1 == objects.TrueValue {
 | 
			
		||||
		ret = &objects.String{Value: "true"}
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = &objects.String{Value: "false"}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textFormatFloat(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 4 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f1, ok := args[0].(*objects.Float)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "float",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i4, ok := objects.ToInt(args[3])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fourth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[3].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: strconv.FormatFloat(f1.Value, s2[0], i3, i4)}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textFormatInt(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := args[0].(*objects.Int)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: strconv.FormatInt(i1.Value, i2)}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textParseBool(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := args[0].(*objects.String)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parsed, err := strconv.ParseBool(s1.Value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if parsed {
 | 
			
		||||
		ret = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textParseFloat(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := args[0].(*objects.String)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parsed, err := strconv.ParseFloat(s1.Value, i2)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Float{Value: parsed}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func textParseInt(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 3 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := args[0].(*objects.String)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parsed, err := strconv.ParseInt(s1.Value, i2, i3)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: parsed}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Modified implementation of strings.Replace
 | 
			
		||||
// to limit the maximum length of output string.
 | 
			
		||||
func doTextReplace(s, old, new string, n int) (string, bool) {
 | 
			
		||||
	if old == new || n == 0 {
 | 
			
		||||
		return s, true // avoid allocation
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Compute number of replacements.
 | 
			
		||||
	if m := strings.Count(s, old); m == 0 {
 | 
			
		||||
		return s, true // avoid allocation
 | 
			
		||||
	} else if n < 0 || m < n {
 | 
			
		||||
		n = m
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Apply replacements to buffer.
 | 
			
		||||
	t := make([]byte, len(s)+n*(len(new)-len(old)))
 | 
			
		||||
	w := 0
 | 
			
		||||
	start := 0
 | 
			
		||||
	for i := 0; i < n; i++ {
 | 
			
		||||
		j := start
 | 
			
		||||
		if len(old) == 0 {
 | 
			
		||||
			if i > 0 {
 | 
			
		||||
				_, wid := utf8.DecodeRuneInString(s[start:])
 | 
			
		||||
				j += wid
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			j += strings.Index(s[start:], old)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ssj := s[start:j]
 | 
			
		||||
		if w+len(ssj)+len(new) > tengo.MaxStringLen {
 | 
			
		||||
			return "", false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		w += copy(t[w:], ssj)
 | 
			
		||||
		w += copy(t[w:], new)
 | 
			
		||||
		start = j + len(old)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ss := s[start:]
 | 
			
		||||
	if w+len(ss) > tengo.MaxStringLen {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w += copy(t[w:], ss)
 | 
			
		||||
 | 
			
		||||
	return string(t[0:w]), true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										228
									
								
								vendor/github.com/d5/tengo/stdlib/text_regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								vendor/github.com/d5/tengo/stdlib/text_regexp.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,228 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"regexp"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func makeTextRegexp(re *regexp.Regexp) *objects.ImmutableMap {
 | 
			
		||||
	return &objects.ImmutableMap{
 | 
			
		||||
		Value: map[string]objects.Object{
 | 
			
		||||
			// match(text) => bool
 | 
			
		||||
			"match": &objects.UserFunction{
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 1 {
 | 
			
		||||
						err = objects.ErrWrongNumArguments
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if re.MatchString(s1) {
 | 
			
		||||
						ret = objects.TrueValue
 | 
			
		||||
					} else {
 | 
			
		||||
						ret = objects.FalseValue
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			// find(text) 			=> array(array({text:,begin:,end:}))/undefined
 | 
			
		||||
			// find(text, maxCount) => array(array({text:,begin:,end:}))/undefined
 | 
			
		||||
			"find": &objects.UserFunction{
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					numArgs := len(args)
 | 
			
		||||
					if numArgs != 1 && numArgs != 2 {
 | 
			
		||||
						err = objects.ErrWrongNumArguments
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if numArgs == 1 {
 | 
			
		||||
						m := re.FindStringSubmatchIndex(s1)
 | 
			
		||||
						if m == nil {
 | 
			
		||||
							ret = objects.UndefinedValue
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						arr := &objects.Array{}
 | 
			
		||||
						for i := 0; i < len(m); i += 2 {
 | 
			
		||||
							arr.Value = append(arr.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
 | 
			
		||||
								"text":  &objects.String{Value: s1[m[i]:m[i+1]]},
 | 
			
		||||
								"begin": &objects.Int{Value: int64(m[i])},
 | 
			
		||||
								"end":   &objects.Int{Value: int64(m[i+1])},
 | 
			
		||||
							}})
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						ret = &objects.Array{Value: []objects.Object{arr}}
 | 
			
		||||
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					i2, ok := objects.ToInt(args[1])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "second",
 | 
			
		||||
							Expected: "int(compatible)",
 | 
			
		||||
							Found:    args[1].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
					m := re.FindAllStringSubmatchIndex(s1, i2)
 | 
			
		||||
					if m == nil {
 | 
			
		||||
						ret = objects.UndefinedValue
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					arr := &objects.Array{}
 | 
			
		||||
					for _, m := range m {
 | 
			
		||||
						subMatch := &objects.Array{}
 | 
			
		||||
						for i := 0; i < len(m); i += 2 {
 | 
			
		||||
							subMatch.Value = append(subMatch.Value, &objects.ImmutableMap{Value: map[string]objects.Object{
 | 
			
		||||
								"text":  &objects.String{Value: s1[m[i]:m[i+1]]},
 | 
			
		||||
								"begin": &objects.Int{Value: int64(m[i])},
 | 
			
		||||
								"end":   &objects.Int{Value: int64(m[i+1])},
 | 
			
		||||
							}})
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						arr.Value = append(arr.Value, subMatch)
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					ret = arr
 | 
			
		||||
 | 
			
		||||
					return
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			// replace(src, repl) => string
 | 
			
		||||
			"replace": &objects.UserFunction{
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					if len(args) != 2 {
 | 
			
		||||
						err = objects.ErrWrongNumArguments
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s2, ok := objects.ToString(args[1])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "second",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[1].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s, ok := doTextRegexpReplace(re, s1, s2)
 | 
			
		||||
					if !ok {
 | 
			
		||||
						return nil, objects.ErrStringLimit
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					ret = &objects.String{Value: s}
 | 
			
		||||
 | 
			
		||||
					return
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			// split(text) 			 => array(string)
 | 
			
		||||
			// split(text, maxCount) => array(string)
 | 
			
		||||
			"split": &objects.UserFunction{
 | 
			
		||||
				Value: func(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
					numArgs := len(args)
 | 
			
		||||
					if numArgs != 1 && numArgs != 2 {
 | 
			
		||||
						err = objects.ErrWrongNumArguments
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					s1, ok := objects.ToString(args[0])
 | 
			
		||||
					if !ok {
 | 
			
		||||
						err = objects.ErrInvalidArgumentType{
 | 
			
		||||
							Name:     "first",
 | 
			
		||||
							Expected: "string(compatible)",
 | 
			
		||||
							Found:    args[0].TypeName(),
 | 
			
		||||
						}
 | 
			
		||||
						return
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					var i2 = -1
 | 
			
		||||
					if numArgs > 1 {
 | 
			
		||||
						i2, ok = objects.ToInt(args[1])
 | 
			
		||||
						if !ok {
 | 
			
		||||
							err = objects.ErrInvalidArgumentType{
 | 
			
		||||
								Name:     "second",
 | 
			
		||||
								Expected: "int(compatible)",
 | 
			
		||||
								Found:    args[1].TypeName(),
 | 
			
		||||
							}
 | 
			
		||||
							return
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					arr := &objects.Array{}
 | 
			
		||||
					for _, s := range re.Split(s1, i2) {
 | 
			
		||||
						arr.Value = append(arr.Value, &objects.String{Value: s})
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					ret = arr
 | 
			
		||||
 | 
			
		||||
					return
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Size-limit checking implementation of regexp.ReplaceAllString.
 | 
			
		||||
func doTextRegexpReplace(re *regexp.Regexp, src, repl string) (string, bool) {
 | 
			
		||||
	idx := 0
 | 
			
		||||
	out := ""
 | 
			
		||||
 | 
			
		||||
	for _, m := range re.FindAllStringSubmatchIndex(src, -1) {
 | 
			
		||||
		var exp []byte
 | 
			
		||||
		exp = re.ExpandString(exp, repl, src, m)
 | 
			
		||||
 | 
			
		||||
		if len(out)+m[0]-idx+len(exp) > tengo.MaxStringLen {
 | 
			
		||||
			return "", false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		out += src[idx:m[0]] + string(exp)
 | 
			
		||||
		idx = m[1]
 | 
			
		||||
	}
 | 
			
		||||
	if idx < len(src) {
 | 
			
		||||
		if len(out)+len(src)-idx > tengo.MaxStringLen {
 | 
			
		||||
			return "", false
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		out += src[idx:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return string(out), true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										989
									
								
								vendor/github.com/d5/tengo/stdlib/times.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										989
									
								
								vendor/github.com/d5/tengo/stdlib/times.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,989 @@
 | 
			
		||||
package stdlib
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/d5/tengo"
 | 
			
		||||
	"github.com/d5/tengo/objects"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var timesModule = map[string]objects.Object{
 | 
			
		||||
	"format_ansic":         &objects.String{Value: time.ANSIC},
 | 
			
		||||
	"format_unix_date":     &objects.String{Value: time.UnixDate},
 | 
			
		||||
	"format_ruby_date":     &objects.String{Value: time.RubyDate},
 | 
			
		||||
	"format_rfc822":        &objects.String{Value: time.RFC822},
 | 
			
		||||
	"format_rfc822z":       &objects.String{Value: time.RFC822Z},
 | 
			
		||||
	"format_rfc850":        &objects.String{Value: time.RFC850},
 | 
			
		||||
	"format_rfc1123":       &objects.String{Value: time.RFC1123},
 | 
			
		||||
	"format_rfc1123z":      &objects.String{Value: time.RFC1123Z},
 | 
			
		||||
	"format_rfc3339":       &objects.String{Value: time.RFC3339},
 | 
			
		||||
	"format_rfc3339_nano":  &objects.String{Value: time.RFC3339Nano},
 | 
			
		||||
	"format_kitchen":       &objects.String{Value: time.Kitchen},
 | 
			
		||||
	"format_stamp":         &objects.String{Value: time.Stamp},
 | 
			
		||||
	"format_stamp_milli":   &objects.String{Value: time.StampMilli},
 | 
			
		||||
	"format_stamp_micro":   &objects.String{Value: time.StampMicro},
 | 
			
		||||
	"format_stamp_nano":    &objects.String{Value: time.StampNano},
 | 
			
		||||
	"nanosecond":           &objects.Int{Value: int64(time.Nanosecond)},
 | 
			
		||||
	"microsecond":          &objects.Int{Value: int64(time.Microsecond)},
 | 
			
		||||
	"millisecond":          &objects.Int{Value: int64(time.Millisecond)},
 | 
			
		||||
	"second":               &objects.Int{Value: int64(time.Second)},
 | 
			
		||||
	"minute":               &objects.Int{Value: int64(time.Minute)},
 | 
			
		||||
	"hour":                 &objects.Int{Value: int64(time.Hour)},
 | 
			
		||||
	"january":              &objects.Int{Value: int64(time.January)},
 | 
			
		||||
	"february":             &objects.Int{Value: int64(time.February)},
 | 
			
		||||
	"march":                &objects.Int{Value: int64(time.March)},
 | 
			
		||||
	"april":                &objects.Int{Value: int64(time.April)},
 | 
			
		||||
	"may":                  &objects.Int{Value: int64(time.May)},
 | 
			
		||||
	"june":                 &objects.Int{Value: int64(time.June)},
 | 
			
		||||
	"july":                 &objects.Int{Value: int64(time.July)},
 | 
			
		||||
	"august":               &objects.Int{Value: int64(time.August)},
 | 
			
		||||
	"september":            &objects.Int{Value: int64(time.September)},
 | 
			
		||||
	"october":              &objects.Int{Value: int64(time.October)},
 | 
			
		||||
	"november":             &objects.Int{Value: int64(time.November)},
 | 
			
		||||
	"december":             &objects.Int{Value: int64(time.December)},
 | 
			
		||||
	"sleep":                &objects.UserFunction{Name: "sleep", Value: timesSleep},                              // sleep(int)
 | 
			
		||||
	"parse_duration":       &objects.UserFunction{Name: "parse_duration", Value: timesParseDuration},             // parse_duration(str) => int
 | 
			
		||||
	"since":                &objects.UserFunction{Name: "since", Value: timesSince},                              // since(time) => int
 | 
			
		||||
	"until":                &objects.UserFunction{Name: "until", Value: timesUntil},                              // until(time) => int
 | 
			
		||||
	"duration_hours":       &objects.UserFunction{Name: "duration_hours", Value: timesDurationHours},             // duration_hours(int) => float
 | 
			
		||||
	"duration_minutes":     &objects.UserFunction{Name: "duration_minutes", Value: timesDurationMinutes},         // duration_minutes(int) => float
 | 
			
		||||
	"duration_nanoseconds": &objects.UserFunction{Name: "duration_nanoseconds", Value: timesDurationNanoseconds}, // duration_nanoseconds(int) => int
 | 
			
		||||
	"duration_seconds":     &objects.UserFunction{Name: "duration_seconds", Value: timesDurationSeconds},         // duration_seconds(int) => float
 | 
			
		||||
	"duration_string":      &objects.UserFunction{Name: "duration_string", Value: timesDurationString},           // duration_string(int) => string
 | 
			
		||||
	"month_string":         &objects.UserFunction{Name: "month_string", Value: timesMonthString},                 // month_string(int) => string
 | 
			
		||||
	"date":                 &objects.UserFunction{Name: "date", Value: timesDate},                                // date(year, month, day, hour, min, sec, nsec) => time
 | 
			
		||||
	"now":                  &objects.UserFunction{Name: "now", Value: timesNow},                                  // now() => time
 | 
			
		||||
	"parse":                &objects.UserFunction{Name: "parse", Value: timesParse},                              // parse(format, str) => time
 | 
			
		||||
	"unix":                 &objects.UserFunction{Name: "unix", Value: timesUnix},                                // unix(sec, nsec) => time
 | 
			
		||||
	"add":                  &objects.UserFunction{Name: "add", Value: timesAdd},                                  // add(time, int) => time
 | 
			
		||||
	"add_date":             &objects.UserFunction{Name: "add_date", Value: timesAddDate},                         // add_date(time, years, months, days) => time
 | 
			
		||||
	"sub":                  &objects.UserFunction{Name: "sub", Value: timesSub},                                  // sub(t time, u time) => int
 | 
			
		||||
	"after":                &objects.UserFunction{Name: "after", Value: timesAfter},                              // after(t time, u time) => bool
 | 
			
		||||
	"before":               &objects.UserFunction{Name: "before", Value: timesBefore},                            // before(t time, u time) => bool
 | 
			
		||||
	"time_year":            &objects.UserFunction{Name: "time_year", Value: timesTimeYear},                       // time_year(time) => int
 | 
			
		||||
	"time_month":           &objects.UserFunction{Name: "time_month", Value: timesTimeMonth},                     // time_month(time) => int
 | 
			
		||||
	"time_day":             &objects.UserFunction{Name: "time_day", Value: timesTimeDay},                         // time_day(time) => int
 | 
			
		||||
	"time_weekday":         &objects.UserFunction{Name: "time_weekday", Value: timesTimeWeekday},                 // time_weekday(time) => int
 | 
			
		||||
	"time_hour":            &objects.UserFunction{Name: "time_hour", Value: timesTimeHour},                       // time_hour(time) => int
 | 
			
		||||
	"time_minute":          &objects.UserFunction{Name: "time_minute", Value: timesTimeMinute},                   // time_minute(time) => int
 | 
			
		||||
	"time_second":          &objects.UserFunction{Name: "time_second", Value: timesTimeSecond},                   // time_second(time) => int
 | 
			
		||||
	"time_nanosecond":      &objects.UserFunction{Name: "time_nanosecond", Value: timesTimeNanosecond},           // time_nanosecond(time) => int
 | 
			
		||||
	"time_unix":            &objects.UserFunction{Name: "time_unix", Value: timesTimeUnix},                       // time_unix(time) => int
 | 
			
		||||
	"time_unix_nano":       &objects.UserFunction{Name: "time_unix_nano", Value: timesTimeUnixNano},              // time_unix_nano(time) => int
 | 
			
		||||
	"time_format":          &objects.UserFunction{Name: "time_format", Value: timesTimeFormat},                   // time_format(time, format) => string
 | 
			
		||||
	"time_location":        &objects.UserFunction{Name: "time_location", Value: timesTimeLocation},               // time_location(time) => string
 | 
			
		||||
	"time_string":          &objects.UserFunction{Name: "time_string", Value: timesTimeString},                   // time_string(time) => string
 | 
			
		||||
	"is_zero":              &objects.UserFunction{Name: "is_zero", Value: timesIsZero},                           // is_zero(time) => bool
 | 
			
		||||
	"to_local":             &objects.UserFunction{Name: "to_local", Value: timesToLocal},                         // to_local(time) => time
 | 
			
		||||
	"to_utc":               &objects.UserFunction{Name: "to_utc", Value: timesToUTC},                             // to_utc(time) => time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesSleep(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	time.Sleep(time.Duration(i1))
 | 
			
		||||
	ret = objects.UndefinedValue
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesParseDuration(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dur, err := time.ParseDuration(s1)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(dur)}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesSince(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(time.Since(t1))}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesUntil(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(time.Until(t1))}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDurationHours(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Float{Value: time.Duration(i1).Hours()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDurationMinutes(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Float{Value: time.Duration(i1).Minutes()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDurationNanoseconds(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: time.Duration(i1).Nanoseconds()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDurationSeconds(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Float{Value: time.Duration(i1).Seconds()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDurationString(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: time.Duration(i1).String()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesMonthString(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: time.Month(i1).String()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesDate(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 7 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i4, ok := objects.ToInt(args[3])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fourth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[3].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i5, ok := objects.ToInt(args[4])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fifth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[4].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i6, ok := objects.ToInt(args[5])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "sixth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[5].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	i7, ok := objects.ToInt(args[6])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "seventh",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[6].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: time.Date(i1, time.Month(i2), i3, i4, i5, i6, i7, time.Now().Location())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesNow(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 0 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: time.Now()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesParse(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s1, ok := objects.ToString(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parsed, err := time.Parse(s1, s2)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ret = wrapError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: parsed}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesUnix(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i1, ok := objects.ToInt64(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt64(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: time.Unix(i1, i2)}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesAdd(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt64(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: t1.Add(time.Duration(i2))}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesSub(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t2, ok := objects.ToTime(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Sub(t2))}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesAddDate(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 4 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i2, ok := objects.ToInt(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i3, ok := objects.ToInt(args[2])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "third",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[2].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i4, ok := objects.ToInt(args[3])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "fourth",
 | 
			
		||||
			Expected: "int(compatible)",
 | 
			
		||||
			Found:    args[3].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: t1.AddDate(i2, i3, i4)}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesAfter(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t2, ok := objects.ToTime(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t1.After(t2) {
 | 
			
		||||
		ret = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesBefore(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t2, ok := objects.ToTime(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t1.Before(t2) {
 | 
			
		||||
		ret = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeYear(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Year())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeMonth(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Month())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeDay(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Day())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeWeekday(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Weekday())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeHour(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Hour())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeMinute(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Minute())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeSecond(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Second())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeNanosecond(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Nanosecond())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeUnix(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.Unix())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeUnixNano(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Int{Value: int64(t1.UnixNano())}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeFormat(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 2 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s2, ok := objects.ToString(args[1])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "second",
 | 
			
		||||
			Expected: "string(compatible)",
 | 
			
		||||
			Found:    args[1].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s := t1.Format(s2)
 | 
			
		||||
	if len(s) > tengo.MaxStringLen {
 | 
			
		||||
 | 
			
		||||
		return nil, objects.ErrStringLimit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: s}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesIsZero(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t1.IsZero() {
 | 
			
		||||
		ret = objects.TrueValue
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = objects.FalseValue
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesToLocal(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: t1.Local()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesToUTC(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.Time{Value: t1.UTC()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeLocation(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: t1.Location().String()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timesTimeString(args ...objects.Object) (ret objects.Object, err error) {
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		err = objects.ErrWrongNumArguments
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t1, ok := objects.ToTime(args[0])
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = objects.ErrInvalidArgumentType{
 | 
			
		||||
			Name:     "first",
 | 
			
		||||
			Expected: "time(compatible)",
 | 
			
		||||
			Found:    args[0].TypeName(),
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = &objects.String{Value: t1.String()}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -17,14 +17,16 @@ github.com/Philipp15b/go-steam/rwu
 | 
			
		||||
github.com/Philipp15b/go-steam/socialcache
 | 
			
		||||
# github.com/bwmarrin/discordgo v0.19.0
 | 
			
		||||
github.com/bwmarrin/discordgo
 | 
			
		||||
# github.com/d5/tengo v1.12.1
 | 
			
		||||
# github.com/d5/tengo v1.20.0
 | 
			
		||||
github.com/d5/tengo/script
 | 
			
		||||
github.com/d5/tengo/stdlib
 | 
			
		||||
github.com/d5/tengo/compiler
 | 
			
		||||
github.com/d5/tengo/compiler/parser
 | 
			
		||||
github.com/d5/tengo/compiler/source
 | 
			
		||||
github.com/d5/tengo/objects
 | 
			
		||||
github.com/d5/tengo/runtime
 | 
			
		||||
github.com/d5/tengo
 | 
			
		||||
github.com/d5/tengo/stdlib/json
 | 
			
		||||
github.com/d5/tengo/compiler/ast
 | 
			
		||||
github.com/d5/tengo/compiler/token
 | 
			
		||||
github.com/d5/tengo/compiler/scanner
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user