1package goja
2
3import (
4	"fmt"
5	"github.com/dop251/goja/ast"
6	"github.com/dop251/goja/file"
7	"github.com/dop251/goja/token"
8	"github.com/dop251/goja/unistring"
9)
10
11type compiledExpr interface {
12	emitGetter(putOnStack bool)
13	emitSetter(valueExpr compiledExpr, putOnStack bool)
14	emitRef()
15	emitUnary(prepare, body func(), postfix, putOnStack bool)
16	deleteExpr() compiledExpr
17	constant() bool
18	addSrcMap()
19}
20
21type compiledExprOrRef interface {
22	compiledExpr
23	emitGetterOrRef()
24}
25
26type compiledCallExpr struct {
27	baseCompiledExpr
28	args   []compiledExpr
29	callee compiledExpr
30
31	isVariadic bool
32}
33
34type compiledNewExpr struct {
35	compiledCallExpr
36}
37
38type compiledObjectLiteral struct {
39	baseCompiledExpr
40	expr *ast.ObjectLiteral
41}
42
43type compiledArrayLiteral struct {
44	baseCompiledExpr
45	expr *ast.ArrayLiteral
46}
47
48type compiledRegexpLiteral struct {
49	baseCompiledExpr
50	expr *ast.RegExpLiteral
51}
52
53type compiledLiteral struct {
54	baseCompiledExpr
55	val Value
56}
57
58type compiledTemplateLiteral struct {
59	baseCompiledExpr
60	tag         compiledExpr
61	elements    []*ast.TemplateElement
62	expressions []compiledExpr
63}
64
65type compiledAssignExpr struct {
66	baseCompiledExpr
67	left, right compiledExpr
68	operator    token.Token
69}
70
71type compiledObjectAssignmentPattern struct {
72	baseCompiledExpr
73	expr *ast.ObjectPattern
74}
75
76type compiledArrayAssignmentPattern struct {
77	baseCompiledExpr
78	expr *ast.ArrayPattern
79}
80
81type deleteGlobalExpr struct {
82	baseCompiledExpr
83	name unistring.String
84}
85
86type deleteVarExpr struct {
87	baseCompiledExpr
88	name unistring.String
89}
90
91type deletePropExpr struct {
92	baseCompiledExpr
93	left compiledExpr
94	name unistring.String
95}
96
97type deleteElemExpr struct {
98	baseCompiledExpr
99	left, member compiledExpr
100}
101
102type constantExpr struct {
103	baseCompiledExpr
104	val Value
105}
106
107type baseCompiledExpr struct {
108	c      *compiler
109	offset int
110}
111
112type compiledIdentifierExpr struct {
113	baseCompiledExpr
114	name unistring.String
115}
116
117type compiledFunctionLiteral struct {
118	baseCompiledExpr
119	name            *ast.Identifier
120	parameterList   *ast.ParameterList
121	body            []ast.Statement
122	source          string
123	declarationList []*ast.VariableDeclaration
124	lhsName         unistring.String
125	strict          *ast.StringLiteral
126	isExpr          bool
127	isArrow         bool
128}
129
130type compiledBracketExpr struct {
131	baseCompiledExpr
132	left, member compiledExpr
133}
134
135type compiledThisExpr struct {
136	baseCompiledExpr
137}
138
139type compiledNewTarget struct {
140	baseCompiledExpr
141}
142
143type compiledSequenceExpr struct {
144	baseCompiledExpr
145	sequence []compiledExpr
146}
147
148type compiledUnaryExpr struct {
149	baseCompiledExpr
150	operand  compiledExpr
151	operator token.Token
152	postfix  bool
153}
154
155type compiledConditionalExpr struct {
156	baseCompiledExpr
157	test, consequent, alternate compiledExpr
158}
159
160type compiledLogicalOr struct {
161	baseCompiledExpr
162	left, right compiledExpr
163}
164
165type compiledLogicalAnd struct {
166	baseCompiledExpr
167	left, right compiledExpr
168}
169
170type compiledBinaryExpr struct {
171	baseCompiledExpr
172	left, right compiledExpr
173	operator    token.Token
174}
175
176type compiledEnumGetExpr struct {
177	baseCompiledExpr
178}
179
180type defaultDeleteExpr struct {
181	baseCompiledExpr
182	expr compiledExpr
183}
184
185type compiledSpreadCallArgument struct {
186	baseCompiledExpr
187	expr compiledExpr
188}
189
190func (e *defaultDeleteExpr) emitGetter(putOnStack bool) {
191	e.expr.emitGetter(false)
192	if putOnStack {
193		e.c.emit(loadVal(e.c.p.defineLiteralValue(valueTrue)))
194	}
195}
196
197func (c *compiler) compileExpression(v ast.Expression) compiledExpr {
198	// log.Printf("compileExpression: %T", v)
199	switch v := v.(type) {
200	case nil:
201		return nil
202	case *ast.AssignExpression:
203		return c.compileAssignExpression(v)
204	case *ast.NumberLiteral:
205		return c.compileNumberLiteral(v)
206	case *ast.StringLiteral:
207		return c.compileStringLiteral(v)
208	case *ast.TemplateLiteral:
209		return c.compileTemplateLiteral(v)
210	case *ast.BooleanLiteral:
211		return c.compileBooleanLiteral(v)
212	case *ast.NullLiteral:
213		r := &compiledLiteral{
214			val: _null,
215		}
216		r.init(c, v.Idx0())
217		return r
218	case *ast.Identifier:
219		return c.compileIdentifierExpression(v)
220	case *ast.CallExpression:
221		return c.compileCallExpression(v)
222	case *ast.ObjectLiteral:
223		return c.compileObjectLiteral(v)
224	case *ast.ArrayLiteral:
225		return c.compileArrayLiteral(v)
226	case *ast.RegExpLiteral:
227		return c.compileRegexpLiteral(v)
228	case *ast.BinaryExpression:
229		return c.compileBinaryExpression(v)
230	case *ast.UnaryExpression:
231		return c.compileUnaryExpression(v)
232	case *ast.ConditionalExpression:
233		return c.compileConditionalExpression(v)
234	case *ast.FunctionLiteral:
235		return c.compileFunctionLiteral(v, true)
236	case *ast.ArrowFunctionLiteral:
237		return c.compileArrowFunctionLiteral(v)
238	case *ast.DotExpression:
239		r := &compiledDotExpr{
240			left: c.compileExpression(v.Left),
241			name: v.Identifier.Name,
242		}
243		r.init(c, v.Idx0())
244		return r
245	case *ast.BracketExpression:
246		r := &compiledBracketExpr{
247			left:   c.compileExpression(v.Left),
248			member: c.compileExpression(v.Member),
249		}
250		r.init(c, v.Idx0())
251		return r
252	case *ast.ThisExpression:
253		r := &compiledThisExpr{}
254		r.init(c, v.Idx0())
255		return r
256	case *ast.SequenceExpression:
257		return c.compileSequenceExpression(v)
258	case *ast.NewExpression:
259		return c.compileNewExpression(v)
260	case *ast.MetaProperty:
261		return c.compileMetaProperty(v)
262	case *ast.ObjectPattern:
263		return c.compileObjectAssignmentPattern(v)
264	case *ast.ArrayPattern:
265		return c.compileArrayAssignmentPattern(v)
266	default:
267		panic(fmt.Errorf("Unknown expression type: %T", v))
268	}
269}
270
271func (e *baseCompiledExpr) constant() bool {
272	return false
273}
274
275func (e *baseCompiledExpr) init(c *compiler, idx file.Idx) {
276	e.c = c
277	e.offset = int(idx) - 1
278}
279
280func (e *baseCompiledExpr) emitSetter(compiledExpr, bool) {
281	e.c.throwSyntaxError(e.offset, "Not a valid left-value expression")
282}
283
284func (e *baseCompiledExpr) emitRef() {
285	e.c.throwSyntaxError(e.offset, "Cannot emit reference for this type of expression")
286}
287
288func (e *baseCompiledExpr) deleteExpr() compiledExpr {
289	r := &constantExpr{
290		val: valueTrue,
291	}
292	r.init(e.c, file.Idx(e.offset+1))
293	return r
294}
295
296func (e *baseCompiledExpr) emitUnary(func(), func(), bool, bool) {
297	e.c.throwSyntaxError(e.offset, "Not a valid left-value expression")
298}
299
300func (e *baseCompiledExpr) addSrcMap() {
301	if e.offset > 0 {
302		e.c.p.srcMap = append(e.c.p.srcMap, srcMapItem{pc: len(e.c.p.code), srcPos: e.offset})
303	}
304}
305
306func (e *constantExpr) emitGetter(putOnStack bool) {
307	if putOnStack {
308		e.addSrcMap()
309		e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val)))
310	}
311}
312
313func (e *compiledIdentifierExpr) emitGetter(putOnStack bool) {
314	e.addSrcMap()
315	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
316		if b != nil {
317			if putOnStack {
318				b.emitGet()
319			} else {
320				b.emitGetP()
321			}
322		} else {
323			panic("No dynamics and not found")
324		}
325	} else {
326		if b != nil {
327			b.emitGetVar(false)
328		} else {
329			e.c.emit(loadDynamic(e.name))
330		}
331		if !putOnStack {
332			e.c.emit(pop)
333		}
334	}
335}
336
337func (e *compiledIdentifierExpr) emitGetterOrRef() {
338	e.addSrcMap()
339	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
340		if b != nil {
341			b.emitGet()
342		} else {
343			panic("No dynamics and not found")
344		}
345	} else {
346		if b != nil {
347			b.emitGetVar(false)
348		} else {
349			e.c.emit(loadDynamicRef(e.name))
350		}
351	}
352}
353
354func (e *compiledIdentifierExpr) emitGetterAndCallee() {
355	e.addSrcMap()
356	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
357		if b != nil {
358			e.c.emit(loadUndef)
359			b.emitGet()
360		} else {
361			panic("No dynamics and not found")
362		}
363	} else {
364		if b != nil {
365			b.emitGetVar(true)
366		} else {
367			e.c.emit(loadDynamicCallee(e.name))
368		}
369	}
370}
371
372func (c *compiler) emitVarSetter1(name unistring.String, offset int, putOnStack bool, emitRight func(isRef bool)) {
373	if c.scope.strict {
374		c.checkIdentifierLName(name, offset)
375	}
376
377	if b, noDynamics := c.scope.lookupName(name); noDynamics {
378		emitRight(false)
379		if b != nil {
380			if putOnStack {
381				b.emitSet()
382			} else {
383				b.emitSetP()
384			}
385		} else {
386			if c.scope.strict {
387				c.emit(setGlobalStrict(name))
388			} else {
389				c.emit(setGlobal(name))
390			}
391			if !putOnStack {
392				c.emit(pop)
393			}
394		}
395	} else {
396		if b != nil {
397			b.emitResolveVar(c.scope.strict)
398		} else {
399			if c.scope.strict {
400				c.emit(resolveVar1Strict(name))
401			} else {
402				c.emit(resolveVar1(name))
403			}
404		}
405		emitRight(true)
406		if putOnStack {
407			c.emit(putValue)
408		} else {
409			c.emit(putValueP)
410		}
411	}
412}
413
414func (c *compiler) emitVarSetter(name unistring.String, offset int, valueExpr compiledExpr, putOnStack bool) {
415	c.emitVarSetter1(name, offset, putOnStack, func(bool) {
416		c.emitExpr(valueExpr, true)
417	})
418}
419
420func (c *compiler) emitVarRef(name unistring.String, offset int) {
421	if c.scope.strict {
422		c.checkIdentifierLName(name, offset)
423	}
424
425	b, _ := c.scope.lookupName(name)
426	if b != nil {
427		b.emitResolveVar(c.scope.strict)
428	} else {
429		if c.scope.strict {
430			c.emit(resolveVar1Strict(name))
431		} else {
432			c.emit(resolveVar1(name))
433		}
434	}
435}
436
437func (e *compiledIdentifierExpr) emitRef() {
438	e.c.emitVarRef(e.name, e.offset)
439}
440
441func (e *compiledIdentifierExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
442	e.c.emitVarSetter(e.name, e.offset, valueExpr, putOnStack)
443}
444
445func (e *compiledIdentifierExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
446	if putOnStack {
447		e.c.emitVarSetter1(e.name, e.offset, true, func(isRef bool) {
448			e.c.emit(loadUndef)
449			if isRef {
450				e.c.emit(getValue)
451			} else {
452				e.emitGetter(true)
453			}
454			if prepare != nil {
455				prepare()
456			}
457			if !postfix {
458				body()
459			}
460			e.c.emit(rdupN(1))
461			if postfix {
462				body()
463			}
464		})
465		e.c.emit(pop)
466	} else {
467		e.c.emitVarSetter1(e.name, e.offset, false, func(isRef bool) {
468			if isRef {
469				e.c.emit(getValue)
470			} else {
471				e.emitGetter(true)
472			}
473			body()
474		})
475	}
476}
477
478func (e *compiledIdentifierExpr) deleteExpr() compiledExpr {
479	if e.c.scope.strict {
480		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
481		panic("Unreachable")
482	}
483	if b, noDynamics := e.c.scope.lookupName(e.name); noDynamics {
484		if b == nil {
485			r := &deleteGlobalExpr{
486				name: e.name,
487			}
488			r.init(e.c, file.Idx(0))
489			return r
490		}
491	} else {
492		if b == nil {
493			r := &deleteVarExpr{
494				name: e.name,
495			}
496			r.init(e.c, file.Idx(e.offset+1))
497			return r
498		}
499	}
500	r := &compiledLiteral{
501		val: valueFalse,
502	}
503	r.init(e.c, file.Idx(e.offset+1))
504	return r
505}
506
507type compiledDotExpr struct {
508	baseCompiledExpr
509	left compiledExpr
510	name unistring.String
511}
512
513func (e *compiledDotExpr) emitGetter(putOnStack bool) {
514	e.left.emitGetter(true)
515	e.addSrcMap()
516	e.c.emit(getProp(e.name))
517	if !putOnStack {
518		e.c.emit(pop)
519	}
520}
521
522func (e *compiledDotExpr) emitRef() {
523	e.left.emitGetter(true)
524	if e.c.scope.strict {
525		e.c.emit(getPropRefStrict(e.name))
526	} else {
527		e.c.emit(getPropRef(e.name))
528	}
529}
530
531func (e *compiledDotExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
532	e.left.emitGetter(true)
533	valueExpr.emitGetter(true)
534	if e.c.scope.strict {
535		if putOnStack {
536			e.c.emit(setPropStrict(e.name))
537		} else {
538			e.c.emit(setPropStrictP(e.name))
539		}
540	} else {
541		if putOnStack {
542			e.c.emit(setProp(e.name))
543		} else {
544			e.c.emit(setPropP(e.name))
545		}
546	}
547}
548
549func (e *compiledDotExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
550	if !putOnStack {
551		e.left.emitGetter(true)
552		e.c.emit(dup)
553		e.c.emit(getProp(e.name))
554		body()
555		if e.c.scope.strict {
556			e.c.emit(setPropStrict(e.name), pop)
557		} else {
558			e.c.emit(setProp(e.name), pop)
559		}
560	} else {
561		if !postfix {
562			e.left.emitGetter(true)
563			e.c.emit(dup)
564			e.c.emit(getProp(e.name))
565			if prepare != nil {
566				prepare()
567			}
568			body()
569			if e.c.scope.strict {
570				e.c.emit(setPropStrict(e.name))
571			} else {
572				e.c.emit(setProp(e.name))
573			}
574		} else {
575			e.c.emit(loadUndef)
576			e.left.emitGetter(true)
577			e.c.emit(dup)
578			e.c.emit(getProp(e.name))
579			if prepare != nil {
580				prepare()
581			}
582			e.c.emit(rdupN(2))
583			body()
584			if e.c.scope.strict {
585				e.c.emit(setPropStrict(e.name))
586			} else {
587				e.c.emit(setProp(e.name))
588			}
589			e.c.emit(pop)
590		}
591	}
592}
593
594func (e *compiledDotExpr) deleteExpr() compiledExpr {
595	r := &deletePropExpr{
596		left: e.left,
597		name: e.name,
598	}
599	r.init(e.c, file.Idx(0))
600	return r
601}
602
603func (e *compiledBracketExpr) emitGetter(putOnStack bool) {
604	e.left.emitGetter(true)
605	e.member.emitGetter(true)
606	e.addSrcMap()
607	e.c.emit(getElem)
608	if !putOnStack {
609		e.c.emit(pop)
610	}
611}
612
613func (e *compiledBracketExpr) emitRef() {
614	e.left.emitGetter(true)
615	e.member.emitGetter(true)
616	if e.c.scope.strict {
617		e.c.emit(getElemRefStrict)
618	} else {
619		e.c.emit(getElemRef)
620	}
621}
622
623func (e *compiledBracketExpr) emitSetter(valueExpr compiledExpr, putOnStack bool) {
624	e.left.emitGetter(true)
625	e.member.emitGetter(true)
626	valueExpr.emitGetter(true)
627	if e.c.scope.strict {
628		if putOnStack {
629			e.c.emit(setElemStrict)
630		} else {
631			e.c.emit(setElemStrictP)
632		}
633	} else {
634		if putOnStack {
635			e.c.emit(setElem)
636		} else {
637			e.c.emit(setElemP)
638		}
639	}
640}
641
642func (e *compiledBracketExpr) emitUnary(prepare, body func(), postfix, putOnStack bool) {
643	if !putOnStack {
644		e.left.emitGetter(true)
645		e.member.emitGetter(true)
646		e.c.emit(dupN(1), dupN(1))
647		e.c.emit(getElem)
648		body()
649		if e.c.scope.strict {
650			e.c.emit(setElemStrict, pop)
651		} else {
652			e.c.emit(setElem, pop)
653		}
654	} else {
655		if !postfix {
656			e.left.emitGetter(true)
657			e.member.emitGetter(true)
658			e.c.emit(dupN(1), dupN(1))
659			e.c.emit(getElem)
660			if prepare != nil {
661				prepare()
662			}
663			body()
664			if e.c.scope.strict {
665				e.c.emit(setElemStrict)
666			} else {
667				e.c.emit(setElem)
668			}
669		} else {
670			e.c.emit(loadUndef)
671			e.left.emitGetter(true)
672			e.member.emitGetter(true)
673			e.c.emit(dupN(1), dupN(1))
674			e.c.emit(getElem)
675			if prepare != nil {
676				prepare()
677			}
678			e.c.emit(rdupN(3))
679			body()
680			if e.c.scope.strict {
681				e.c.emit(setElemStrict, pop)
682			} else {
683				e.c.emit(setElem, pop)
684			}
685		}
686	}
687}
688
689func (e *compiledBracketExpr) deleteExpr() compiledExpr {
690	r := &deleteElemExpr{
691		left:   e.left,
692		member: e.member,
693	}
694	r.init(e.c, file.Idx(0))
695	return r
696}
697
698func (e *deleteElemExpr) emitGetter(putOnStack bool) {
699	e.left.emitGetter(true)
700	e.member.emitGetter(true)
701	e.addSrcMap()
702	if e.c.scope.strict {
703		e.c.emit(deleteElemStrict)
704	} else {
705		e.c.emit(deleteElem)
706	}
707	if !putOnStack {
708		e.c.emit(pop)
709	}
710}
711
712func (e *deletePropExpr) emitGetter(putOnStack bool) {
713	e.left.emitGetter(true)
714	e.addSrcMap()
715	if e.c.scope.strict {
716		e.c.emit(deletePropStrict(e.name))
717	} else {
718		e.c.emit(deleteProp(e.name))
719	}
720	if !putOnStack {
721		e.c.emit(pop)
722	}
723}
724
725func (e *deleteVarExpr) emitGetter(putOnStack bool) {
726	/*if e.c.scope.strict {
727		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
728		return
729	}*/
730	e.c.emit(deleteVar(e.name))
731	if !putOnStack {
732		e.c.emit(pop)
733	}
734}
735
736func (e *deleteGlobalExpr) emitGetter(putOnStack bool) {
737	/*if e.c.scope.strict {
738		e.c.throwSyntaxError(e.offset, "Delete of an unqualified identifier in strict mode")
739		return
740	}*/
741
742	e.c.emit(deleteGlobal(e.name))
743	if !putOnStack {
744		e.c.emit(pop)
745	}
746}
747
748func (e *compiledAssignExpr) emitGetter(putOnStack bool) {
749	e.addSrcMap()
750	switch e.operator {
751	case token.ASSIGN:
752		if fn, ok := e.right.(*compiledFunctionLiteral); ok {
753			if fn.name == nil {
754				if id, ok := e.left.(*compiledIdentifierExpr); ok {
755					fn.lhsName = id.name
756				}
757			}
758		}
759		e.left.emitSetter(e.right, putOnStack)
760	case token.PLUS:
761		e.left.emitUnary(nil, func() {
762			e.right.emitGetter(true)
763			e.c.emit(add)
764		}, false, putOnStack)
765	case token.MINUS:
766		e.left.emitUnary(nil, func() {
767			e.right.emitGetter(true)
768			e.c.emit(sub)
769		}, false, putOnStack)
770	case token.MULTIPLY:
771		e.left.emitUnary(nil, func() {
772			e.right.emitGetter(true)
773			e.c.emit(mul)
774		}, false, putOnStack)
775	case token.SLASH:
776		e.left.emitUnary(nil, func() {
777			e.right.emitGetter(true)
778			e.c.emit(div)
779		}, false, putOnStack)
780	case token.REMAINDER:
781		e.left.emitUnary(nil, func() {
782			e.right.emitGetter(true)
783			e.c.emit(mod)
784		}, false, putOnStack)
785	case token.OR:
786		e.left.emitUnary(nil, func() {
787			e.right.emitGetter(true)
788			e.c.emit(or)
789		}, false, putOnStack)
790	case token.AND:
791		e.left.emitUnary(nil, func() {
792			e.right.emitGetter(true)
793			e.c.emit(and)
794		}, false, putOnStack)
795	case token.EXCLUSIVE_OR:
796		e.left.emitUnary(nil, func() {
797			e.right.emitGetter(true)
798			e.c.emit(xor)
799		}, false, putOnStack)
800	case token.SHIFT_LEFT:
801		e.left.emitUnary(nil, func() {
802			e.right.emitGetter(true)
803			e.c.emit(sal)
804		}, false, putOnStack)
805	case token.SHIFT_RIGHT:
806		e.left.emitUnary(nil, func() {
807			e.right.emitGetter(true)
808			e.c.emit(sar)
809		}, false, putOnStack)
810	case token.UNSIGNED_SHIFT_RIGHT:
811		e.left.emitUnary(nil, func() {
812			e.right.emitGetter(true)
813			e.c.emit(shr)
814		}, false, putOnStack)
815	default:
816		panic(fmt.Errorf("Unknown assign operator: %s", e.operator.String()))
817	}
818}
819
820func (e *compiledLiteral) emitGetter(putOnStack bool) {
821	if putOnStack {
822		e.addSrcMap()
823		e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val)))
824	}
825}
826
827func (e *compiledLiteral) constant() bool {
828	return true
829}
830
831func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) {
832	if e.tag == nil {
833		if len(e.elements) == 0 {
834			e.c.emit(loadVal(e.c.p.defineLiteralValue(stringEmpty)))
835		} else {
836			tail := e.elements[len(e.elements)-1].Parsed
837			if len(e.elements) == 1 {
838				e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail))))
839			} else {
840				stringCount := 0
841				if head := e.elements[0].Parsed; head != "" {
842					e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(head))))
843					stringCount++
844				}
845				e.expressions[0].emitGetter(true)
846				e.c.emit(_toString{})
847				stringCount++
848				for i := 1; i < len(e.elements)-1; i++ {
849					if elt := e.elements[i].Parsed; elt != "" {
850						e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(elt))))
851						stringCount++
852					}
853					e.expressions[i].emitGetter(true)
854					e.c.emit(_toString{})
855					stringCount++
856				}
857				if tail != "" {
858					e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail))))
859					stringCount++
860				}
861				e.c.emit(concatStrings(stringCount))
862			}
863		}
864	} else {
865		cooked := make([]Value, len(e.elements))
866		raw := make([]Value, len(e.elements))
867		for i, elt := range e.elements {
868			raw[i] = &valueProperty{
869				enumerable: true,
870				value:      newStringValue(elt.Literal),
871			}
872			var cookedVal Value
873			if elt.Valid {
874				cookedVal = stringValueFromRaw(elt.Parsed)
875			} else {
876				cookedVal = _undefined
877			}
878			cooked[i] = &valueProperty{
879				enumerable: true,
880				value:      cookedVal,
881			}
882		}
883		e.c.emitCallee(e.tag)
884		e.c.emit(&getTaggedTmplObject{
885			raw:    raw,
886			cooked: cooked,
887		})
888		for _, expr := range e.expressions {
889			expr.emitGetter(true)
890		}
891		e.c.emit(call(len(e.expressions) + 1))
892	}
893	if !putOnStack {
894		e.c.emit(pop)
895	}
896}
897
898func (c *compiler) compileParameterBindingIdentifier(name unistring.String, offset int) (*binding, bool) {
899	if c.scope.strict {
900		c.checkIdentifierName(name, offset)
901		c.checkIdentifierLName(name, offset)
902	}
903	return c.scope.bindNameShadow(name)
904}
905
906func (c *compiler) compileParameterPatternIdBinding(name unistring.String, offset int) {
907	if _, unique := c.compileParameterBindingIdentifier(name, offset); !unique {
908		c.throwSyntaxError(offset, "Duplicate parameter name not allowed in this context")
909	}
910}
911
912func (c *compiler) compileParameterPatternBinding(item ast.Expression) {
913	c.createBindings(item, c.compileParameterPatternIdBinding)
914}
915
916func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
917	savedPrg := e.c.p
918	e.c.p = &Program{
919		src: e.c.p.src,
920	}
921	e.c.newScope()
922	s := e.c.scope
923	s.function = true
924	s.arrow = e.isArrow
925
926	var name unistring.String
927	if e.name != nil {
928		name = e.name.Name
929	} else {
930		name = e.lhsName
931	}
932
933	if name != "" {
934		e.c.p.funcName = name
935	}
936	savedBlock := e.c.block
937	defer func() {
938		e.c.block = savedBlock
939	}()
940
941	e.c.block = &block{
942		typ: blockScope,
943	}
944
945	if !s.strict {
946		s.strict = e.strict != nil
947	}
948
949	hasPatterns := false
950	hasInits := false
951	firstDupIdx := -1
952	length := 0
953
954	if e.parameterList.Rest != nil {
955		hasPatterns = true // strictly speaking not, but we need to activate all the checks
956	}
957
958	// First, make sure that the first bindings correspond to the formal parameters
959	for _, item := range e.parameterList.List {
960		switch tgt := item.Target.(type) {
961		case *ast.Identifier:
962			offset := int(tgt.Idx) - 1
963			b, unique := e.c.compileParameterBindingIdentifier(tgt.Name, offset)
964			if !unique {
965				firstDupIdx = offset
966			}
967			b.isArg = true
968		case ast.Pattern:
969			b := s.addBinding(int(item.Idx0()) - 1)
970			b.isArg = true
971			hasPatterns = true
972		default:
973			e.c.throwSyntaxError(int(item.Idx0())-1, "Unsupported BindingElement type: %T", item)
974			return
975		}
976		if item.Initializer != nil {
977			hasInits = true
978		}
979
980		if firstDupIdx >= 0 && (hasPatterns || hasInits || s.strict || e.isArrow) {
981			e.c.throwSyntaxError(firstDupIdx, "Duplicate parameter name not allowed in this context")
982			return
983		}
984
985		if (hasPatterns || hasInits) && e.strict != nil {
986			e.c.throwSyntaxError(int(e.strict.Idx)-1, "Illegal 'use strict' directive in function with non-simple parameter list")
987			return
988		}
989
990		if !hasInits {
991			length++
992		}
993	}
994
995	// create pattern bindings
996	if hasPatterns {
997		for _, item := range e.parameterList.List {
998			switch tgt := item.Target.(type) {
999			case *ast.Identifier:
1000				// we already created those in the previous loop, skipping
1001			default:
1002				e.c.compileParameterPatternBinding(tgt)
1003			}
1004		}
1005		if rest := e.parameterList.Rest; rest != nil {
1006			e.c.compileParameterPatternBinding(rest)
1007		}
1008	}
1009
1010	paramsCount := len(e.parameterList.List)
1011
1012	s.numArgs = paramsCount
1013	body := e.body
1014	funcs := e.c.extractFunctions(body)
1015	var calleeBinding *binding
1016	preambleLen := 4 // enter, boxThis, createArgs, set
1017	e.c.p.code = make([]instruction, preambleLen, 8)
1018
1019	emitArgsRestMark := -1
1020	firstForwardRef := -1
1021	enterFunc2Mark := -1
1022
1023	if hasPatterns || hasInits {
1024		if e.isExpr && e.name != nil {
1025			if b, created := s.bindNameLexical(e.name.Name, false, 0); created {
1026				b.isConst = true
1027				calleeBinding = b
1028			}
1029		}
1030		if calleeBinding != nil {
1031			e.c.emit(loadCallee)
1032			calleeBinding.emitInit()
1033		}
1034		for i, item := range e.parameterList.List {
1035			if pattern, ok := item.Target.(ast.Pattern); ok {
1036				i := i
1037				e.c.compilePatternInitExpr(func() {
1038					if firstForwardRef == -1 {
1039						s.bindings[i].emitGet()
1040					} else {
1041						e.c.emit(loadStackLex(-i - 1))
1042					}
1043				}, item.Initializer, item.Target.Idx0()).emitGetter(true)
1044				e.c.emitPattern(pattern, func(target, init compiledExpr) {
1045					e.c.emitPatternLexicalAssign(target, init, false)
1046				}, false)
1047			} else if item.Initializer != nil {
1048				markGet := len(e.c.p.code)
1049				e.c.emit(nil)
1050				mark := len(e.c.p.code)
1051				e.c.emit(nil)
1052				e.c.compileExpression(item.Initializer).emitGetter(true)
1053				if firstForwardRef == -1 && (s.isDynamic() || s.bindings[i].useCount() > 0) {
1054					firstForwardRef = i
1055				}
1056				if firstForwardRef == -1 {
1057					s.bindings[i].emitGetAt(markGet)
1058				} else {
1059					e.c.p.code[markGet] = loadStackLex(-i - 1)
1060				}
1061				s.bindings[i].emitInit()
1062				e.c.p.code[mark] = jdefP(len(e.c.p.code) - mark)
1063			} else {
1064				if firstForwardRef == -1 && s.bindings[i].useCount() > 0 {
1065					firstForwardRef = i
1066				}
1067				if firstForwardRef != -1 {
1068					e.c.emit(loadStackLex(-i - 1))
1069					s.bindings[i].emitInit()
1070				}
1071			}
1072		}
1073		if rest := e.parameterList.Rest; rest != nil {
1074			e.c.emitAssign(rest, e.c.compileEmitterExpr(
1075				func() {
1076					emitArgsRestMark = len(e.c.p.code)
1077					e.c.emit(createArgsRestStack(paramsCount))
1078				}, rest.Idx0()),
1079				func(target, init compiledExpr) {
1080					e.c.emitPatternLexicalAssign(target, init, false)
1081				})
1082		}
1083		if firstForwardRef != -1 {
1084			for _, b := range s.bindings {
1085				b.inStash = true
1086			}
1087			s.argsInStash = true
1088			s.needStash = true
1089		}
1090
1091		e.c.newBlockScope()
1092		varScope := e.c.scope
1093		varScope.variable = true
1094		enterFunc2Mark = len(e.c.p.code)
1095		e.c.emit(nil)
1096		e.c.compileDeclList(e.declarationList, false)
1097		e.c.createFunctionBindings(funcs)
1098		e.c.compileLexicalDeclarationsFuncBody(body, calleeBinding)
1099		for _, b := range varScope.bindings {
1100			if b.isVar {
1101				if parentBinding := s.boundNames[b.name]; parentBinding != nil && parentBinding != calleeBinding {
1102					parentBinding.emitGet()
1103					b.emitSetP()
1104				}
1105			}
1106		}
1107	} else {
1108		// To avoid triggering variable conflict when binding from non-strict direct eval().
1109		// Parameters are supposed to be in a parent scope, hence no conflict.
1110		for _, b := range s.bindings[:paramsCount] {
1111			b.isVar = true
1112		}
1113		e.c.compileDeclList(e.declarationList, true)
1114		e.c.createFunctionBindings(funcs)
1115		e.c.compileLexicalDeclarations(body, true)
1116		if e.isExpr && e.name != nil {
1117			if b, created := s.bindNameLexical(e.name.Name, false, 0); created {
1118				b.isConst = true
1119				calleeBinding = b
1120			}
1121		}
1122		if calleeBinding != nil {
1123			e.c.emit(loadCallee)
1124			calleeBinding.emitInit()
1125		}
1126	}
1127
1128	e.c.compileFunctions(funcs)
1129	e.c.compileStatements(body, false)
1130
1131	var last ast.Statement
1132	if l := len(body); l > 0 {
1133		last = body[l-1]
1134	}
1135	if _, ok := last.(*ast.ReturnStatement); !ok {
1136		e.c.emit(loadUndef, ret)
1137	}
1138
1139	delta := 0
1140	code := e.c.p.code
1141
1142	if calleeBinding != nil && !s.isDynamic() && calleeBinding.useCount() == 1 {
1143		s.deleteBinding(calleeBinding)
1144		preambleLen += 2
1145	}
1146
1147	if !s.argsInStash && (s.argsNeeded || s.isDynamic()) {
1148		s.moveArgsToStash()
1149	}
1150
1151	if s.argsNeeded {
1152		b, created := s.bindNameLexical("arguments", false, 0)
1153		if !created && !b.isVar {
1154			s.argsNeeded = false
1155		} else {
1156			if s.strict {
1157				b.isConst = true
1158			} else {
1159				b.isVar = e.c.scope.function
1160			}
1161			pos := preambleLen - 2
1162			delta += 2
1163			if s.strict || hasPatterns || hasInits {
1164				code[pos] = createArgsUnmapped(paramsCount)
1165			} else {
1166				code[pos] = createArgsMapped(paramsCount)
1167			}
1168			pos++
1169			b.markAccessPointAtScope(s, pos)
1170			code[pos] = storeStashP(0)
1171		}
1172	}
1173
1174	stashSize, stackSize := s.finaliseVarAlloc(0)
1175
1176	if !s.strict && s.thisNeeded {
1177		delta++
1178		code[preambleLen-delta] = boxThis
1179	}
1180	delta++
1181	delta = preambleLen - delta
1182	var enter instruction
1183	if stashSize > 0 || s.argsInStash {
1184		if firstForwardRef == -1 {
1185			enter1 := enterFunc{
1186				numArgs:     uint32(paramsCount),
1187				argsToStash: s.argsInStash,
1188				stashSize:   uint32(stashSize),
1189				stackSize:   uint32(stackSize),
1190				extensible:  s.dynamic,
1191			}
1192			if s.isDynamic() {
1193				enter1.names = s.makeNamesMap()
1194			}
1195			enter = &enter1
1196			if enterFunc2Mark != -1 {
1197				ef2 := &enterFuncBody{
1198					extensible: e.c.scope.dynamic,
1199				}
1200				e.c.updateEnterBlock(&ef2.enterBlock)
1201				e.c.p.code[enterFunc2Mark] = ef2
1202			}
1203		} else {
1204			enter1 := enterFunc1{
1205				stashSize:  uint32(stashSize),
1206				numArgs:    uint32(paramsCount),
1207				argsToCopy: uint32(firstForwardRef),
1208				extensible: s.dynamic,
1209			}
1210			if s.isDynamic() {
1211				enter1.names = s.makeNamesMap()
1212			}
1213			enter = &enter1
1214			if enterFunc2Mark != -1 {
1215				ef2 := &enterFuncBody{
1216					adjustStack: true,
1217					extensible:  e.c.scope.dynamic,
1218				}
1219				e.c.updateEnterBlock(&ef2.enterBlock)
1220				e.c.p.code[enterFunc2Mark] = ef2
1221			}
1222		}
1223		if emitArgsRestMark != -1 && s.argsInStash {
1224			e.c.p.code[emitArgsRestMark] = createArgsRestStash
1225		}
1226	} else {
1227		enter = &enterFuncStashless{
1228			stackSize: uint32(stackSize),
1229			args:      uint32(paramsCount),
1230		}
1231		if enterFunc2Mark != -1 {
1232			ef2 := &enterFuncBody{
1233				extensible: e.c.scope.dynamic,
1234			}
1235			e.c.updateEnterBlock(&ef2.enterBlock)
1236			e.c.p.code[enterFunc2Mark] = ef2
1237		}
1238	}
1239	code[delta] = enter
1240	if delta != 0 {
1241		e.c.p.code = code[delta:]
1242		for i := range e.c.p.srcMap {
1243			e.c.p.srcMap[i].pc -= delta
1244		}
1245		s.adjustBase(-delta)
1246	}
1247
1248	strict := s.strict
1249	p := e.c.p
1250	// e.c.p.dumpCode()
1251	if enterFunc2Mark != -1 {
1252		e.c.popScope()
1253	}
1254	e.c.popScope()
1255	e.c.p = savedPrg
1256	if e.isArrow {
1257		e.c.emit(&newArrowFunc{newFunc: newFunc{prg: p, length: uint32(length), name: name, source: e.source, strict: strict}})
1258	} else {
1259		e.c.emit(&newFunc{prg: p, length: uint32(length), name: name, source: e.source, strict: strict})
1260	}
1261	if !putOnStack {
1262		e.c.emit(pop)
1263	}
1264}
1265
1266func (c *compiler) compileFunctionLiteral(v *ast.FunctionLiteral, isExpr bool) *compiledFunctionLiteral {
1267	strictBody := c.isStrictStatement(v.Body)
1268	if v.Name != nil && (c.scope.strict || strictBody != nil) {
1269		c.checkIdentifierLName(v.Name.Name, int(v.Name.Idx)-1)
1270	}
1271	r := &compiledFunctionLiteral{
1272		name:            v.Name,
1273		parameterList:   v.ParameterList,
1274		body:            v.Body.List,
1275		source:          v.Source,
1276		declarationList: v.DeclarationList,
1277		isExpr:          isExpr,
1278		strict:          strictBody,
1279	}
1280	r.init(c, v.Idx0())
1281	return r
1282}
1283
1284func (c *compiler) compileArrowFunctionLiteral(v *ast.ArrowFunctionLiteral) *compiledFunctionLiteral {
1285	var strictBody *ast.StringLiteral
1286	var body []ast.Statement
1287	switch b := v.Body.(type) {
1288	case *ast.BlockStatement:
1289		strictBody = c.isStrictStatement(b)
1290		body = b.List
1291	case *ast.ExpressionBody:
1292		body = []ast.Statement{
1293			&ast.ReturnStatement{
1294				Argument: b.Expression,
1295			},
1296		}
1297	default:
1298		c.throwSyntaxError(int(b.Idx0())-1, "Unsupported ConciseBody type: %T", b)
1299	}
1300	r := &compiledFunctionLiteral{
1301		parameterList:   v.ParameterList,
1302		body:            body,
1303		source:          v.Source,
1304		declarationList: v.DeclarationList,
1305		isExpr:          true,
1306		isArrow:         true,
1307		strict:          strictBody,
1308	}
1309	r.init(c, v.Idx0())
1310	return r
1311}
1312
1313func (e *compiledThisExpr) emitGetter(putOnStack bool) {
1314	if putOnStack {
1315		e.addSrcMap()
1316		scope := e.c.scope
1317		for ; scope != nil && (scope.arrow || !scope.function && !scope.eval); scope = scope.outer {
1318		}
1319
1320		if scope != nil {
1321			scope.thisNeeded = true
1322			e.c.emit(loadStack(0))
1323		} else {
1324			e.c.emit(loadGlobalObject)
1325		}
1326	}
1327}
1328
1329func (e *compiledNewExpr) emitGetter(putOnStack bool) {
1330	if e.isVariadic {
1331		e.c.emit(startVariadic)
1332	}
1333	e.callee.emitGetter(true)
1334	for _, expr := range e.args {
1335		expr.emitGetter(true)
1336	}
1337	e.addSrcMap()
1338	if e.isVariadic {
1339		e.c.emit(newVariadic, endVariadic)
1340	} else {
1341		e.c.emit(_new(len(e.args)))
1342	}
1343	if !putOnStack {
1344		e.c.emit(pop)
1345	}
1346}
1347
1348func (c *compiler) compileCallArgs(list []ast.Expression) (args []compiledExpr, isVariadic bool) {
1349	args = make([]compiledExpr, len(list))
1350	for i, argExpr := range list {
1351		if spread, ok := argExpr.(*ast.SpreadElement); ok {
1352			args[i] = c.compileSpreadCallArgument(spread)
1353			isVariadic = true
1354		} else {
1355			args[i] = c.compileExpression(argExpr)
1356		}
1357	}
1358	return
1359}
1360
1361func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr {
1362	args, isVariadic := c.compileCallArgs(v.ArgumentList)
1363	r := &compiledNewExpr{
1364		compiledCallExpr: compiledCallExpr{
1365			callee:     c.compileExpression(v.Callee),
1366			args:       args,
1367			isVariadic: isVariadic,
1368		},
1369	}
1370	r.init(c, v.Idx0())
1371	return r
1372}
1373
1374func (e *compiledNewTarget) emitGetter(putOnStack bool) {
1375	if putOnStack {
1376		e.addSrcMap()
1377		e.c.emit(loadNewTarget)
1378	}
1379}
1380
1381func (c *compiler) compileMetaProperty(v *ast.MetaProperty) compiledExpr {
1382	if v.Meta.Name == "new" || v.Property.Name != "target" {
1383		r := &compiledNewTarget{}
1384		r.init(c, v.Idx0())
1385		return r
1386	}
1387	c.throwSyntaxError(int(v.Idx)-1, "Unsupported meta property: %s.%s", v.Meta.Name, v.Property.Name)
1388	return nil
1389}
1390
1391func (e *compiledSequenceExpr) emitGetter(putOnStack bool) {
1392	if len(e.sequence) > 0 {
1393		for i := 0; i < len(e.sequence)-1; i++ {
1394			e.sequence[i].emitGetter(false)
1395		}
1396		e.sequence[len(e.sequence)-1].emitGetter(putOnStack)
1397	}
1398}
1399
1400func (c *compiler) compileSequenceExpression(v *ast.SequenceExpression) compiledExpr {
1401	s := make([]compiledExpr, len(v.Sequence))
1402	for i, expr := range v.Sequence {
1403		s[i] = c.compileExpression(expr)
1404	}
1405	r := &compiledSequenceExpr{
1406		sequence: s,
1407	}
1408	var idx file.Idx
1409	if len(v.Sequence) > 0 {
1410		idx = v.Idx0()
1411	}
1412	r.init(c, idx)
1413	return r
1414}
1415
1416func (c *compiler) emitThrow(v Value) {
1417	if o, ok := v.(*Object); ok {
1418		t := nilSafe(o.self.getStr("name", nil)).toString().String()
1419		switch t {
1420		case "TypeError":
1421			c.emit(loadDynamic(t))
1422			msg := o.self.getStr("message", nil)
1423			if msg != nil {
1424				c.emit(loadVal(c.p.defineLiteralValue(msg)))
1425				c.emit(_new(1))
1426			} else {
1427				c.emit(_new(0))
1428			}
1429			c.emit(throw)
1430			return
1431		}
1432	}
1433	panic(fmt.Errorf("unknown exception type thrown while evaliating constant expression: %s", v.String()))
1434}
1435
1436func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) {
1437	v, ex := c.evalConst(expr)
1438	if ex == nil {
1439		if putOnStack {
1440			c.emit(loadVal(c.p.defineLiteralValue(v)))
1441		}
1442	} else {
1443		c.emitThrow(ex.val)
1444	}
1445}
1446
1447func (c *compiler) emitExpr(expr compiledExpr, putOnStack bool) {
1448	if expr.constant() {
1449		c.emitConst(expr, putOnStack)
1450	} else {
1451		expr.emitGetter(putOnStack)
1452	}
1453}
1454
1455func (c *compiler) evalConst(expr compiledExpr) (Value, *Exception) {
1456	if expr, ok := expr.(*compiledLiteral); ok {
1457		return expr.val, nil
1458	}
1459	if c.evalVM == nil {
1460		c.evalVM = New().vm
1461	}
1462	var savedPrg *Program
1463	createdPrg := false
1464	if c.evalVM.prg == nil {
1465		c.evalVM.prg = &Program{}
1466		savedPrg = c.p
1467		c.p = c.evalVM.prg
1468		createdPrg = true
1469	}
1470	savedPc := len(c.p.code)
1471	expr.emitGetter(true)
1472	c.emit(halt)
1473	c.evalVM.pc = savedPc
1474	ex := c.evalVM.runTry()
1475	if createdPrg {
1476		c.evalVM.prg = nil
1477		c.evalVM.pc = 0
1478		c.p = savedPrg
1479	} else {
1480		c.evalVM.prg.code = c.evalVM.prg.code[:savedPc]
1481		c.p.code = c.evalVM.prg.code
1482	}
1483	if ex == nil {
1484		return c.evalVM.pop(), nil
1485	}
1486	return nil, ex
1487}
1488
1489func (e *compiledUnaryExpr) constant() bool {
1490	return e.operand.constant()
1491}
1492
1493func (e *compiledUnaryExpr) emitGetter(putOnStack bool) {
1494	var prepare, body func()
1495
1496	toNumber := func() {
1497		e.c.emit(toNumber)
1498	}
1499
1500	switch e.operator {
1501	case token.NOT:
1502		e.operand.emitGetter(true)
1503		e.c.emit(not)
1504		goto end
1505	case token.BITWISE_NOT:
1506		e.operand.emitGetter(true)
1507		e.c.emit(bnot)
1508		goto end
1509	case token.TYPEOF:
1510		if o, ok := e.operand.(compiledExprOrRef); ok {
1511			o.emitGetterOrRef()
1512		} else {
1513			e.operand.emitGetter(true)
1514		}
1515		e.c.emit(typeof)
1516		goto end
1517	case token.DELETE:
1518		e.operand.deleteExpr().emitGetter(putOnStack)
1519		return
1520	case token.MINUS:
1521		e.c.emitExpr(e.operand, true)
1522		e.c.emit(neg)
1523		goto end
1524	case token.PLUS:
1525		e.c.emitExpr(e.operand, true)
1526		e.c.emit(plus)
1527		goto end
1528	case token.INCREMENT:
1529		prepare = toNumber
1530		body = func() {
1531			e.c.emit(inc)
1532		}
1533	case token.DECREMENT:
1534		prepare = toNumber
1535		body = func() {
1536			e.c.emit(dec)
1537		}
1538	case token.VOID:
1539		e.c.emitExpr(e.operand, false)
1540		if putOnStack {
1541			e.c.emit(loadUndef)
1542		}
1543		return
1544	default:
1545		panic(fmt.Errorf("Unknown unary operator: %s", e.operator.String()))
1546	}
1547
1548	e.operand.emitUnary(prepare, body, e.postfix, putOnStack)
1549	return
1550
1551end:
1552	if !putOnStack {
1553		e.c.emit(pop)
1554	}
1555}
1556
1557func (c *compiler) compileUnaryExpression(v *ast.UnaryExpression) compiledExpr {
1558	r := &compiledUnaryExpr{
1559		operand:  c.compileExpression(v.Operand),
1560		operator: v.Operator,
1561		postfix:  v.Postfix,
1562	}
1563	r.init(c, v.Idx0())
1564	return r
1565}
1566
1567func (e *compiledConditionalExpr) emitGetter(putOnStack bool) {
1568	e.test.emitGetter(true)
1569	j := len(e.c.p.code)
1570	e.c.emit(nil)
1571	e.consequent.emitGetter(putOnStack)
1572	j1 := len(e.c.p.code)
1573	e.c.emit(nil)
1574	e.c.p.code[j] = jne(len(e.c.p.code) - j)
1575	e.alternate.emitGetter(putOnStack)
1576	e.c.p.code[j1] = jump(len(e.c.p.code) - j1)
1577}
1578
1579func (c *compiler) compileConditionalExpression(v *ast.ConditionalExpression) compiledExpr {
1580	r := &compiledConditionalExpr{
1581		test:       c.compileExpression(v.Test),
1582		consequent: c.compileExpression(v.Consequent),
1583		alternate:  c.compileExpression(v.Alternate),
1584	}
1585	r.init(c, v.Idx0())
1586	return r
1587}
1588
1589func (e *compiledLogicalOr) constant() bool {
1590	if e.left.constant() {
1591		if v, ex := e.c.evalConst(e.left); ex == nil {
1592			if v.ToBoolean() {
1593				return true
1594			}
1595			return e.right.constant()
1596		} else {
1597			return true
1598		}
1599	}
1600
1601	return false
1602}
1603
1604func (e *compiledLogicalOr) emitGetter(putOnStack bool) {
1605	if e.left.constant() {
1606		if v, ex := e.c.evalConst(e.left); ex == nil {
1607			if !v.ToBoolean() {
1608				e.c.emitExpr(e.right, putOnStack)
1609			} else {
1610				if putOnStack {
1611					e.c.emit(loadVal(e.c.p.defineLiteralValue(v)))
1612				}
1613			}
1614		} else {
1615			e.c.emitThrow(ex.val)
1616		}
1617		return
1618	}
1619	e.c.emitExpr(e.left, true)
1620	j := len(e.c.p.code)
1621	e.addSrcMap()
1622	e.c.emit(nil)
1623	e.c.emit(pop)
1624	e.c.emitExpr(e.right, true)
1625	e.c.p.code[j] = jeq1(len(e.c.p.code) - j)
1626	if !putOnStack {
1627		e.c.emit(pop)
1628	}
1629}
1630
1631func (e *compiledLogicalAnd) constant() bool {
1632	if e.left.constant() {
1633		if v, ex := e.c.evalConst(e.left); ex == nil {
1634			if !v.ToBoolean() {
1635				return true
1636			} else {
1637				return e.right.constant()
1638			}
1639		} else {
1640			return true
1641		}
1642	}
1643
1644	return false
1645}
1646
1647func (e *compiledLogicalAnd) emitGetter(putOnStack bool) {
1648	var j int
1649	if e.left.constant() {
1650		if v, ex := e.c.evalConst(e.left); ex == nil {
1651			if !v.ToBoolean() {
1652				e.c.emit(loadVal(e.c.p.defineLiteralValue(v)))
1653			} else {
1654				e.c.emitExpr(e.right, putOnStack)
1655			}
1656		} else {
1657			e.c.emitThrow(ex.val)
1658		}
1659		return
1660	}
1661	e.left.emitGetter(true)
1662	j = len(e.c.p.code)
1663	e.addSrcMap()
1664	e.c.emit(nil)
1665	e.c.emit(pop)
1666	e.c.emitExpr(e.right, true)
1667	e.c.p.code[j] = jneq1(len(e.c.p.code) - j)
1668	if !putOnStack {
1669		e.c.emit(pop)
1670	}
1671}
1672
1673func (e *compiledBinaryExpr) constant() bool {
1674	return e.left.constant() && e.right.constant()
1675}
1676
1677func (e *compiledBinaryExpr) emitGetter(putOnStack bool) {
1678	e.c.emitExpr(e.left, true)
1679	e.c.emitExpr(e.right, true)
1680	e.addSrcMap()
1681
1682	switch e.operator {
1683	case token.LESS:
1684		e.c.emit(op_lt)
1685	case token.GREATER:
1686		e.c.emit(op_gt)
1687	case token.LESS_OR_EQUAL:
1688		e.c.emit(op_lte)
1689	case token.GREATER_OR_EQUAL:
1690		e.c.emit(op_gte)
1691	case token.EQUAL:
1692		e.c.emit(op_eq)
1693	case token.NOT_EQUAL:
1694		e.c.emit(op_neq)
1695	case token.STRICT_EQUAL:
1696		e.c.emit(op_strict_eq)
1697	case token.STRICT_NOT_EQUAL:
1698		e.c.emit(op_strict_neq)
1699	case token.PLUS:
1700		e.c.emit(add)
1701	case token.MINUS:
1702		e.c.emit(sub)
1703	case token.MULTIPLY:
1704		e.c.emit(mul)
1705	case token.SLASH:
1706		e.c.emit(div)
1707	case token.REMAINDER:
1708		e.c.emit(mod)
1709	case token.AND:
1710		e.c.emit(and)
1711	case token.OR:
1712		e.c.emit(or)
1713	case token.EXCLUSIVE_OR:
1714		e.c.emit(xor)
1715	case token.INSTANCEOF:
1716		e.c.emit(op_instanceof)
1717	case token.IN:
1718		e.c.emit(op_in)
1719	case token.SHIFT_LEFT:
1720		e.c.emit(sal)
1721	case token.SHIFT_RIGHT:
1722		e.c.emit(sar)
1723	case token.UNSIGNED_SHIFT_RIGHT:
1724		e.c.emit(shr)
1725	default:
1726		panic(fmt.Errorf("Unknown operator: %s", e.operator.String()))
1727	}
1728
1729	if !putOnStack {
1730		e.c.emit(pop)
1731	}
1732}
1733
1734func (c *compiler) compileBinaryExpression(v *ast.BinaryExpression) compiledExpr {
1735
1736	switch v.Operator {
1737	case token.LOGICAL_OR:
1738		return c.compileLogicalOr(v.Left, v.Right, v.Idx0())
1739	case token.LOGICAL_AND:
1740		return c.compileLogicalAnd(v.Left, v.Right, v.Idx0())
1741	}
1742
1743	r := &compiledBinaryExpr{
1744		left:     c.compileExpression(v.Left),
1745		right:    c.compileExpression(v.Right),
1746		operator: v.Operator,
1747	}
1748	r.init(c, v.Idx0())
1749	return r
1750}
1751
1752func (c *compiler) compileLogicalOr(left, right ast.Expression, idx file.Idx) compiledExpr {
1753	r := &compiledLogicalOr{
1754		left:  c.compileExpression(left),
1755		right: c.compileExpression(right),
1756	}
1757	r.init(c, idx)
1758	return r
1759}
1760
1761func (c *compiler) compileLogicalAnd(left, right ast.Expression, idx file.Idx) compiledExpr {
1762	r := &compiledLogicalAnd{
1763		left:  c.compileExpression(left),
1764		right: c.compileExpression(right),
1765	}
1766	r.init(c, idx)
1767	return r
1768}
1769
1770func (e *compiledObjectLiteral) emitGetter(putOnStack bool) {
1771	e.addSrcMap()
1772	e.c.emit(newObject)
1773	for _, prop := range e.expr.Value {
1774		switch prop := prop.(type) {
1775		case *ast.PropertyKeyed:
1776			keyExpr := e.c.compileExpression(prop.Key)
1777			computed := false
1778			var key unistring.String
1779			switch keyExpr := keyExpr.(type) {
1780			case *compiledLiteral:
1781				key = keyExpr.val.string()
1782			default:
1783				keyExpr.emitGetter(true)
1784				computed = true
1785			}
1786			valueExpr := e.c.compileExpression(prop.Value)
1787			var anonFn *compiledFunctionLiteral
1788			if fn, ok := valueExpr.(*compiledFunctionLiteral); ok {
1789				if fn.name == nil {
1790					anonFn = fn
1791					fn.lhsName = key
1792				}
1793			}
1794			if computed {
1795				e.c.emit(_toPropertyKey{})
1796				valueExpr.emitGetter(true)
1797				switch prop.Kind {
1798				case ast.PropertyKindValue, ast.PropertyKindMethod:
1799					if anonFn != nil {
1800						e.c.emit(setElem1Named)
1801					} else {
1802						e.c.emit(setElem1)
1803					}
1804				case ast.PropertyKindGet:
1805					e.c.emit(setPropGetter1)
1806				case ast.PropertyKindSet:
1807					e.c.emit(setPropSetter1)
1808				default:
1809					panic(fmt.Errorf("unknown property kind: %s", prop.Kind))
1810				}
1811			} else {
1812				if anonFn != nil {
1813					anonFn.lhsName = key
1814				}
1815				valueExpr.emitGetter(true)
1816				switch prop.Kind {
1817				case ast.PropertyKindValue:
1818					if key == __proto__ {
1819						e.c.emit(setProto)
1820					} else {
1821						e.c.emit(setProp1(key))
1822					}
1823				case ast.PropertyKindMethod:
1824					e.c.emit(setProp1(key))
1825				case ast.PropertyKindGet:
1826					e.c.emit(setPropGetter(key))
1827				case ast.PropertyKindSet:
1828					e.c.emit(setPropSetter(key))
1829				default:
1830					panic(fmt.Errorf("unknown property kind: %s", prop.Kind))
1831				}
1832			}
1833		case *ast.PropertyShort:
1834			key := prop.Name.Name
1835			if prop.Initializer != nil {
1836				e.c.throwSyntaxError(int(prop.Initializer.Idx0())-1, "Invalid shorthand property initializer")
1837			}
1838			if e.c.scope.strict && key == "let" {
1839				e.c.throwSyntaxError(e.offset, "'let' cannot be used as a shorthand property in strict mode")
1840			}
1841			e.c.compileIdentifierExpression(&prop.Name).emitGetter(true)
1842			e.c.emit(setProp1(key))
1843		case *ast.SpreadElement:
1844			e.c.compileExpression(prop.Expression).emitGetter(true)
1845			e.c.emit(copySpread)
1846		default:
1847			panic(fmt.Errorf("unknown Property type: %T", prop))
1848		}
1849	}
1850	if !putOnStack {
1851		e.c.emit(pop)
1852	}
1853}
1854
1855func (c *compiler) compileObjectLiteral(v *ast.ObjectLiteral) compiledExpr {
1856	r := &compiledObjectLiteral{
1857		expr: v,
1858	}
1859	r.init(c, v.Idx0())
1860	return r
1861}
1862
1863func (e *compiledArrayLiteral) emitGetter(putOnStack bool) {
1864	e.addSrcMap()
1865	hasSpread := false
1866	mark := len(e.c.p.code)
1867	e.c.emit(nil)
1868	for _, v := range e.expr.Value {
1869		if spread, ok := v.(*ast.SpreadElement); ok {
1870			hasSpread = true
1871			e.c.compileExpression(spread.Expression).emitGetter(true)
1872			e.c.emit(pushArraySpread)
1873		} else {
1874			if v != nil {
1875				e.c.compileExpression(v).emitGetter(true)
1876			} else {
1877				e.c.emit(loadNil)
1878			}
1879			e.c.emit(pushArrayItem)
1880		}
1881	}
1882	var objCount uint32
1883	if !hasSpread {
1884		objCount = uint32(len(e.expr.Value))
1885	}
1886	e.c.p.code[mark] = newArray(objCount)
1887	if !putOnStack {
1888		e.c.emit(pop)
1889	}
1890}
1891
1892func (c *compiler) compileArrayLiteral(v *ast.ArrayLiteral) compiledExpr {
1893	r := &compiledArrayLiteral{
1894		expr: v,
1895	}
1896	r.init(c, v.Idx0())
1897	return r
1898}
1899
1900func (e *compiledRegexpLiteral) emitGetter(putOnStack bool) {
1901	if putOnStack {
1902		pattern, err := compileRegexp(e.expr.Pattern, e.expr.Flags)
1903		if err != nil {
1904			e.c.throwSyntaxError(e.offset, err.Error())
1905		}
1906
1907		e.c.emit(&newRegexp{pattern: pattern, src: newStringValue(e.expr.Pattern)})
1908	}
1909}
1910
1911func (c *compiler) compileRegexpLiteral(v *ast.RegExpLiteral) compiledExpr {
1912	r := &compiledRegexpLiteral{
1913		expr: v,
1914	}
1915	r.init(c, v.Idx0())
1916	return r
1917}
1918
1919func (c *compiler) emitCallee(callee compiledExpr) (calleeName unistring.String) {
1920	switch callee := callee.(type) {
1921	case *compiledDotExpr:
1922		callee.left.emitGetter(true)
1923		c.emit(dup)
1924		c.emit(getPropCallee(callee.name))
1925	case *compiledBracketExpr:
1926		callee.left.emitGetter(true)
1927		c.emit(dup)
1928		callee.member.emitGetter(true)
1929		c.emit(getElemCallee)
1930	case *compiledIdentifierExpr:
1931		calleeName = callee.name
1932		callee.emitGetterAndCallee()
1933	default:
1934		c.emit(loadUndef)
1935		callee.emitGetter(true)
1936	}
1937	return
1938}
1939
1940func (e *compiledCallExpr) emitGetter(putOnStack bool) {
1941	if e.isVariadic {
1942		e.c.emit(startVariadic)
1943	}
1944	calleeName := e.c.emitCallee(e.callee)
1945
1946	for _, expr := range e.args {
1947		expr.emitGetter(true)
1948	}
1949
1950	e.addSrcMap()
1951	if calleeName == "eval" {
1952		foundFunc, foundVar := false, false
1953		for sc := e.c.scope; sc != nil; sc = sc.outer {
1954			if !foundFunc && sc.function && !sc.arrow {
1955				foundFunc = true
1956				sc.thisNeeded, sc.argsNeeded = true, true
1957			}
1958			if !foundVar && (sc.variable || sc.function) {
1959				foundVar = true
1960				if !sc.strict {
1961					sc.dynamic = true
1962				}
1963			}
1964			sc.dynLookup = true
1965		}
1966
1967		if e.c.scope.strict {
1968			if e.isVariadic {
1969				e.c.emit(callEvalVariadicStrict)
1970			} else {
1971				e.c.emit(callEvalStrict(len(e.args)))
1972			}
1973		} else {
1974			if e.isVariadic {
1975				e.c.emit(callEvalVariadic)
1976			} else {
1977				e.c.emit(callEval(len(e.args)))
1978			}
1979		}
1980	} else {
1981		if e.isVariadic {
1982			e.c.emit(callVariadic)
1983		} else {
1984			e.c.emit(call(len(e.args)))
1985		}
1986	}
1987	if e.isVariadic {
1988		e.c.emit(endVariadic)
1989	}
1990	if !putOnStack {
1991		e.c.emit(pop)
1992	}
1993}
1994
1995func (e *compiledCallExpr) deleteExpr() compiledExpr {
1996	r := &defaultDeleteExpr{
1997		expr: e,
1998	}
1999	r.init(e.c, file.Idx(e.offset+1))
2000	return r
2001}
2002
2003func (c *compiler) compileSpreadCallArgument(spread *ast.SpreadElement) compiledExpr {
2004	r := &compiledSpreadCallArgument{
2005		expr: c.compileExpression(spread.Expression),
2006	}
2007	r.init(c, spread.Idx0())
2008	return r
2009}
2010
2011func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr {
2012
2013	args := make([]compiledExpr, len(v.ArgumentList))
2014	isVariadic := false
2015	for i, argExpr := range v.ArgumentList {
2016		if spread, ok := argExpr.(*ast.SpreadElement); ok {
2017			args[i] = c.compileSpreadCallArgument(spread)
2018			isVariadic = true
2019		} else {
2020			args[i] = c.compileExpression(argExpr)
2021		}
2022	}
2023
2024	r := &compiledCallExpr{
2025		args:       args,
2026		callee:     c.compileExpression(v.Callee),
2027		isVariadic: isVariadic,
2028	}
2029	r.init(c, v.LeftParenthesis)
2030	return r
2031}
2032
2033func (c *compiler) compileIdentifierExpression(v *ast.Identifier) compiledExpr {
2034	if c.scope.strict {
2035		c.checkIdentifierName(v.Name, int(v.Idx)-1)
2036	}
2037
2038	r := &compiledIdentifierExpr{
2039		name: v.Name,
2040	}
2041	r.offset = int(v.Idx) - 1
2042	r.init(c, v.Idx0())
2043	return r
2044}
2045
2046func (c *compiler) compileNumberLiteral(v *ast.NumberLiteral) compiledExpr {
2047	if c.scope.strict && len(v.Literal) > 1 && v.Literal[0] == '0' && v.Literal[1] <= '7' && v.Literal[1] >= '0' {
2048		c.throwSyntaxError(int(v.Idx)-1, "Octal literals are not allowed in strict mode")
2049		panic("Unreachable")
2050	}
2051	var val Value
2052	switch num := v.Value.(type) {
2053	case int64:
2054		val = intToValue(num)
2055	case float64:
2056		val = floatToValue(num)
2057	default:
2058		panic(fmt.Errorf("Unsupported number literal type: %T", v.Value))
2059	}
2060	r := &compiledLiteral{
2061		val: val,
2062	}
2063	r.init(c, v.Idx0())
2064	return r
2065}
2066
2067func (c *compiler) compileStringLiteral(v *ast.StringLiteral) compiledExpr {
2068	r := &compiledLiteral{
2069		val: stringValueFromRaw(v.Value),
2070	}
2071	r.init(c, v.Idx0())
2072	return r
2073}
2074
2075func (c *compiler) compileTemplateLiteral(v *ast.TemplateLiteral) compiledExpr {
2076	r := &compiledTemplateLiteral{}
2077	if v.Tag != nil {
2078		r.tag = c.compileExpression(v.Tag)
2079	}
2080	ce := make([]compiledExpr, len(v.Expressions))
2081	for i, expr := range v.Expressions {
2082		ce[i] = c.compileExpression(expr)
2083	}
2084	r.expressions = ce
2085	r.elements = v.Elements
2086	r.init(c, v.Idx0())
2087	return r
2088}
2089
2090func (c *compiler) compileBooleanLiteral(v *ast.BooleanLiteral) compiledExpr {
2091	var val Value
2092	if v.Value {
2093		val = valueTrue
2094	} else {
2095		val = valueFalse
2096	}
2097
2098	r := &compiledLiteral{
2099		val: val,
2100	}
2101	r.init(c, v.Idx0())
2102	return r
2103}
2104
2105func (c *compiler) compileAssignExpression(v *ast.AssignExpression) compiledExpr {
2106	// log.Printf("compileAssignExpression(): %+v", v)
2107
2108	r := &compiledAssignExpr{
2109		left:     c.compileExpression(v.Left),
2110		right:    c.compileExpression(v.Right),
2111		operator: v.Operator,
2112	}
2113	r.init(c, v.Idx0())
2114	return r
2115}
2116
2117func (e *compiledEnumGetExpr) emitGetter(putOnStack bool) {
2118	e.c.emit(enumGet)
2119	if !putOnStack {
2120		e.c.emit(pop)
2121	}
2122}
2123
2124func (c *compiler) compileObjectAssignmentPattern(v *ast.ObjectPattern) compiledExpr {
2125	r := &compiledObjectAssignmentPattern{
2126		expr: v,
2127	}
2128	r.init(c, v.Idx0())
2129	return r
2130}
2131
2132func (e *compiledObjectAssignmentPattern) emitGetter(putOnStack bool) {
2133	if putOnStack {
2134		e.c.emit(loadUndef)
2135	}
2136}
2137
2138func (c *compiler) compileArrayAssignmentPattern(v *ast.ArrayPattern) compiledExpr {
2139	r := &compiledArrayAssignmentPattern{
2140		expr: v,
2141	}
2142	r.init(c, v.Idx0())
2143	return r
2144}
2145
2146func (e *compiledArrayAssignmentPattern) emitGetter(putOnStack bool) {
2147	if putOnStack {
2148		e.c.emit(loadUndef)
2149	}
2150}
2151
2152func (c *compiler) emitNamed(expr compiledExpr, name unistring.String) {
2153	if en, ok := expr.(interface {
2154		emitNamed(name unistring.String)
2155	}); ok {
2156		en.emitNamed(name)
2157	} else {
2158		expr.emitGetter(true)
2159	}
2160}
2161
2162func (e *compiledFunctionLiteral) emitNamed(name unistring.String) {
2163	e.lhsName = name
2164	e.emitGetter(true)
2165}
2166
2167func (c *compiler) emitPattern(pattern ast.Pattern, emitter func(target, init compiledExpr), putOnStack bool) {
2168	switch pattern := pattern.(type) {
2169	case *ast.ObjectPattern:
2170		c.emitObjectPattern(pattern, emitter, putOnStack)
2171	case *ast.ArrayPattern:
2172		c.emitArrayPattern(pattern, emitter, putOnStack)
2173	default:
2174		panic(fmt.Errorf("unsupported Pattern: %T", pattern))
2175	}
2176}
2177
2178func (c *compiler) emitAssign(target ast.Expression, init compiledExpr, emitAssignSimple func(target, init compiledExpr)) {
2179	pattern, isPattern := target.(ast.Pattern)
2180	if isPattern {
2181		init.emitGetter(true)
2182		c.emitPattern(pattern, emitAssignSimple, false)
2183	} else {
2184		emitAssignSimple(c.compileExpression(target), init)
2185	}
2186}
2187
2188func (c *compiler) emitObjectPattern(pattern *ast.ObjectPattern, emitAssign func(target, init compiledExpr), putOnStack bool) {
2189	if pattern.Rest != nil {
2190		c.emit(createDestructSrc)
2191	} else {
2192		c.emit(checkObjectCoercible)
2193	}
2194	for _, prop := range pattern.Properties {
2195		switch prop := prop.(type) {
2196		case *ast.PropertyShort:
2197			c.emit(dup)
2198			emitAssign(c.compileIdentifierExpression(&prop.Name), c.compilePatternInitExpr(func() {
2199				c.emit(getProp(prop.Name.Name))
2200			}, prop.Initializer, prop.Idx0()))
2201		case *ast.PropertyKeyed:
2202			c.emit(dup)
2203			c.compileExpression(prop.Key).emitGetter(true)
2204			c.emit(_toPropertyKey{})
2205			var target ast.Expression
2206			var initializer ast.Expression
2207			if e, ok := prop.Value.(*ast.AssignExpression); ok {
2208				target = e.Left
2209				initializer = e.Right
2210			} else {
2211				target = prop.Value
2212			}
2213			c.emitAssign(target, c.compilePatternInitExpr(func() {
2214				c.emit(getKey)
2215			}, initializer, prop.Idx0()), emitAssign)
2216		default:
2217			c.throwSyntaxError(int(prop.Idx0()-1), "Unsupported AssignmentProperty type: %T", prop)
2218		}
2219	}
2220	if pattern.Rest != nil {
2221		emitAssign(c.compileExpression(pattern.Rest), c.compileEmitterExpr(func() {
2222			c.emit(copyRest)
2223		}, pattern.Rest.Idx0()))
2224		c.emit(pop)
2225	}
2226	if !putOnStack {
2227		c.emit(pop)
2228	}
2229}
2230
2231func (c *compiler) emitArrayPattern(pattern *ast.ArrayPattern, emitAssign func(target, init compiledExpr), putOnStack bool) {
2232	var marks []int
2233	c.emit(iterate)
2234	for _, elt := range pattern.Elements {
2235		switch elt := elt.(type) {
2236		case nil:
2237			marks = append(marks, len(c.p.code))
2238			c.emit(nil)
2239		case *ast.AssignExpression:
2240			c.emitAssign(elt.Left, c.compilePatternInitExpr(func() {
2241				marks = append(marks, len(c.p.code))
2242				c.emit(nil, enumGet)
2243			}, elt.Right, elt.Idx0()), emitAssign)
2244		default:
2245			c.emitAssign(elt, c.compileEmitterExpr(func() {
2246				marks = append(marks, len(c.p.code))
2247				c.emit(nil, enumGet)
2248			}, elt.Idx0()), emitAssign)
2249		}
2250	}
2251	if pattern.Rest != nil {
2252		c.emitAssign(pattern.Rest, c.compileEmitterExpr(func() {
2253			c.emit(newArrayFromIter)
2254		}, pattern.Rest.Idx0()), emitAssign)
2255	} else {
2256		c.emit(enumPopClose)
2257	}
2258	mark1 := len(c.p.code)
2259	c.emit(nil)
2260
2261	for i, elt := range pattern.Elements {
2262		switch elt := elt.(type) {
2263		case nil:
2264			c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i])
2265		case *ast.Identifier:
2266			emitAssign(c.compileIdentifierExpression(elt), c.compileEmitterExpr(func() {
2267				c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i])
2268				c.emit(loadUndef)
2269			}, elt.Idx0()))
2270		case *ast.AssignExpression:
2271			c.emitAssign(elt.Left, c.compileNamedEmitterExpr(func(name unistring.String) {
2272				c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i])
2273				c.emitNamed(c.compileExpression(elt.Right), name)
2274			}, elt.Idx0()), emitAssign)
2275		default:
2276			c.emitAssign(elt, c.compileEmitterExpr(
2277				func() {
2278					c.p.code[marks[i]] = iterNext(len(c.p.code) - marks[i])
2279					c.emit(loadUndef)
2280				}, elt.Idx0()), emitAssign)
2281		}
2282	}
2283	c.emit(enumPop)
2284	if pattern.Rest != nil {
2285		c.emitAssign(pattern.Rest, c.compileExpression(
2286			&ast.ArrayLiteral{
2287				LeftBracket:  pattern.Rest.Idx0(),
2288				RightBracket: pattern.Rest.Idx0(),
2289			}), emitAssign)
2290	}
2291	c.p.code[mark1] = jump(len(c.p.code) - mark1)
2292
2293	if !putOnStack {
2294		c.emit(pop)
2295	}
2296}
2297
2298func (e *compiledObjectAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) {
2299	valueExpr.emitGetter(true)
2300	e.c.emitObjectPattern(e.expr, e.c.emitPatternAssign, putOnStack)
2301}
2302
2303func (e *compiledArrayAssignmentPattern) emitSetter(valueExpr compiledExpr, putOnStack bool) {
2304	valueExpr.emitGetter(true)
2305	e.c.emitArrayPattern(e.expr, e.c.emitPatternAssign, putOnStack)
2306}
2307
2308type compiledPatternInitExpr struct {
2309	baseCompiledExpr
2310	emitSrc func()
2311	def     compiledExpr
2312}
2313
2314func (e *compiledPatternInitExpr) emitGetter(putOnStack bool) {
2315	if !putOnStack {
2316		return
2317	}
2318	e.emitSrc()
2319	if e.def != nil {
2320		mark := len(e.c.p.code)
2321		e.c.emit(nil)
2322		e.def.emitGetter(true)
2323		e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
2324	}
2325}
2326
2327func (e *compiledPatternInitExpr) emitNamed(name unistring.String) {
2328	e.emitSrc()
2329	if e.def != nil {
2330		mark := len(e.c.p.code)
2331		e.c.emit(nil)
2332		e.c.emitNamed(e.def, name)
2333		e.c.p.code[mark] = jdef(len(e.c.p.code) - mark)
2334	}
2335}
2336
2337func (c *compiler) compilePatternInitExpr(emitSrc func(), def ast.Expression, idx file.Idx) compiledExpr {
2338	r := &compiledPatternInitExpr{
2339		emitSrc: emitSrc,
2340		def:     c.compileExpression(def),
2341	}
2342	r.init(c, idx)
2343	return r
2344}
2345
2346type compiledEmitterExpr struct {
2347	baseCompiledExpr
2348	emitter      func()
2349	namedEmitter func(name unistring.String)
2350}
2351
2352func (e *compiledEmitterExpr) emitGetter(putOnStack bool) {
2353	if e.emitter != nil {
2354		e.emitter()
2355	} else {
2356		e.namedEmitter("")
2357	}
2358	if !putOnStack {
2359		e.c.emit(pop)
2360	}
2361}
2362
2363func (e *compiledEmitterExpr) emitNamed(name unistring.String) {
2364	if e.namedEmitter != nil {
2365		e.namedEmitter(name)
2366	} else {
2367		e.emitter()
2368	}
2369}
2370
2371func (c *compiler) compileEmitterExpr(emitter func(), idx file.Idx) *compiledEmitterExpr {
2372	r := &compiledEmitterExpr{
2373		emitter: emitter,
2374	}
2375	r.init(c, idx)
2376	return r
2377}
2378
2379func (c *compiler) compileNamedEmitterExpr(namedEmitter func(unistring.String), idx file.Idx) *compiledEmitterExpr {
2380	r := &compiledEmitterExpr{
2381		namedEmitter: namedEmitter,
2382	}
2383	r.init(c, idx)
2384	return r
2385}
2386
2387func (e *compiledSpreadCallArgument) emitGetter(putOnStack bool) {
2388	e.expr.emitGetter(putOnStack)
2389	if putOnStack {
2390		e.c.emit(pushSpread)
2391	}
2392}
2393