func()

in internal/compile/compile.go [1742:1803]


func (fcomp *fcomp) comprehension(comp *syntax.Comprehension, clauseIndex int) {
	if clauseIndex == len(comp.Clauses) {
		fcomp.emit(DUP) // accumulator
		if comp.Curly {
			// dict: {k:v for ...}
			// Parser ensures that body is of form k:v.
			// Python-style set comprehensions {body for vars in x}
			// are not supported.
			entry := comp.Body.(*syntax.DictEntry)
			fcomp.expr(entry.Key)
			fcomp.expr(entry.Value)
			fcomp.setPos(entry.Colon)
			fcomp.emit(SETDICT)
		} else {
			// list: [body for vars in x]
			fcomp.expr(comp.Body)
			fcomp.emit(APPEND)
		}
		return
	}

	clause := comp.Clauses[clauseIndex]
	switch clause := clause.(type) {
	case *syntax.IfClause:
		t := fcomp.newBlock()
		done := fcomp.newBlock()
		fcomp.ifelse(clause.Cond, t, done)

		fcomp.block = t
		fcomp.comprehension(comp, clauseIndex+1)
		fcomp.jump(done)

		fcomp.block = done
		return

	case *syntax.ForClause:
		// Keep consistent with ForStmt.
		head := fcomp.newBlock()
		body := fcomp.newBlock()
		tail := fcomp.newBlock()

		fcomp.expr(clause.X)
		fcomp.setPos(clause.For)
		fcomp.emit(ITERPUSH)
		fcomp.jump(head)

		fcomp.block = head
		fcomp.condjump(ITERJMP, tail, body)

		fcomp.block = body
		fcomp.assign(clause.For, clause.Vars)
		fcomp.comprehension(comp, clauseIndex+1)
		fcomp.jump(head)

		fcomp.block = tail
		fcomp.emit(ITERPOP)
		return
	}

	start, _ := clause.Span()
	log.Panicf("%s: unexpected comprehension clause %T", start, clause)
}