Initial Blueprint commit.

Blueprint is a build system component that reads Blueprints files defining
modules to be built, and generates a Ninja build manifest that can be used to
perform all the build actions.  It does not dictate or implement much build
policy itself, but rather provides a framework to ease the process of defining
build logic in Go.

The "blueprint" and "blueprint/parser" Go packages contain the functionality
for reading Blueprint files and invoking build logic functions defined in other
Go packages.

The "blueprint/bootstrap" Go package contains just enough build logic to build
a binary that includes Blueprint and any pure-Go (i.e. no cgo) build logic
defined in external Go packages.  This can be used to create a minimal Ninja
file that's capable of bootstrapping a Blueprint-based build system from
source.

The "blueprint/bootstrap/minibp" Go package contains code for a minimal binary
that includes the build logic defined in the "blueprint/bootstrap" package.
This binary can then create the Ninja file for the bootstrapping process.

Change-Id: I8d8390042372a72d225785cda738525001b009f1
diff --git a/blueprint/module_ctx.go b/blueprint/module_ctx.go
new file mode 100644
index 0000000..f8fe564
--- /dev/null
+++ b/blueprint/module_ctx.go
@@ -0,0 +1,116 @@
+package blueprint
+
+import (
+	"fmt"
+	"path/filepath"
+)
+
+type Module interface {
+	GenerateBuildActions(ModuleContext)
+}
+
+type ModuleContext interface {
+	ModuleName() string
+	ModuleDir() string
+	Config() Config
+
+	ModuleErrorf(fmt string, args ...interface{})
+	PropertyErrorf(property, fmt string, args ...interface{})
+
+	Variable(name, value string)
+	Rule(name string, params RuleParams) Rule
+	Build(params BuildParams)
+
+	VisitDepsDepthFirst(visit func(Module))
+	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+}
+
+var _ ModuleContext = (*moduleContext)(nil)
+
+type moduleContext struct {
+	context *Context
+	config  Config
+	module  Module
+	scope   *localScope
+	info    *moduleInfo
+
+	errs []error
+
+	actionDefs localBuildActions
+}
+
+func (m *moduleContext) ModuleName() string {
+	return m.info.properties.Name
+}
+
+func (m *moduleContext) ModuleDir() string {
+	return filepath.Dir(m.info.relBlueprintFile)
+}
+
+func (m *moduleContext) Config() Config {
+	return m.config
+}
+
+func (m *moduleContext) ModuleErrorf(format string, args ...interface{}) {
+	m.errs = append(m.errs, &Error{
+		Err: fmt.Errorf(format, args...),
+		Pos: m.info.pos,
+	})
+}
+
+func (m *moduleContext) PropertyErrorf(property, format string,
+	args ...interface{}) {
+
+	pos, ok := m.info.propertyPos[property]
+	if !ok {
+		panic(fmt.Errorf("property %q was not set for this module", property))
+	}
+
+	m.errs = append(m.errs, &Error{
+		Err: fmt.Errorf(format, args...),
+		Pos: pos,
+	})
+}
+
+func (m *moduleContext) Variable(name, value string) {
+	v, err := m.scope.AddLocalVariable(name, value)
+	if err != nil {
+		panic(err)
+	}
+
+	m.actionDefs.variables = append(m.actionDefs.variables, v)
+}
+
+func (m *moduleContext) Rule(name string, params RuleParams) Rule {
+	// TODO: Verify that params.Pool is accessible in this module's scope.
+
+	r, err := m.scope.AddLocalRule(name, &params)
+	if err != nil {
+		panic(err)
+	}
+
+	m.actionDefs.rules = append(m.actionDefs.rules, r)
+
+	return r
+}
+
+func (m *moduleContext) Build(params BuildParams) {
+	// TODO: Verify that params.Rule is accessible in this module's scope.
+
+	def, err := parseBuildParams(m.scope, &params)
+	if err != nil {
+		panic(err)
+	}
+
+	m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
+}
+
+func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
+	m.context.visitDepsDepthFirst(m.module, visit)
+}
+
+func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
+	visit func(Module)) {
+
+	m.context.visitDepsDepthFirstIf(m.module, pred, visit)
+}