compiler_stmt.go 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. package goja
  2. import (
  3. "fmt"
  4. "github.com/dop251/goja/ast"
  5. "github.com/dop251/goja/file"
  6. "github.com/dop251/goja/token"
  7. "github.com/dop251/goja/unistring"
  8. )
  9. func (c *compiler) compileStatement(v ast.Statement, needResult bool) {
  10. // log.Printf("compileStatement(): %T", v)
  11. switch v := v.(type) {
  12. case *ast.BlockStatement:
  13. c.compileBlockStatement(v, needResult)
  14. case *ast.ExpressionStatement:
  15. c.compileExpressionStatement(v, needResult)
  16. case *ast.VariableStatement:
  17. c.compileVariableStatement(v)
  18. case *ast.LexicalDeclaration:
  19. c.compileLexicalDeclaration(v)
  20. case *ast.ReturnStatement:
  21. c.compileReturnStatement(v)
  22. case *ast.IfStatement:
  23. c.compileIfStatement(v, needResult)
  24. case *ast.DoWhileStatement:
  25. c.compileDoWhileStatement(v, needResult)
  26. case *ast.ForStatement:
  27. c.compileForStatement(v, needResult)
  28. case *ast.ForInStatement:
  29. c.compileForInStatement(v, needResult)
  30. case *ast.ForOfStatement:
  31. c.compileForOfStatement(v, needResult)
  32. case *ast.WhileStatement:
  33. c.compileWhileStatement(v, needResult)
  34. case *ast.BranchStatement:
  35. c.compileBranchStatement(v)
  36. case *ast.TryStatement:
  37. c.compileTryStatement(v, needResult)
  38. case *ast.ThrowStatement:
  39. c.compileThrowStatement(v)
  40. case *ast.SwitchStatement:
  41. c.compileSwitchStatement(v, needResult)
  42. case *ast.LabelledStatement:
  43. c.compileLabeledStatement(v, needResult)
  44. case *ast.EmptyStatement:
  45. c.compileEmptyStatement(needResult)
  46. case *ast.FunctionDeclaration:
  47. c.compileStandaloneFunctionDecl(v)
  48. // note functions inside blocks are hoisted to the top of the block and are compiled using compileFunctions()
  49. case *ast.WithStatement:
  50. c.compileWithStatement(v, needResult)
  51. case *ast.DebuggerStatement:
  52. default:
  53. panic(fmt.Errorf("Unknown statement type: %T", v))
  54. }
  55. }
  56. func (c *compiler) compileLabeledStatement(v *ast.LabelledStatement, needResult bool) {
  57. label := v.Label.Name
  58. if c.scope.strict {
  59. c.checkIdentifierName(label, int(v.Label.Idx)-1)
  60. }
  61. for b := c.block; b != nil; b = b.outer {
  62. if b.label == label {
  63. c.throwSyntaxError(int(v.Label.Idx-1), "Label '%s' has already been declared", label)
  64. }
  65. }
  66. switch s := v.Statement.(type) {
  67. case *ast.ForInStatement:
  68. c.compileLabeledForInStatement(s, needResult, label)
  69. case *ast.ForOfStatement:
  70. c.compileLabeledForOfStatement(s, needResult, label)
  71. case *ast.ForStatement:
  72. c.compileLabeledForStatement(s, needResult, label)
  73. case *ast.WhileStatement:
  74. c.compileLabeledWhileStatement(s, needResult, label)
  75. case *ast.DoWhileStatement:
  76. c.compileLabeledDoWhileStatement(s, needResult, label)
  77. default:
  78. c.compileGenericLabeledStatement(s, needResult, label)
  79. }
  80. }
  81. func (c *compiler) updateEnterBlock(enter *enterBlock) {
  82. scope := c.scope
  83. stashSize, stackSize := 0, 0
  84. if scope.dynLookup {
  85. stashSize = len(scope.bindings)
  86. enter.names = scope.makeNamesMap()
  87. } else {
  88. for _, b := range scope.bindings {
  89. if b.inStash {
  90. stashSize++
  91. } else {
  92. stackSize++
  93. }
  94. }
  95. }
  96. enter.stashSize, enter.stackSize = uint32(stashSize), uint32(stackSize)
  97. }
  98. func (c *compiler) compileTryStatement(v *ast.TryStatement, needResult bool) {
  99. if c.scope.strict && v.Catch != nil && v.Catch.Parameter != nil {
  100. switch v.Catch.Parameter.Name {
  101. case "arguments", "eval":
  102. c.throwSyntaxError(int(v.Catch.Parameter.Idx)-1, "Catch variable may not be eval or arguments in strict mode")
  103. }
  104. }
  105. c.block = &block{
  106. typ: blockTry,
  107. outer: c.block,
  108. }
  109. var lp int
  110. var bodyNeedResult bool
  111. var finallyBreaking *block
  112. if v.Finally != nil {
  113. lp, finallyBreaking = c.scanStatements(v.Finally.List)
  114. }
  115. if finallyBreaking != nil {
  116. c.block.breaking = finallyBreaking
  117. if lp == -1 {
  118. bodyNeedResult = finallyBreaking.needResult
  119. }
  120. } else {
  121. bodyNeedResult = needResult
  122. }
  123. lbl := len(c.p.code)
  124. c.emit(nil)
  125. if needResult {
  126. c.emit(clearResult)
  127. }
  128. c.compileBlockStatement(v.Body, bodyNeedResult)
  129. c.emit(halt)
  130. lbl2 := len(c.p.code)
  131. c.emit(nil)
  132. var catchOffset int
  133. if v.Catch != nil {
  134. catchOffset = len(c.p.code) - lbl
  135. if v.Catch.Parameter != nil {
  136. c.block = &block{
  137. typ: blockScope,
  138. outer: c.block,
  139. }
  140. c.newBlockScope()
  141. list := v.Catch.Body.List
  142. funcs := c.extractFunctions(list)
  143. c.createFunctionBindings(funcs)
  144. c.scope.bindNameLexical(v.Catch.Parameter.Name, true, int(v.Catch.Parameter.Idx)-1)
  145. bindings := c.scope.bindings
  146. if l := len(bindings); l > 1 {
  147. // make sure the catch variable always goes first
  148. bindings[0], bindings[l-1] = bindings[l-1], bindings[0]
  149. }
  150. c.compileLexicalDeclarations(list, true)
  151. enter := &enterBlock{}
  152. c.emit(enter)
  153. c.compileFunctions(funcs)
  154. c.compileStatements(list, bodyNeedResult)
  155. c.leaveScopeBlock(enter)
  156. if c.scope.dynLookup || c.scope.bindings[0].inStash {
  157. c.p.code[lbl+catchOffset] = &enterCatchBlock{
  158. names: enter.names,
  159. stashSize: enter.stashSize,
  160. stackSize: enter.stackSize,
  161. }
  162. } else {
  163. enter.stackSize--
  164. }
  165. c.popScope()
  166. } else {
  167. c.emit(pop)
  168. c.compileBlockStatement(v.Catch.Body, bodyNeedResult)
  169. }
  170. c.emit(halt)
  171. }
  172. var finallyOffset int
  173. if v.Finally != nil {
  174. lbl1 := len(c.p.code)
  175. c.emit(nil)
  176. finallyOffset = len(c.p.code) - lbl
  177. c.compileBlockStatement(v.Finally, false)
  178. c.emit(halt, retFinally)
  179. c.p.code[lbl1] = jump(len(c.p.code) - lbl1)
  180. }
  181. c.p.code[lbl] = try{catchOffset: int32(catchOffset), finallyOffset: int32(finallyOffset)}
  182. c.p.code[lbl2] = jump(len(c.p.code) - lbl2)
  183. c.leaveBlock()
  184. }
  185. func (c *compiler) compileThrowStatement(v *ast.ThrowStatement) {
  186. //c.p.srcMap = append(c.p.srcMap, srcMapItem{pc: len(c.p.code), srcPos: int(v.Throw) - 1})
  187. c.compileExpression(v.Argument).emitGetter(true)
  188. c.emit(throw)
  189. }
  190. func (c *compiler) compileDoWhileStatement(v *ast.DoWhileStatement, needResult bool) {
  191. c.compileLabeledDoWhileStatement(v, needResult, "")
  192. }
  193. func (c *compiler) compileLabeledDoWhileStatement(v *ast.DoWhileStatement, needResult bool, label unistring.String) {
  194. c.block = &block{
  195. typ: blockLoop,
  196. outer: c.block,
  197. label: label,
  198. needResult: needResult,
  199. }
  200. start := len(c.p.code)
  201. c.compileStatement(v.Body, needResult)
  202. c.block.cont = len(c.p.code)
  203. c.emitExpr(c.compileExpression(v.Test), true)
  204. c.emit(jeq(start - len(c.p.code)))
  205. c.leaveBlock()
  206. }
  207. func (c *compiler) compileForStatement(v *ast.ForStatement, needResult bool) {
  208. c.compileLabeledForStatement(v, needResult, "")
  209. }
  210. func (c *compiler) compileForHeadLexDecl(decl *ast.LexicalDeclaration, needResult bool) *enterBlock {
  211. c.block = &block{
  212. typ: blockIterScope,
  213. outer: c.block,
  214. needResult: needResult,
  215. }
  216. c.newBlockScope()
  217. enterIterBlock := &enterBlock{}
  218. c.emit(enterIterBlock)
  219. c.createLexicalBindings(decl)
  220. c.compileLexicalDeclaration(decl)
  221. return enterIterBlock
  222. }
  223. func (c *compiler) compileLabeledForStatement(v *ast.ForStatement, needResult bool, label unistring.String) {
  224. loopBlock := &block{
  225. typ: blockLoop,
  226. outer: c.block,
  227. label: label,
  228. needResult: needResult,
  229. }
  230. c.block = loopBlock
  231. var enterIterBlock *enterBlock
  232. switch init := v.Initializer.(type) {
  233. case nil:
  234. // no-op
  235. case *ast.ForLoopInitializerLexicalDecl:
  236. enterIterBlock = c.compileForHeadLexDecl(&init.LexicalDeclaration, needResult)
  237. case *ast.ForLoopInitializerVarDeclList:
  238. for _, expr := range init.List {
  239. c.compileVarBinding(expr)
  240. }
  241. case *ast.ForLoopInitializerExpression:
  242. c.compileExpression(init.Expression).emitGetter(false)
  243. default:
  244. panic(fmt.Sprintf("Unsupported for loop initializer: %T", init))
  245. }
  246. if needResult {
  247. c.emit(clearResult) // initial result
  248. }
  249. if enterIterBlock != nil {
  250. c.emit(jump(1))
  251. }
  252. start := len(c.p.code)
  253. var j int
  254. testConst := false
  255. if v.Test != nil {
  256. expr := c.compileExpression(v.Test)
  257. if expr.constant() {
  258. r, ex := c.evalConst(expr)
  259. if ex == nil {
  260. if r.ToBoolean() {
  261. testConst = true
  262. } else {
  263. leave := c.enterDummyMode()
  264. c.compileStatement(v.Body, false)
  265. if v.Update != nil {
  266. c.compileExpression(v.Update).emitGetter(false)
  267. }
  268. leave()
  269. goto end
  270. }
  271. } else {
  272. expr.addSrcMap()
  273. c.emitThrow(ex.val)
  274. goto end
  275. }
  276. } else {
  277. expr.emitGetter(true)
  278. j = len(c.p.code)
  279. c.emit(nil)
  280. }
  281. }
  282. if needResult {
  283. c.emit(clearResult)
  284. }
  285. c.compileStatement(v.Body, needResult)
  286. loopBlock.cont = len(c.p.code)
  287. if enterIterBlock != nil {
  288. c.emit(jump(1))
  289. }
  290. if v.Update != nil {
  291. c.compileExpression(v.Update).emitGetter(false)
  292. }
  293. if enterIterBlock != nil {
  294. if c.scope.needStash || c.scope.isDynamic() {
  295. c.p.code[start-1] = copyStash{}
  296. c.p.code[loopBlock.cont] = copyStash{}
  297. } else {
  298. if l := len(c.p.code); l > loopBlock.cont {
  299. loopBlock.cont++
  300. } else {
  301. c.p.code = c.p.code[:l-1]
  302. }
  303. }
  304. }
  305. c.emit(jump(start - len(c.p.code)))
  306. if v.Test != nil {
  307. if !testConst {
  308. c.p.code[j] = jne(len(c.p.code) - j)
  309. }
  310. }
  311. end:
  312. if enterIterBlock != nil {
  313. c.leaveScopeBlock(enterIterBlock)
  314. c.popScope()
  315. }
  316. c.leaveBlock()
  317. }
  318. func (c *compiler) compileForInStatement(v *ast.ForInStatement, needResult bool) {
  319. c.compileLabeledForInStatement(v, needResult, "")
  320. }
  321. func (c *compiler) compileForInto(into ast.ForInto, needResult bool) (enter *enterBlock) {
  322. switch into := into.(type) {
  323. case *ast.ForIntoExpression:
  324. c.compileExpression(into.Expression).emitSetter(&c.enumGetExpr, false)
  325. case *ast.ForIntoVar:
  326. if c.scope.strict && into.Binding.Initializer != nil {
  327. c.throwSyntaxError(int(into.Binding.Initializer.Idx0())-1, "for-in loop variable declaration may not have an initializer.")
  328. }
  329. switch target := into.Binding.Target.(type) {
  330. case *ast.Identifier:
  331. c.compileIdentifierExpression(target).emitSetter(&c.enumGetExpr, false)
  332. case ast.Pattern:
  333. c.emit(enumGet)
  334. c.emitPattern(target, c.emitPatternVarAssign, false)
  335. default:
  336. c.throwSyntaxError(int(target.Idx0()-1), "unsupported for-in var target: %T", target)
  337. }
  338. case *ast.ForDeclaration:
  339. c.block = &block{
  340. typ: blockIterScope,
  341. outer: c.block,
  342. needResult: needResult,
  343. }
  344. c.newBlockScope()
  345. enter = &enterBlock{}
  346. c.emit(enter)
  347. switch target := into.Target.(type) {
  348. case *ast.Identifier:
  349. b := c.createLexicalIdBinding(target.Name, into.IsConst, int(into.Idx)-1)
  350. c.emit(enumGet)
  351. b.emitInit()
  352. case ast.Pattern:
  353. c.createLexicalBinding(target, into.IsConst)
  354. c.emit(enumGet)
  355. c.emitPattern(target, func(target, init compiledExpr) {
  356. c.emitPatternLexicalAssign(target, init, into.IsConst)
  357. }, false)
  358. default:
  359. c.throwSyntaxError(int(into.Idx)-1, "Unsupported ForBinding: %T", into.Target)
  360. }
  361. default:
  362. panic(fmt.Sprintf("Unsupported for-into: %T", into))
  363. }
  364. return
  365. }
  366. func (c *compiler) compileLabeledForInOfStatement(into ast.ForInto, source ast.Expression, body ast.Statement, iter, needResult bool, label unistring.String) {
  367. c.block = &block{
  368. typ: blockLoopEnum,
  369. outer: c.block,
  370. label: label,
  371. needResult: needResult,
  372. }
  373. enterPos := -1
  374. if forDecl, ok := into.(*ast.ForDeclaration); ok {
  375. c.block = &block{
  376. typ: blockScope,
  377. outer: c.block,
  378. needResult: false,
  379. }
  380. c.newBlockScope()
  381. enterPos = len(c.p.code)
  382. c.emit(jump(1))
  383. c.createLexicalBinding(forDecl.Target, forDecl.IsConst)
  384. }
  385. c.compileExpression(source).emitGetter(true)
  386. if enterPos != -1 {
  387. s := c.scope
  388. used := len(c.block.breaks) > 0 || s.isDynamic()
  389. if !used {
  390. for _, b := range s.bindings {
  391. if b.useCount() > 0 {
  392. used = true
  393. break
  394. }
  395. }
  396. }
  397. if used {
  398. // We need the stack untouched because it contains the source.
  399. // This is not the most optimal way, but it's an edge case, hopefully quite rare.
  400. for _, b := range s.bindings {
  401. b.moveToStash()
  402. }
  403. enter := &enterBlock{}
  404. c.p.code[enterPos] = enter
  405. c.leaveScopeBlock(enter)
  406. } else {
  407. c.block = c.block.outer
  408. }
  409. c.popScope()
  410. }
  411. if iter {
  412. c.emit(iterateP)
  413. } else {
  414. c.emit(enumerate)
  415. }
  416. if needResult {
  417. c.emit(clearResult)
  418. }
  419. start := len(c.p.code)
  420. c.block.cont = start
  421. c.emit(nil)
  422. enterIterBlock := c.compileForInto(into, needResult)
  423. if needResult {
  424. c.emit(clearResult)
  425. }
  426. c.compileStatement(body, needResult)
  427. if enterIterBlock != nil {
  428. c.leaveScopeBlock(enterIterBlock)
  429. c.popScope()
  430. }
  431. c.emit(jump(start - len(c.p.code)))
  432. if iter {
  433. c.p.code[start] = iterNext(len(c.p.code) - start)
  434. } else {
  435. c.p.code[start] = enumNext(len(c.p.code) - start)
  436. }
  437. c.emit(enumPop, jump(2))
  438. c.leaveBlock()
  439. c.emit(enumPopClose)
  440. }
  441. func (c *compiler) compileLabeledForInStatement(v *ast.ForInStatement, needResult bool, label unistring.String) {
  442. c.compileLabeledForInOfStatement(v.Into, v.Source, v.Body, false, needResult, label)
  443. }
  444. func (c *compiler) compileForOfStatement(v *ast.ForOfStatement, needResult bool) {
  445. c.compileLabeledForOfStatement(v, needResult, "")
  446. }
  447. func (c *compiler) compileLabeledForOfStatement(v *ast.ForOfStatement, needResult bool, label unistring.String) {
  448. c.compileLabeledForInOfStatement(v.Into, v.Source, v.Body, true, needResult, label)
  449. }
  450. func (c *compiler) compileWhileStatement(v *ast.WhileStatement, needResult bool) {
  451. c.compileLabeledWhileStatement(v, needResult, "")
  452. }
  453. func (c *compiler) compileLabeledWhileStatement(v *ast.WhileStatement, needResult bool, label unistring.String) {
  454. c.block = &block{
  455. typ: blockLoop,
  456. outer: c.block,
  457. label: label,
  458. needResult: needResult,
  459. }
  460. if needResult {
  461. c.emit(clearResult)
  462. }
  463. start := len(c.p.code)
  464. c.block.cont = start
  465. expr := c.compileExpression(v.Test)
  466. testTrue := false
  467. var j int
  468. if expr.constant() {
  469. if t, ex := c.evalConst(expr); ex == nil {
  470. if t.ToBoolean() {
  471. testTrue = true
  472. } else {
  473. c.compileStatementDummy(v.Body)
  474. goto end
  475. }
  476. } else {
  477. c.emitThrow(ex.val)
  478. goto end
  479. }
  480. } else {
  481. expr.emitGetter(true)
  482. j = len(c.p.code)
  483. c.emit(nil)
  484. }
  485. if needResult {
  486. c.emit(clearResult)
  487. }
  488. c.compileStatement(v.Body, needResult)
  489. c.emit(jump(start - len(c.p.code)))
  490. if !testTrue {
  491. c.p.code[j] = jne(len(c.p.code) - j)
  492. }
  493. end:
  494. c.leaveBlock()
  495. }
  496. func (c *compiler) compileEmptyStatement(needResult bool) {
  497. if needResult {
  498. c.emit(clearResult)
  499. }
  500. }
  501. func (c *compiler) compileBranchStatement(v *ast.BranchStatement) {
  502. switch v.Token {
  503. case token.BREAK:
  504. c.compileBreak(v.Label, v.Idx)
  505. case token.CONTINUE:
  506. c.compileContinue(v.Label, v.Idx)
  507. default:
  508. panic(fmt.Errorf("Unknown branch statement token: %s", v.Token.String()))
  509. }
  510. }
  511. func (c *compiler) findBranchBlock(st *ast.BranchStatement) *block {
  512. switch st.Token {
  513. case token.BREAK:
  514. return c.findBreakBlock(st.Label, true)
  515. case token.CONTINUE:
  516. return c.findBreakBlock(st.Label, false)
  517. }
  518. return nil
  519. }
  520. func (c *compiler) findBreakBlock(label *ast.Identifier, isBreak bool) (res *block) {
  521. if label != nil {
  522. var found *block
  523. for b := c.block; b != nil; b = b.outer {
  524. if res == nil {
  525. if bb := b.breaking; bb != nil {
  526. res = bb
  527. if isBreak {
  528. return
  529. }
  530. }
  531. }
  532. if b.label == label.Name {
  533. found = b
  534. break
  535. }
  536. }
  537. if !isBreak && found != nil && found.typ != blockLoop && found.typ != blockLoopEnum {
  538. c.throwSyntaxError(int(label.Idx)-1, "Illegal continue statement: '%s' does not denote an iteration statement", label.Name)
  539. }
  540. if res == nil {
  541. res = found
  542. }
  543. } else {
  544. // find the nearest loop or switch (if break)
  545. L:
  546. for b := c.block; b != nil; b = b.outer {
  547. if bb := b.breaking; bb != nil {
  548. return bb
  549. }
  550. switch b.typ {
  551. case blockLoop, blockLoopEnum:
  552. res = b
  553. break L
  554. case blockSwitch:
  555. if isBreak {
  556. res = b
  557. break L
  558. }
  559. }
  560. }
  561. }
  562. return
  563. }
  564. func (c *compiler) emitBlockExitCode(label *ast.Identifier, idx file.Idx, isBreak bool) *block {
  565. block := c.findBreakBlock(label, isBreak)
  566. if block == nil {
  567. c.throwSyntaxError(int(idx)-1, "Could not find block")
  568. panic("unreachable")
  569. }
  570. L:
  571. for b := c.block; b != block; b = b.outer {
  572. switch b.typ {
  573. case blockIterScope:
  574. if !isBreak && b.outer == block {
  575. break L
  576. }
  577. fallthrough
  578. case blockScope:
  579. b.breaks = append(b.breaks, len(c.p.code))
  580. c.emit(nil)
  581. case blockTry:
  582. c.emit(halt)
  583. case blockWith:
  584. c.emit(leaveWith)
  585. case blockLoopEnum:
  586. c.emit(enumPopClose)
  587. }
  588. }
  589. return block
  590. }
  591. func (c *compiler) compileBreak(label *ast.Identifier, idx file.Idx) {
  592. block := c.emitBlockExitCode(label, idx, true)
  593. block.breaks = append(block.breaks, len(c.p.code))
  594. c.emit(nil)
  595. }
  596. func (c *compiler) compileContinue(label *ast.Identifier, idx file.Idx) {
  597. block := c.emitBlockExitCode(label, idx, false)
  598. block.conts = append(block.conts, len(c.p.code))
  599. c.emit(nil)
  600. }
  601. func (c *compiler) compileIfBody(s ast.Statement, needResult bool) {
  602. if !c.scope.strict {
  603. if s, ok := s.(*ast.FunctionDeclaration); ok {
  604. c.compileFunction(s)
  605. if needResult {
  606. c.emit(clearResult)
  607. }
  608. return
  609. }
  610. }
  611. c.compileStatement(s, needResult)
  612. }
  613. func (c *compiler) compileIfBodyDummy(s ast.Statement) {
  614. leave := c.enterDummyMode()
  615. defer leave()
  616. c.compileIfBody(s, false)
  617. }
  618. func (c *compiler) compileIfStatement(v *ast.IfStatement, needResult bool) {
  619. test := c.compileExpression(v.Test)
  620. if needResult {
  621. c.emit(clearResult)
  622. }
  623. if test.constant() {
  624. r, ex := c.evalConst(test)
  625. if ex != nil {
  626. test.addSrcMap()
  627. c.emitThrow(ex.val)
  628. return
  629. }
  630. if r.ToBoolean() {
  631. c.compileIfBody(v.Consequent, needResult)
  632. if v.Alternate != nil {
  633. c.compileIfBodyDummy(v.Alternate)
  634. }
  635. } else {
  636. c.compileIfBodyDummy(v.Consequent)
  637. if v.Alternate != nil {
  638. c.compileIfBody(v.Alternate, needResult)
  639. } else {
  640. if needResult {
  641. c.emit(clearResult)
  642. }
  643. }
  644. }
  645. return
  646. }
  647. test.emitGetter(true)
  648. jmp := len(c.p.code)
  649. c.emit(nil)
  650. c.compileIfBody(v.Consequent, needResult)
  651. if v.Alternate != nil {
  652. jmp1 := len(c.p.code)
  653. c.emit(nil)
  654. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  655. c.compileIfBody(v.Alternate, needResult)
  656. c.p.code[jmp1] = jump(len(c.p.code) - jmp1)
  657. } else {
  658. if needResult {
  659. c.emit(jump(2))
  660. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  661. c.emit(clearResult)
  662. } else {
  663. c.p.code[jmp] = jne(len(c.p.code) - jmp)
  664. }
  665. }
  666. }
  667. func (c *compiler) compileReturnStatement(v *ast.ReturnStatement) {
  668. if v.Argument != nil {
  669. c.compileExpression(v.Argument).emitGetter(true)
  670. } else {
  671. c.emit(loadUndef)
  672. }
  673. for b := c.block; b != nil; b = b.outer {
  674. switch b.typ {
  675. case blockTry:
  676. c.emit(halt)
  677. case blockLoopEnum:
  678. c.emit(enumPopClose)
  679. }
  680. }
  681. c.emit(ret)
  682. }
  683. func (c *compiler) checkVarConflict(name unistring.String, offset int) {
  684. for sc := c.scope; sc != nil; sc = sc.outer {
  685. if b, exists := sc.boundNames[name]; exists && !b.isVar {
  686. c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  687. }
  688. if sc.function {
  689. break
  690. }
  691. }
  692. }
  693. func (c *compiler) emitVarAssign(name unistring.String, offset int, init compiledExpr) {
  694. c.checkVarConflict(name, offset)
  695. if init != nil {
  696. c.emitVarRef(name, offset)
  697. c.emitNamed(init, name)
  698. c.emit(putValueP)
  699. }
  700. }
  701. func (c *compiler) compileVarBinding(expr *ast.Binding) {
  702. switch target := expr.Target.(type) {
  703. case *ast.Identifier:
  704. c.emitVarAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer))
  705. case ast.Pattern:
  706. c.compileExpression(expr.Initializer).emitGetter(true)
  707. c.emitPattern(target, c.emitPatternVarAssign, false)
  708. default:
  709. c.throwSyntaxError(int(target.Idx0()-1), "unsupported variable binding target: %T", target)
  710. }
  711. }
  712. func (c *compiler) emitLexicalAssign(name unistring.String, offset int, init compiledExpr, isConst bool) {
  713. b := c.scope.boundNames[name]
  714. if b == nil {
  715. panic("Lexical declaration for an unbound name")
  716. }
  717. if init != nil {
  718. c.emitNamed(init, name)
  719. } else {
  720. if isConst {
  721. c.throwSyntaxError(offset, "Missing initializer in const declaration")
  722. }
  723. c.emit(loadUndef)
  724. }
  725. if c.scope.outer != nil {
  726. b.emitInit()
  727. } else {
  728. c.emit(initGlobal(name))
  729. }
  730. }
  731. func (c *compiler) emitPatternVarAssign(target, init compiledExpr) {
  732. id := target.(*compiledIdentifierExpr)
  733. c.emitVarAssign(id.name, id.offset, init)
  734. }
  735. func (c *compiler) emitPatternLexicalAssign(target, init compiledExpr, isConst bool) {
  736. id := target.(*compiledIdentifierExpr)
  737. c.emitLexicalAssign(id.name, id.offset, init, isConst)
  738. }
  739. func (c *compiler) emitPatternAssign(target, init compiledExpr) {
  740. target.emitRef()
  741. if id, ok := target.(*compiledIdentifierExpr); ok {
  742. c.emitNamed(init, id.name)
  743. } else {
  744. init.emitGetter(true)
  745. }
  746. c.emit(putValueP)
  747. }
  748. func (c *compiler) compileLexicalBinding(expr *ast.Binding, isConst bool) {
  749. switch target := expr.Target.(type) {
  750. case *ast.Identifier:
  751. c.emitLexicalAssign(target.Name, int(target.Idx)-1, c.compileExpression(expr.Initializer), isConst)
  752. case ast.Pattern:
  753. c.compileExpression(expr.Initializer).emitGetter(true)
  754. c.emitPattern(target, func(target, init compiledExpr) {
  755. c.emitPatternLexicalAssign(target, init, isConst)
  756. }, false)
  757. default:
  758. c.throwSyntaxError(int(target.Idx0()-1), "unsupported lexical binding target: %T", target)
  759. }
  760. }
  761. func (c *compiler) compileVariableStatement(v *ast.VariableStatement) {
  762. for _, expr := range v.List {
  763. c.compileVarBinding(expr)
  764. }
  765. }
  766. func (c *compiler) compileLexicalDeclaration(v *ast.LexicalDeclaration) {
  767. isConst := v.Token == token.CONST
  768. for _, e := range v.List {
  769. c.compileLexicalBinding(e, isConst)
  770. }
  771. }
  772. func (c *compiler) isEmptyResult(st ast.Statement) bool {
  773. switch st := st.(type) {
  774. case *ast.EmptyStatement, *ast.VariableStatement, *ast.LexicalDeclaration, *ast.FunctionDeclaration,
  775. *ast.BranchStatement, *ast.DebuggerStatement:
  776. return true
  777. case *ast.LabelledStatement:
  778. return c.isEmptyResult(st.Statement)
  779. case *ast.BlockStatement:
  780. for _, s := range st.List {
  781. if _, ok := s.(*ast.BranchStatement); ok {
  782. return true
  783. }
  784. if !c.isEmptyResult(s) {
  785. return false
  786. }
  787. }
  788. return true
  789. }
  790. return false
  791. }
  792. func (c *compiler) scanStatements(list []ast.Statement) (lastProducingIdx int, breakingBlock *block) {
  793. lastProducingIdx = -1
  794. for i, st := range list {
  795. if bs, ok := st.(*ast.BranchStatement); ok {
  796. if blk := c.findBranchBlock(bs); blk != nil {
  797. breakingBlock = blk
  798. }
  799. break
  800. }
  801. if !c.isEmptyResult(st) {
  802. lastProducingIdx = i
  803. }
  804. }
  805. return
  806. }
  807. func (c *compiler) compileStatementsNeedResult(list []ast.Statement, lastProducingIdx int) {
  808. if lastProducingIdx >= 0 {
  809. for _, st := range list[:lastProducingIdx] {
  810. if _, ok := st.(*ast.FunctionDeclaration); ok {
  811. continue
  812. }
  813. c.compileStatement(st, false)
  814. }
  815. c.compileStatement(list[lastProducingIdx], true)
  816. }
  817. var leave func()
  818. defer func() {
  819. if leave != nil {
  820. leave()
  821. }
  822. }()
  823. for _, st := range list[lastProducingIdx+1:] {
  824. if _, ok := st.(*ast.FunctionDeclaration); ok {
  825. continue
  826. }
  827. c.compileStatement(st, false)
  828. if leave == nil {
  829. if _, ok := st.(*ast.BranchStatement); ok {
  830. leave = c.enterDummyMode()
  831. }
  832. }
  833. }
  834. }
  835. func (c *compiler) compileStatements(list []ast.Statement, needResult bool) {
  836. lastProducingIdx, blk := c.scanStatements(list)
  837. if blk != nil {
  838. needResult = blk.needResult
  839. }
  840. if needResult {
  841. c.compileStatementsNeedResult(list, lastProducingIdx)
  842. return
  843. }
  844. for _, st := range list {
  845. if _, ok := st.(*ast.FunctionDeclaration); ok {
  846. continue
  847. }
  848. c.compileStatement(st, false)
  849. }
  850. }
  851. func (c *compiler) compileGenericLabeledStatement(v ast.Statement, needResult bool, label unistring.String) {
  852. c.block = &block{
  853. typ: blockLabel,
  854. outer: c.block,
  855. label: label,
  856. needResult: needResult,
  857. }
  858. c.compileStatement(v, needResult)
  859. c.leaveBlock()
  860. }
  861. func (c *compiler) compileBlockStatement(v *ast.BlockStatement, needResult bool) {
  862. var scopeDeclared bool
  863. funcs := c.extractFunctions(v.List)
  864. if len(funcs) > 0 {
  865. c.newBlockScope()
  866. scopeDeclared = true
  867. }
  868. c.createFunctionBindings(funcs)
  869. scopeDeclared = c.compileLexicalDeclarations(v.List, scopeDeclared)
  870. var enter *enterBlock
  871. if scopeDeclared {
  872. c.block = &block{
  873. outer: c.block,
  874. typ: blockScope,
  875. needResult: needResult,
  876. }
  877. enter = &enterBlock{}
  878. c.emit(enter)
  879. }
  880. c.compileFunctions(funcs)
  881. c.compileStatements(v.List, needResult)
  882. if scopeDeclared {
  883. c.leaveScopeBlock(enter)
  884. c.popScope()
  885. }
  886. }
  887. func (c *compiler) compileExpressionStatement(v *ast.ExpressionStatement, needResult bool) {
  888. expr := c.compileExpression(v.Expression)
  889. if expr.constant() {
  890. c.emitConst(expr, needResult)
  891. } else {
  892. expr.emitGetter(needResult)
  893. }
  894. if needResult {
  895. c.emit(saveResult)
  896. }
  897. }
  898. func (c *compiler) compileWithStatement(v *ast.WithStatement, needResult bool) {
  899. if c.scope.strict {
  900. c.throwSyntaxError(int(v.With)-1, "Strict mode code may not include a with statement")
  901. return
  902. }
  903. c.compileExpression(v.Object).emitGetter(true)
  904. c.emit(enterWith)
  905. c.block = &block{
  906. outer: c.block,
  907. typ: blockWith,
  908. needResult: needResult,
  909. }
  910. c.newBlockScope()
  911. c.scope.dynamic = true
  912. c.compileStatement(v.Body, needResult)
  913. c.emit(leaveWith)
  914. c.leaveBlock()
  915. c.popScope()
  916. }
  917. func (c *compiler) compileSwitchStatement(v *ast.SwitchStatement, needResult bool) {
  918. c.block = &block{
  919. typ: blockSwitch,
  920. outer: c.block,
  921. needResult: needResult,
  922. }
  923. c.compileExpression(v.Discriminant).emitGetter(true)
  924. var funcs []*ast.FunctionDeclaration
  925. for _, s := range v.Body {
  926. f := c.extractFunctions(s.Consequent)
  927. funcs = append(funcs, f...)
  928. }
  929. var scopeDeclared bool
  930. if len(funcs) > 0 {
  931. c.newBlockScope()
  932. scopeDeclared = true
  933. c.createFunctionBindings(funcs)
  934. }
  935. for _, s := range v.Body {
  936. scopeDeclared = c.compileLexicalDeclarations(s.Consequent, scopeDeclared)
  937. }
  938. var enter *enterBlock
  939. var db *binding
  940. if scopeDeclared {
  941. c.block = &block{
  942. typ: blockScope,
  943. outer: c.block,
  944. needResult: needResult,
  945. }
  946. enter = &enterBlock{}
  947. c.emit(enter)
  948. // create anonymous variable for the discriminant
  949. bindings := c.scope.bindings
  950. var bb []*binding
  951. if cap(bindings) == len(bindings) {
  952. bb = make([]*binding, len(bindings)+1)
  953. } else {
  954. bb = bindings[:len(bindings)+1]
  955. }
  956. copy(bb[1:], bindings)
  957. db = &binding{
  958. scope: c.scope,
  959. isConst: true,
  960. isStrict: true,
  961. }
  962. bb[0] = db
  963. c.scope.bindings = bb
  964. }
  965. c.compileFunctions(funcs)
  966. if needResult {
  967. c.emit(clearResult)
  968. }
  969. jumps := make([]int, len(v.Body))
  970. for i, s := range v.Body {
  971. if s.Test != nil {
  972. if db != nil {
  973. db.emitGet()
  974. } else {
  975. c.emit(dup)
  976. }
  977. c.compileExpression(s.Test).emitGetter(true)
  978. c.emit(op_strict_eq)
  979. if db != nil {
  980. c.emit(jne(2))
  981. } else {
  982. c.emit(jne(3), pop)
  983. }
  984. jumps[i] = len(c.p.code)
  985. c.emit(nil)
  986. }
  987. }
  988. if db == nil {
  989. c.emit(pop)
  990. }
  991. jumpNoMatch := -1
  992. if v.Default != -1 {
  993. if v.Default != 0 {
  994. jumps[v.Default] = len(c.p.code)
  995. c.emit(nil)
  996. }
  997. } else {
  998. jumpNoMatch = len(c.p.code)
  999. c.emit(nil)
  1000. }
  1001. for i, s := range v.Body {
  1002. if s.Test != nil || i != 0 {
  1003. c.p.code[jumps[i]] = jump(len(c.p.code) - jumps[i])
  1004. }
  1005. c.compileStatements(s.Consequent, needResult)
  1006. }
  1007. if jumpNoMatch != -1 {
  1008. c.p.code[jumpNoMatch] = jump(len(c.p.code) - jumpNoMatch)
  1009. }
  1010. if enter != nil {
  1011. c.leaveScopeBlock(enter)
  1012. enter.stackSize--
  1013. c.popScope()
  1014. }
  1015. c.leaveBlock()
  1016. }