				case *BoolNode:
					value[i] = b.Value
				}
			}
			patch(&ConstantNode{Value: value})
		}

	case *BuiltinNode:
		// TODO: Move this to a separate visitor filter_filter.go
		switch n.Name {
		case "filter":
			if len(n.Arguments) != 2 {
				return
			}
			if base, ok := n.Arguments[0].(*BuiltinNode); ok && base.Name == "filter" {
				patchCopy(&BuiltinNode{
					Name: "filter",
					Arguments: []Node{
						base.Arguments[0],
						&PredicateNode{
							Node: &BinaryNode{
								Operator: "&&",
								Left:     base.Arguments[1].(*PredicateNode).Node,
								Right:    n.Arguments[1].(*PredicateNode).Node,
							},
						},
					},
				})
			}
		}
	}
}

func toString(n Node) *StringNode {
	switch a := n.(type) {
	case *StringNode:
		return a
	}
	return nil
}

vm/program.go:75:// Disassemble returns opcodes as a string.
vm/program.go:76:func (program *Program) Disassemble() string {
vm/program.go:79:	program.DisassembleWriter(w)
vm/program.go:84:// DisassembleWriter takes a writer and writes opcodes to it.
vm/program.go:85:func (program *Program) DisassembleWriter(w io.Writer) {
