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)
}