cmpl_evaluate_expression.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. package otto
  2. import (
  3. "fmt"
  4. "math"
  5. "runtime"
  6. "github.com/robertkrimen/otto/token"
  7. )
  8. func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value {
  9. // Allow interpreter interruption
  10. // If the Interrupt channel is nil, then
  11. // we avoid runtime.Gosched() overhead (if any)
  12. // FIXME: Test this
  13. if self.otto.Interrupt != nil {
  14. runtime.Gosched()
  15. select {
  16. case value := <-self.otto.Interrupt:
  17. value()
  18. default:
  19. }
  20. }
  21. switch node := node.(type) {
  22. case *_nodeArrayLiteral:
  23. return self.cmpl_evaluate_nodeArrayLiteral(node)
  24. case *_nodeAssignExpression:
  25. return self.cmpl_evaluate_nodeAssignExpression(node)
  26. case *_nodeBinaryExpression:
  27. if node.comparison {
  28. return self.cmpl_evaluate_nodeBinaryExpression_comparison(node)
  29. } else {
  30. return self.cmpl_evaluate_nodeBinaryExpression(node)
  31. }
  32. case *_nodeBracketExpression:
  33. return self.cmpl_evaluate_nodeBracketExpression(node)
  34. case *_nodeCallExpression:
  35. return self.cmpl_evaluate_nodeCallExpression(node, nil)
  36. case *_nodeConditionalExpression:
  37. return self.cmpl_evaluate_nodeConditionalExpression(node)
  38. case *_nodeDotExpression:
  39. return self.cmpl_evaluate_nodeDotExpression(node)
  40. case *_nodeFunctionLiteral:
  41. var local = self.scope.lexical
  42. if node.name != "" {
  43. local = self.newDeclarationStash(local)
  44. }
  45. value := toValue_object(self.newNodeFunction(node, local))
  46. if node.name != "" {
  47. local.createBinding(node.name, false, value)
  48. }
  49. return value
  50. case *_nodeIdentifier:
  51. name := node.name
  52. // TODO Should be true or false (strictness) depending on context
  53. // getIdentifierReference should not return nil, but we check anyway and panic
  54. // so as not to propagate the nil into something else
  55. reference := getIdentifierReference(self, self.scope.lexical, name, false, _at(node.idx))
  56. if reference == nil {
  57. // Should never get here!
  58. panic(hereBeDragons("referenceError == nil: " + name))
  59. }
  60. return toValue(reference)
  61. case *_nodeLiteral:
  62. return node.value
  63. case *_nodeNewExpression:
  64. return self.cmpl_evaluate_nodeNewExpression(node)
  65. case *_nodeObjectLiteral:
  66. return self.cmpl_evaluate_nodeObjectLiteral(node)
  67. case *_nodeRegExpLiteral:
  68. return toValue_object(self._newRegExp(node.pattern, node.flags))
  69. case *_nodeSequenceExpression:
  70. return self.cmpl_evaluate_nodeSequenceExpression(node)
  71. case *_nodeThisExpression:
  72. return toValue_object(self.scope.this)
  73. case *_nodeUnaryExpression:
  74. return self.cmpl_evaluate_nodeUnaryExpression(node)
  75. case *_nodeVariableExpression:
  76. return self.cmpl_evaluate_nodeVariableExpression(node)
  77. }
  78. panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node))
  79. }
  80. func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value {
  81. valueArray := []Value{}
  82. for _, node := range node.value {
  83. if node == nil {
  84. valueArray = append(valueArray, emptyValue)
  85. } else {
  86. valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve())
  87. }
  88. }
  89. result := self.newArrayOf(valueArray)
  90. return toValue_object(result)
  91. }
  92. func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpression) Value {
  93. left := self.cmpl_evaluate_nodeExpression(node.left)
  94. right := self.cmpl_evaluate_nodeExpression(node.right)
  95. rightValue := right.resolve()
  96. result := rightValue
  97. if node.operator != token.ASSIGN {
  98. result = self.calculateBinaryExpression(node.operator, left, rightValue)
  99. }
  100. self.putValue(left.reference(), result)
  101. return result
  102. }
  103. func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value {
  104. left := self.cmpl_evaluate_nodeExpression(node.left)
  105. leftValue := left.resolve()
  106. switch node.operator {
  107. // Logical
  108. case token.LOGICAL_AND:
  109. if !leftValue.bool() {
  110. return leftValue
  111. }
  112. right := self.cmpl_evaluate_nodeExpression(node.right)
  113. return right.resolve()
  114. case token.LOGICAL_OR:
  115. if leftValue.bool() {
  116. return leftValue
  117. }
  118. right := self.cmpl_evaluate_nodeExpression(node.right)
  119. return right.resolve()
  120. }
  121. return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right))
  122. }
  123. func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value {
  124. left := self.cmpl_evaluate_nodeExpression(node.left).resolve()
  125. right := self.cmpl_evaluate_nodeExpression(node.right).resolve()
  126. return toValue_bool(self.calculateComparison(node.operator, left, right))
  127. }
  128. func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value {
  129. target := self.cmpl_evaluate_nodeExpression(node.left)
  130. targetValue := target.resolve()
  131. member := self.cmpl_evaluate_nodeExpression(node.member)
  132. memberValue := member.resolve()
  133. // TODO Pass in base value as-is, and defer toObject till later?
  134. object, err := self.objectCoerce(targetValue)
  135. if err != nil {
  136. panic(self.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), _at(node.idx)))
  137. }
  138. return toValue(newPropertyReference(self, object, memberValue.string(), false, _at(node.idx)))
  139. }
  140. func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value {
  141. rt := self
  142. this := Value{}
  143. callee := self.cmpl_evaluate_nodeExpression(node.callee)
  144. argumentList := []Value{}
  145. if withArgumentList != nil {
  146. argumentList = self.toValueArray(withArgumentList...)
  147. } else {
  148. for _, argumentNode := range node.argumentList {
  149. argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve())
  150. }
  151. }
  152. rf := callee.reference()
  153. vl := callee.resolve()
  154. eval := false // Whether this call is a (candidate for) direct call to eval
  155. name := ""
  156. if rf != nil {
  157. switch rf := rf.(type) {
  158. case *_propertyReference:
  159. name = rf.name
  160. object := rf.base
  161. this = toValue_object(object)
  162. eval = rf.name == "eval" // Possible direct eval
  163. case *_stashReference:
  164. // TODO ImplicitThisValue
  165. name = rf.name
  166. eval = rf.name == "eval" // Possible direct eval
  167. default:
  168. // FIXME?
  169. panic(rt.panicTypeError("Here be dragons"))
  170. }
  171. }
  172. at := _at(-1)
  173. switch callee := node.callee.(type) {
  174. case *_nodeIdentifier:
  175. at = _at(callee.idx)
  176. case *_nodeDotExpression:
  177. at = _at(callee.idx)
  178. case *_nodeBracketExpression:
  179. at = _at(callee.idx)
  180. }
  181. frame := _frame{
  182. callee: name,
  183. file: self.scope.frame.file,
  184. }
  185. if !vl.IsFunction() {
  186. if name == "" {
  187. // FIXME Maybe typeof?
  188. panic(rt.panicTypeError("%v is not a function", vl, at))
  189. }
  190. panic(rt.panicTypeError("'%s' is not a function", name, at))
  191. }
  192. self.scope.frame.offset = int(at)
  193. return vl._object().call(this, argumentList, eval, frame)
  194. }
  195. func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value {
  196. test := self.cmpl_evaluate_nodeExpression(node.test)
  197. testValue := test.resolve()
  198. if testValue.bool() {
  199. return self.cmpl_evaluate_nodeExpression(node.consequent)
  200. }
  201. return self.cmpl_evaluate_nodeExpression(node.alternate)
  202. }
  203. func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value {
  204. target := self.cmpl_evaluate_nodeExpression(node.left)
  205. targetValue := target.resolve()
  206. // TODO Pass in base value as-is, and defer toObject till later?
  207. object, err := self.objectCoerce(targetValue)
  208. if err != nil {
  209. panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), _at(node.idx)))
  210. }
  211. return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx)))
  212. }
  213. func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value {
  214. rt := self
  215. callee := self.cmpl_evaluate_nodeExpression(node.callee)
  216. argumentList := []Value{}
  217. for _, argumentNode := range node.argumentList {
  218. argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve())
  219. }
  220. rf := callee.reference()
  221. vl := callee.resolve()
  222. name := ""
  223. if rf != nil {
  224. switch rf := rf.(type) {
  225. case *_propertyReference:
  226. name = rf.name
  227. case *_stashReference:
  228. name = rf.name
  229. default:
  230. panic(rt.panicTypeError("Here be dragons"))
  231. }
  232. }
  233. at := _at(-1)
  234. switch callee := node.callee.(type) {
  235. case *_nodeIdentifier:
  236. at = _at(callee.idx)
  237. case *_nodeDotExpression:
  238. at = _at(callee.idx)
  239. case *_nodeBracketExpression:
  240. at = _at(callee.idx)
  241. }
  242. if !vl.IsFunction() {
  243. if name == "" {
  244. // FIXME Maybe typeof?
  245. panic(rt.panicTypeError("%v is not a function", vl, at))
  246. }
  247. panic(rt.panicTypeError("'%s' is not a function", name, at))
  248. }
  249. self.scope.frame.offset = int(at)
  250. return vl._object().construct(argumentList)
  251. }
  252. func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value {
  253. result := self.newObject()
  254. for _, property := range node.value {
  255. switch property.kind {
  256. case "value":
  257. result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false)
  258. case "get":
  259. getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
  260. descriptor := _property{}
  261. descriptor.mode = 0211
  262. descriptor.value = _propertyGetSet{getter, nil}
  263. result.defineOwnProperty(property.key, descriptor, false)
  264. case "set":
  265. setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical)
  266. descriptor := _property{}
  267. descriptor.mode = 0211
  268. descriptor.value = _propertyGetSet{nil, setter}
  269. result.defineOwnProperty(property.key, descriptor, false)
  270. default:
  271. panic(fmt.Errorf("Here be dragons: evaluate_nodeObjectLiteral: invalid property.Kind: %v", property.kind))
  272. }
  273. }
  274. return toValue_object(result)
  275. }
  276. func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceExpression) Value {
  277. var result Value
  278. for _, node := range node.sequence {
  279. result = self.cmpl_evaluate_nodeExpression(node)
  280. result = result.resolve()
  281. }
  282. return result
  283. }
  284. func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value {
  285. target := self.cmpl_evaluate_nodeExpression(node.operand)
  286. switch node.operator {
  287. case token.TYPEOF, token.DELETE:
  288. if target.kind == valueReference && target.reference().invalid() {
  289. if node.operator == token.TYPEOF {
  290. return toValue_string("undefined")
  291. }
  292. return trueValue
  293. }
  294. }
  295. switch node.operator {
  296. case token.NOT:
  297. targetValue := target.resolve()
  298. if targetValue.bool() {
  299. return falseValue
  300. }
  301. return trueValue
  302. case token.BITWISE_NOT:
  303. targetValue := target.resolve()
  304. integerValue := toInt32(targetValue)
  305. return toValue_int32(^integerValue)
  306. case token.PLUS:
  307. targetValue := target.resolve()
  308. return toValue_float64(targetValue.float64())
  309. case token.MINUS:
  310. targetValue := target.resolve()
  311. value := targetValue.float64()
  312. // TODO Test this
  313. sign := float64(-1)
  314. if math.Signbit(value) {
  315. sign = 1
  316. }
  317. return toValue_float64(math.Copysign(value, sign))
  318. case token.INCREMENT:
  319. targetValue := target.resolve()
  320. if node.postfix {
  321. // Postfix++
  322. oldValue := targetValue.float64()
  323. newValue := toValue_float64(+1 + oldValue)
  324. self.putValue(target.reference(), newValue)
  325. return toValue_float64(oldValue)
  326. } else {
  327. // ++Prefix
  328. newValue := toValue_float64(+1 + targetValue.float64())
  329. self.putValue(target.reference(), newValue)
  330. return newValue
  331. }
  332. case token.DECREMENT:
  333. targetValue := target.resolve()
  334. if node.postfix {
  335. // Postfix--
  336. oldValue := targetValue.float64()
  337. newValue := toValue_float64(-1 + oldValue)
  338. self.putValue(target.reference(), newValue)
  339. return toValue_float64(oldValue)
  340. } else {
  341. // --Prefix
  342. newValue := toValue_float64(-1 + targetValue.float64())
  343. self.putValue(target.reference(), newValue)
  344. return newValue
  345. }
  346. case token.VOID:
  347. target.resolve() // FIXME Side effect?
  348. return Value{}
  349. case token.DELETE:
  350. reference := target.reference()
  351. if reference == nil {
  352. return trueValue
  353. }
  354. return toValue_bool(target.reference().delete())
  355. case token.TYPEOF:
  356. targetValue := target.resolve()
  357. switch targetValue.kind {
  358. case valueUndefined:
  359. return toValue_string("undefined")
  360. case valueNull:
  361. return toValue_string("object")
  362. case valueBoolean:
  363. return toValue_string("boolean")
  364. case valueNumber:
  365. return toValue_string("number")
  366. case valueString:
  367. return toValue_string("string")
  368. case valueObject:
  369. if targetValue._object().isCall() {
  370. return toValue_string("function")
  371. }
  372. return toValue_string("object")
  373. default:
  374. // FIXME ?
  375. }
  376. }
  377. panic(hereBeDragons())
  378. }
  379. func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value {
  380. if node.initializer != nil {
  381. // FIXME If reference is nil
  382. left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx))
  383. right := self.cmpl_evaluate_nodeExpression(node.initializer)
  384. rightValue := right.resolve()
  385. self.putValue(left, rightValue)
  386. }
  387. return toValue_string(node.name)
  388. }