1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-26 20:28:49 +08:00

Implement return/break/continue without panic/recover

This fixes #25
This commit is contained in:
Robert Krimen
2013-06-10 18:55:39 -07:00
parent 42d674a81b
commit 73bf2f9fa8
19 changed files with 363 additions and 311 deletions

View File

@@ -18,6 +18,7 @@ const (
valueString
valueBoolean
valueObject
valueResult
valueReference
)
@@ -89,6 +90,10 @@ func (value Value) isCallable() bool {
return false
}
func (value Value) isResult() bool {
return value._valueType == valueResult
}
func (value Value) isReference() bool {
return value._valueType == valueReference
}
@@ -310,6 +315,8 @@ func toValue(value interface{}) Value {
return Value{valueObject, value.object}
case _reference: // reference is an interface (already a pointer)
return Value{valueReference, value}
case _result:
return Value{valueResult, value}
case nil:
// TODO Ugh.
return UndefinedValue()
@@ -371,6 +378,10 @@ func (value Value) toBoolean() bool {
return toBoolean(value)
}
func (value Value) isTrue() bool {
return toBoolean(value)
}
// ToBoolean will convert the value to a boolean (bool).
//
// ToValue(0).ToBoolean() => false
@@ -644,8 +655,9 @@ func (self Value) export() interface{} {
} else {
result := make(map[string]interface{})
// TODO Should we export everything? Or just what is enumerable?
object.enumerate(false, func(name string) {
object.enumerate(false, func(name string) bool {
result[name] = object.get(name).export()
return true
})
return result
}
@@ -654,6 +666,32 @@ func (self Value) export() interface{} {
return self
}
func (self Value) evaluateBreakContinue(labelSet _labelSet) _resultKind {
if result, valid := self.value.(_result); valid {
switch result.kind {
case resultBreak, resultContinue:
if labelSet[result.target] {
return result.kind
}
}
return resultReturn
}
return resultNormal
}
func (self Value) evaluateBreak(labelSet _labelSet) _resultKind {
if result, valid := self.value.(_result); valid {
switch result.kind {
case resultBreak:
if labelSet[result.target] {
return result.kind
}
}
return resultReturn
}
return resultNormal
}
func (self Value) exportNative() interface{} {
switch self._valueType {