bsc/vendor/github.com/robertkrimen/otto/cmpl_evaluate_statement.go
Péter Szilágyi 289b30715d Godeps, vendor: convert dependency management to trash (#3198)
This commit converts the dependency management from Godeps to the vendor
folder, also switching the tool from godep to trash. Since the upstream tool
lacks a few features proposed via a few PRs, until those PRs are merged in
(if), use github.com/karalabe/trash.

You can update dependencies via trash --update.

All dependencies have been updated to their latest version.

Parts of the build system are reworked to drop old notions of Godeps and
invocation of the go vet command so that it doesn't run against the vendor
folder, as that will just blow up during vetting.

The conversion drops OpenCL (and hence GPU mining support) from ethash and our
codebase. The short reasoning is that there's noone to maintain and having
opencl libs in our deps messes up builds as go install ./... tries to build
them, failing with unsatisfied link errors for the C OpenCL deps.

golang.org/x/net/context is not vendored in. We expect it to be fetched by the
user (i.e. using go get). To keep ci.go builds reproducible the package is
"vendored" in build/_vendor.
2016-10-28 19:05:01 +02:00

425 lines
10 KiB
Go

package otto
import (
"fmt"
"runtime"
"github.com/robertkrimen/otto/token"
)
func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value {
// Allow interpreter interruption
// If the Interrupt channel is nil, then
// we avoid runtime.Gosched() overhead (if any)
// FIXME: Test this
if self.otto.Interrupt != nil {
runtime.Gosched()
select {
case value := <-self.otto.Interrupt:
value()
default:
}
}
switch node := node.(type) {
case *_nodeBlockStatement:
labels := self.labels
self.labels = nil
value := self.cmpl_evaluate_nodeStatementList(node.list)
switch value.kind {
case valueResult:
switch value.evaluateBreak(labels) {
case resultBreak:
return emptyValue
}
}
return value
case *_nodeBranchStatement:
target := node.label
switch node.branch { // FIXME Maybe node.kind? node.operator?
case token.BREAK:
return toValue(newBreakResult(target))
case token.CONTINUE:
return toValue(newContinueResult(target))
}
case *_nodeDebuggerStatement:
if self.debugger != nil {
self.debugger(self.otto)
}
return emptyValue // Nothing happens.
case *_nodeDoWhileStatement:
return self.cmpl_evaluate_nodeDoWhileStatement(node)
case *_nodeEmptyStatement:
return emptyValue
case *_nodeExpressionStatement:
return self.cmpl_evaluate_nodeExpression(node.expression)
case *_nodeForInStatement:
return self.cmpl_evaluate_nodeForInStatement(node)
case *_nodeForStatement:
return self.cmpl_evaluate_nodeForStatement(node)
case *_nodeIfStatement:
return self.cmpl_evaluate_nodeIfStatement(node)
case *_nodeLabelledStatement:
self.labels = append(self.labels, node.label)
defer func() {
if len(self.labels) > 0 {
self.labels = self.labels[:len(self.labels)-1] // Pop the label
} else {
self.labels = nil
}
}()
return self.cmpl_evaluate_nodeStatement(node.statement)
case *_nodeReturnStatement:
if node.argument != nil {
return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve()))
}
return toValue(newReturnResult(Value{}))
case *_nodeSwitchStatement:
return self.cmpl_evaluate_nodeSwitchStatement(node)
case *_nodeThrowStatement:
value := self.cmpl_evaluate_nodeExpression(node.argument).resolve()
panic(newException(value))
case *_nodeTryStatement:
return self.cmpl_evaluate_nodeTryStatement(node)
case *_nodeVariableStatement:
// Variables are already defined, this is initialization only
for _, variable := range node.list {
self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression))
}
return emptyValue
case *_nodeWhileStatement:
return self.cmpl_evaluate_nodeWhileStatement(node)
case *_nodeWithStatement:
return self.cmpl_evaluate_nodeWithStatement(node)
}
panic(fmt.Errorf("Here be dragons: evaluate_nodeStatement(%T)", node))
}
func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value {
var result Value
for _, node := range list {
value := self.cmpl_evaluate_nodeStatement(node)
switch value.kind {
case valueResult:
return value
case valueEmpty:
default:
// We have getValue here to (for example) trigger a
// ReferenceError (of the not defined variety)
// Not sure if this is the best way to error out early
// for such errors or if there is a better way
// TODO Do we still need this?
result = value.resolve()
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value {
labels := append(self.labels, "")
self.labels = nil
test := node.test
result := emptyValue
resultBreak:
for {
for _, node := range node.body {
value := self.cmpl_evaluate_nodeStatement(node)
switch value.kind {
case valueResult:
switch value.evaluateBreakContinue(labels) {
case resultReturn:
return value
case resultBreak:
break resultBreak
case resultContinue:
goto resultContinue
}
case valueEmpty:
default:
result = value
}
}
resultContinue:
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
// Stahp: do ... while (false)
break
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value {
labels := append(self.labels, "")
self.labels = nil
source := self.cmpl_evaluate_nodeExpression(node.source)
sourceValue := source.resolve()
switch sourceValue.kind {
case valueUndefined, valueNull:
return emptyValue
}
sourceObject := self.toObject(sourceValue)
into := node.into
body := node.body
result := emptyValue
object := sourceObject
for object != nil {
enumerateValue := emptyValue
object.enumerate(false, func(name string) bool {
into := self.cmpl_evaluate_nodeExpression(into)
// In the case of: for (var abc in def) ...
if into.reference() == nil {
identifier := into.string()
// TODO Should be true or false (strictness) depending on context
into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1))
}
self.putValue(into.reference(), toValue_string(name))
for _, node := range body {
value := self.cmpl_evaluate_nodeStatement(node)
switch value.kind {
case valueResult:
switch value.evaluateBreakContinue(labels) {
case resultReturn:
enumerateValue = value
return false
case resultBreak:
object = nil
return false
case resultContinue:
return true
}
case valueEmpty:
default:
enumerateValue = value
}
}
return true
})
if object == nil {
break
}
object = object.prototype
if !enumerateValue.isEmpty() {
result = enumerateValue
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value {
labels := append(self.labels, "")
self.labels = nil
initializer := node.initializer
test := node.test
update := node.update
body := node.body
if initializer != nil {
initialResult := self.cmpl_evaluate_nodeExpression(initializer)
initialResult.resolve() // Side-effect trigger
}
result := emptyValue
resultBreak:
for {
if test != nil {
testResult := self.cmpl_evaluate_nodeExpression(test)
testResultValue := testResult.resolve()
if testResultValue.bool() == false {
break
}
}
for _, node := range body {
value := self.cmpl_evaluate_nodeStatement(node)
switch value.kind {
case valueResult:
switch value.evaluateBreakContinue(labels) {
case resultReturn:
return value
case resultBreak:
break resultBreak
case resultContinue:
goto resultContinue
}
case valueEmpty:
default:
result = value
}
}
resultContinue:
if update != nil {
updateResult := self.cmpl_evaluate_nodeExpression(update)
updateResult.resolve() // Side-effect trigger
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value {
test := self.cmpl_evaluate_nodeExpression(node.test)
testValue := test.resolve()
if testValue.bool() {
return self.cmpl_evaluate_nodeStatement(node.consequent)
} else if node.alternate != nil {
return self.cmpl_evaluate_nodeStatement(node.alternate)
}
return emptyValue
}
func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value {
labels := append(self.labels, "")
self.labels = nil
discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant)
target := node.default_
for index, clause := range node.body {
test := clause.test
if test != nil {
if self.calculateComparison(token.STRICT_EQUAL, discriminantResult, self.cmpl_evaluate_nodeExpression(test)) {
target = index
break
}
}
}
result := emptyValue
if target != -1 {
for _, clause := range node.body[target:] {
for _, statement := range clause.consequent {
value := self.cmpl_evaluate_nodeStatement(statement)
switch value.kind {
case valueResult:
switch value.evaluateBreak(labels) {
case resultReturn:
return value
case resultBreak:
return emptyValue
}
case valueEmpty:
default:
result = value
}
}
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value {
tryCatchValue, exception := self.tryCatchEvaluate(func() Value {
return self.cmpl_evaluate_nodeStatement(node.body)
})
if exception && node.catch != nil {
outer := self.scope.lexical
self.scope.lexical = self.newDeclarationStash(outer)
defer func() {
self.scope.lexical = outer
}()
// TODO If necessary, convert TypeError<runtime> => TypeError
// That, is, such errors can be thrown despite not being JavaScript "native"
// strict = false
self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false)
// FIXME node.CatchParameter
// FIXME node.Catch
tryCatchValue, exception = self.tryCatchEvaluate(func() Value {
return self.cmpl_evaluate_nodeStatement(node.catch.body)
})
}
if node.finally != nil {
finallyValue := self.cmpl_evaluate_nodeStatement(node.finally)
if finallyValue.kind == valueResult {
return finallyValue
}
}
if exception {
panic(newException(tryCatchValue))
}
return tryCatchValue
}
func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value {
test := node.test
body := node.body
labels := append(self.labels, "")
self.labels = nil
result := emptyValue
resultBreakContinue:
for {
if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() {
// Stahp: while (false) ...
break
}
for _, node := range body {
value := self.cmpl_evaluate_nodeStatement(node)
switch value.kind {
case valueResult:
switch value.evaluateBreakContinue(labels) {
case resultReturn:
return value
case resultBreak:
break resultBreakContinue
case resultContinue:
continue resultBreakContinue
}
case valueEmpty:
default:
result = value
}
}
}
return result
}
func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value {
object := self.cmpl_evaluate_nodeExpression(node.object)
outer := self.scope.lexical
lexical := self.newObjectStash(self.toObject(object.resolve()), outer)
self.scope.lexical = lexical
defer func() {
self.scope.lexical = outer
}()
return self.cmpl_evaluate_nodeStatement(node.body)
}