func NewEvaluator(w io.Writer, opts ...Option) *eval {
	e := &eval{
		p: ast.NewParser(),
		w: writer.NewStarlarkWriter(w),
		v: bindings.New(),
		o: options{
			macroName: "generated_cmake_targets",
			shouldAdd: func(n string) bool { return n == "add_subdirectory" },
		},
	}
	for _, o := range opts {
		o(e)
	}
	e.v.Set("CMAKE_BINARY_DIR", e.ProjectRoot())
	e.v.Set("CMAKE_SOURCE_DIR", e.ProjectRoot())
	return e
}
NewEvaluator returns a new CMake evaluator instance.
package main
import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"go/constant"
	"go/token"
	"go/types"
	"github.com/kythe/llvmbzlgen/cmakelib/ast"
	"github.com/kythe/llvmbzlgen/cmakelib/bindings"
	bzlpath "github.com/kythe/llvmbzlgen/path"
	"github.com/kythe/llvmbzlgen/writer"
)
type blockCounter struct {
	begin string  
	end   string  
	count int
}
func newCounter(begin string) *blockCounter {
	return &blockCounter{begin, "end" + begin, 0}
}
func (bc *blockCounter) Count(text string) bool {
	matched := true
	if text == bc.begin {
		bc.count += 1
	} else if text == bc.end {
		bc.count -= 1
	} else {
		matched = false
	}
	return matched || bc.count > 0
}
type eval struct {
	p *ast.Parser
	o options
	w    *writer.StarlarkWriter
	v    *bindings.Mapping
	root bzlpath.Path
	path bzlpath.Path
}
type options struct {
	macroName   string
	shouldPrint func(string) bool
	shouldAdd   func(string) bool
	excludePath func(string) bool
}
type Option func(*eval)
func PrintCommands(p func(string) bool) Option {
	return func(e *eval) { e.o.shouldPrint = p }
}
func RecurseCommands(p func(string) bool) Option {
	return func(e *eval) { e.o.shouldAdd = p }
}
func ExcludePaths(p func(string) bool) Option {
	return func(e *eval) { e.o.excludePath = p }
}
func DefineVars(vars map[string]string) Option {
	return func(e *eval) {
		for k, v := range vars {
			e.v.Set(k, v)
		}
	}
}
func Matching(pat string) func(string) bool {
	return regexp.MustCompile(pat).MatchString
}