cmpl_evaluate_expression.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. package otto
  2. import (
  3. "fmt"
  4. "math"
  5. goruntime "runtime"
  6. "github.com/robertkrimen/otto/token"
  7. )
  8. func (rt *runtime) cmplEvaluateNodeExpression(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 rt.otto.Interrupt != nil {
  14. goruntime.Gosched()
  15. select {
  16. case value := <-rt.otto.Interrupt:
  17. value()
  18. default:
  19. }
  20. }
  21. switch node := node.(type) {
  22. case *nodeArrayLiteral:
  23. return rt.cmplEvaluateNodeArrayLiteral(node)
  24. case *nodeAssignExpression:
  25. return rt.cmplEvaluateNodeAssignExpression(node)
  26. case *nodeBinaryExpression:
  27. if node.comparison {
  28. return rt.cmplEvaluateNodeBinaryExpressionComparison(node)
  29. }
  30. return rt.cmplEvaluateNodeBinaryExpression(node)
  31. case *nodeBracketExpression:
  32. return rt.cmplEvaluateNodeBracketExpression(node)
  33. case *nodeCallExpression:
  34. return rt.cmplEvaluateNodeCallExpression(node, nil)
  35. case *nodeConditionalExpression:
  36. return rt.cmplEvaluateNodeConditionalExpression(node)
  37. case *nodeDotExpression:
  38. return rt.cmplEvaluateNodeDotExpression(node)
  39. case *nodeFunctionLiteral:
  40. local := rt.scope.lexical
  41. if node.name != "" {
  42. local = rt.newDeclarationStash(local)
  43. }
  44. value := objectValue(rt.newNodeFunction(node, local))
  45. if node.name != "" {
  46. local.createBinding(node.name, false, value)
  47. }
  48. return value
  49. case *nodeIdentifier:
  50. name := node.name
  51. // TODO Should be true or false (strictness) depending on context
  52. // getIdentifierReference should not return nil, but we check anyway and panic
  53. // so as not to propagate the nil into something else
  54. reference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx))
  55. if reference == nil {
  56. // Should never get here!
  57. panic(hereBeDragons("referenceError == nil: " + name))
  58. }
  59. return toValue(reference)
  60. case *nodeLiteral:
  61. return node.value
  62. case *nodeNewExpression:
  63. return rt.cmplEvaluateNodeNewExpression(node)
  64. case *nodeObjectLiteral:
  65. return rt.cmplEvaluateNodeObjectLiteral(node)
  66. case *nodeRegExpLiteral:
  67. return objectValue(rt.newRegExpDirect(node.pattern, node.flags))
  68. case *nodeSequenceExpression:
  69. return rt.cmplEvaluateNodeSequenceExpression(node)
  70. case *nodeThisExpression:
  71. return objectValue(rt.scope.this)
  72. case *nodeUnaryExpression:
  73. return rt.cmplEvaluateNodeUnaryExpression(node)
  74. case *nodeVariableExpression:
  75. return rt.cmplEvaluateNodeVariableExpression(node)
  76. default:
  77. panic(fmt.Sprintf("unknown node type: %T", node))
  78. }
  79. }
  80. func (rt *runtime) cmplEvaluateNodeArrayLiteral(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, rt.cmplEvaluateNodeExpression(node).resolve())
  87. }
  88. }
  89. result := rt.newArrayOf(valueArray)
  90. return objectValue(result)
  91. }
  92. func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value {
  93. left := rt.cmplEvaluateNodeExpression(node.left)
  94. right := rt.cmplEvaluateNodeExpression(node.right)
  95. rightValue := right.resolve()
  96. result := rightValue
  97. if node.operator != token.ASSIGN {
  98. result = rt.calculateBinaryExpression(node.operator, left, rightValue)
  99. }
  100. rt.putValue(left.reference(), result)
  101. return result
  102. }
  103. func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value {
  104. left := rt.cmplEvaluateNodeExpression(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 := rt.cmplEvaluateNodeExpression(node.right)
  113. return right.resolve()
  114. case token.LOGICAL_OR:
  115. if leftValue.bool() {
  116. return leftValue
  117. }
  118. right := rt.cmplEvaluateNodeExpression(node.right)
  119. return right.resolve()
  120. }
  121. return rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right))
  122. }
  123. func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value {
  124. left := rt.cmplEvaluateNodeExpression(node.left).resolve()
  125. right := rt.cmplEvaluateNodeExpression(node.right).resolve()
  126. return boolValue(rt.calculateComparison(node.operator, left, right))
  127. }
  128. func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value {
  129. target := rt.cmplEvaluateNodeExpression(node.left)
  130. targetValue := target.resolve()
  131. member := rt.cmplEvaluateNodeExpression(node.member)
  132. memberValue := member.resolve()
  133. // TODO Pass in base value as-is, and defer toObject till later?
  134. obj, err := rt.objectCoerce(targetValue)
  135. if err != nil {
  136. panic(rt.panicTypeError("Cannot access member %q of %s", memberValue.string(), err, at(node.idx)))
  137. }
  138. return toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx)))
  139. }
  140. func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value {
  141. this := Value{}
  142. callee := rt.cmplEvaluateNodeExpression(node.callee)
  143. argumentList := []Value{}
  144. if withArgumentList != nil {
  145. argumentList = rt.toValueArray(withArgumentList...)
  146. } else {
  147. for _, argumentNode := range node.argumentList {
  148. argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())
  149. }
  150. }
  151. eval := false // Whether this call is a (candidate for) direct call to eval
  152. name := ""
  153. if rf := callee.reference(); rf != nil {
  154. switch rf := rf.(type) {
  155. case *propertyReference:
  156. name = rf.name
  157. this = objectValue(rf.base)
  158. eval = rf.name == "eval" // Possible direct eval
  159. case *stashReference:
  160. // TODO ImplicitThisValue
  161. name = rf.name
  162. eval = rf.name == "eval" // Possible direct eval
  163. default:
  164. // FIXME?
  165. panic(rt.panicTypeError("unexpected callee type %T to node call expression", rf))
  166. }
  167. }
  168. atv := at(-1)
  169. switch callee := node.callee.(type) {
  170. case *nodeIdentifier:
  171. atv = at(callee.idx)
  172. case *nodeDotExpression:
  173. atv = at(callee.idx)
  174. case *nodeBracketExpression:
  175. atv = at(callee.idx)
  176. }
  177. frm := frame{
  178. callee: name,
  179. file: rt.scope.frame.file,
  180. }
  181. vl := callee.resolve()
  182. if !vl.IsFunction() {
  183. if name == "" {
  184. // FIXME Maybe typeof?
  185. panic(rt.panicTypeError("%v is not a function", vl, atv))
  186. }
  187. panic(rt.panicTypeError("%q is not a function", name, atv))
  188. }
  189. rt.scope.frame.offset = int(atv)
  190. return vl.object().call(this, argumentList, eval, frm)
  191. }
  192. func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value {
  193. test := rt.cmplEvaluateNodeExpression(node.test)
  194. testValue := test.resolve()
  195. if testValue.bool() {
  196. return rt.cmplEvaluateNodeExpression(node.consequent)
  197. }
  198. return rt.cmplEvaluateNodeExpression(node.alternate)
  199. }
  200. func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value {
  201. target := rt.cmplEvaluateNodeExpression(node.left)
  202. targetValue := target.resolve()
  203. // TODO Pass in base value as-is, and defer toObject till later?
  204. obj, err := rt.objectCoerce(targetValue)
  205. if err != nil {
  206. panic(rt.panicTypeError("Cannot access member %q of %s", node.identifier, err, at(node.idx)))
  207. }
  208. return toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx)))
  209. }
  210. func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value {
  211. callee := rt.cmplEvaluateNodeExpression(node.callee)
  212. argumentList := []Value{}
  213. for _, argumentNode := range node.argumentList {
  214. argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())
  215. }
  216. var name string
  217. if rf := callee.reference(); rf != nil {
  218. switch rf := rf.(type) {
  219. case *propertyReference:
  220. name = rf.name
  221. case *stashReference:
  222. name = rf.name
  223. default:
  224. panic(rt.panicTypeError("node new expression unexpected callee type %T", rf))
  225. }
  226. }
  227. atv := at(-1)
  228. switch callee := node.callee.(type) {
  229. case *nodeIdentifier:
  230. atv = at(callee.idx)
  231. case *nodeDotExpression:
  232. atv = at(callee.idx)
  233. case *nodeBracketExpression:
  234. atv = at(callee.idx)
  235. }
  236. vl := callee.resolve()
  237. if !vl.IsFunction() {
  238. if name == "" {
  239. // FIXME Maybe typeof?
  240. panic(rt.panicTypeError("%v is not a function", vl, atv))
  241. }
  242. panic(rt.panicTypeError("'%s' is not a function", name, atv))
  243. }
  244. rt.scope.frame.offset = int(atv)
  245. return vl.object().construct(argumentList)
  246. }
  247. func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value {
  248. result := rt.newObject()
  249. for _, prop := range node.value {
  250. switch prop.kind {
  251. case "value":
  252. result.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false)
  253. case "get":
  254. getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
  255. descriptor := property{}
  256. descriptor.mode = 0o211
  257. descriptor.value = propertyGetSet{getter, nil}
  258. result.defineOwnProperty(prop.key, descriptor, false)
  259. case "set":
  260. setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)
  261. descriptor := property{}
  262. descriptor.mode = 0o211
  263. descriptor.value = propertyGetSet{nil, setter}
  264. result.defineOwnProperty(prop.key, descriptor, false)
  265. default:
  266. panic(fmt.Sprintf("unknown node object literal property kind %T", prop.kind))
  267. }
  268. }
  269. return objectValue(result)
  270. }
  271. func (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value {
  272. var result Value
  273. for _, node := range node.sequence {
  274. result = rt.cmplEvaluateNodeExpression(node)
  275. result = result.resolve()
  276. }
  277. return result
  278. }
  279. func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value {
  280. target := rt.cmplEvaluateNodeExpression(node.operand)
  281. switch node.operator {
  282. case token.TYPEOF, token.DELETE:
  283. if target.kind == valueReference && target.reference().invalid() {
  284. if node.operator == token.TYPEOF {
  285. return stringValue("undefined")
  286. }
  287. return trueValue
  288. }
  289. }
  290. switch node.operator {
  291. case token.NOT:
  292. targetValue := target.resolve()
  293. if targetValue.bool() {
  294. return falseValue
  295. }
  296. return trueValue
  297. case token.BITWISE_NOT:
  298. targetValue := target.resolve()
  299. integerValue := toInt32(targetValue)
  300. return int32Value(^integerValue)
  301. case token.PLUS:
  302. targetValue := target.resolve()
  303. return float64Value(targetValue.float64())
  304. case token.MINUS:
  305. targetValue := target.resolve()
  306. value := targetValue.float64()
  307. // TODO Test this
  308. sign := float64(-1)
  309. if math.Signbit(value) {
  310. sign = 1
  311. }
  312. return float64Value(math.Copysign(value, sign))
  313. case token.INCREMENT:
  314. targetValue := target.resolve()
  315. if node.postfix {
  316. // Postfix++
  317. oldValue := targetValue.float64()
  318. newValue := float64Value(+1 + oldValue)
  319. rt.putValue(target.reference(), newValue)
  320. return float64Value(oldValue)
  321. }
  322. // ++Prefix
  323. newValue := float64Value(+1 + targetValue.float64())
  324. rt.putValue(target.reference(), newValue)
  325. return newValue
  326. case token.DECREMENT:
  327. targetValue := target.resolve()
  328. if node.postfix {
  329. // Postfix--
  330. oldValue := targetValue.float64()
  331. newValue := float64Value(-1 + oldValue)
  332. rt.putValue(target.reference(), newValue)
  333. return float64Value(oldValue)
  334. }
  335. // --Prefix
  336. newValue := float64Value(-1 + targetValue.float64())
  337. rt.putValue(target.reference(), newValue)
  338. return newValue
  339. case token.VOID:
  340. target.resolve() // FIXME Side effect?
  341. return Value{}
  342. case token.DELETE:
  343. reference := target.reference()
  344. if reference == nil {
  345. return trueValue
  346. }
  347. return boolValue(target.reference().delete())
  348. case token.TYPEOF:
  349. targetValue := target.resolve()
  350. switch targetValue.kind {
  351. case valueUndefined:
  352. return stringValue("undefined")
  353. case valueNull:
  354. return stringValue("object")
  355. case valueBoolean:
  356. return stringValue("boolean")
  357. case valueNumber:
  358. return stringValue("number")
  359. case valueString:
  360. return stringValue("string")
  361. case valueObject:
  362. if targetValue.object().isCall() {
  363. return stringValue("function")
  364. }
  365. return stringValue("object")
  366. default:
  367. // FIXME ?
  368. }
  369. }
  370. panic(hereBeDragons())
  371. }
  372. func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value {
  373. if node.initializer != nil {
  374. // FIXME If reference is nil
  375. left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx))
  376. right := rt.cmplEvaluateNodeExpression(node.initializer)
  377. rightValue := right.resolve()
  378. rt.putValue(left, rightValue)
  379. }
  380. return stringValue(node.name)
  381. }