Create a new core.Compiland type

This change rejiggers a few things so that we can more clearly introduce
a boundary between front- and back-end compiler phases, including sharing more,
like a diagnostics sink.  Future extensions will include backend code-generation
options.
This commit is contained in:
joeduffy 2016-11-18 17:08:44 -08:00
parent efe69a2e2c
commit 6dfc528ad1
3 changed files with 26 additions and 20 deletions

View file

@ -9,7 +9,7 @@ import (
"github.com/marapongo/mu/pkg/ast"
"github.com/marapongo/mu/pkg/compiler/backends/clouds"
"github.com/marapongo/mu/pkg/diag"
"github.com/marapongo/mu/pkg/compiler/core"
)
// New returns a fresh instance of an AWS Cloud implementation. This targets "native AWS" for the code-gen outputs.
@ -26,15 +26,15 @@ type awsCloud struct {
// TODO: support cloud provider options (e.g., ranging from simple like YAML vs. JSON to complex like IAM).
}
func (c *awsCloud) CodeGen(target *ast.Target, doc *diag.Document, stack *ast.Stack) {
func (c *awsCloud) CodeGen(comp core.Compiland) {
// For now, this routine simply generates the equivalent CloudFormation stack for the input. Eventually this needs
// to do a whole lot more, which the following running list of TODOs will serve as a reminder about:
// TODO: perform delta analysis so that we can emit changesets:
// http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html
// TODO: allow for a "dry-run" mode that queries the target, checks things like limits, shows what will be done.
// TODO: prepare full deployment packages (e.g., tarballs of code, Docker images, etc).
nm := c.genStackName(target, doc, stack)
cf := c.genStackTemplate(target, doc, stack)
nm := c.genStackName(comp)
cf := c.genStackTemplate(comp)
// TODO: actually save this (and any other outputs) to disk, rather than spewing to STDOUT.
y, err := yaml.Marshal(cf)
if err != nil {
@ -47,22 +47,22 @@ func (c *awsCloud) CodeGen(target *ast.Target, doc *diag.Document, stack *ast.St
}
// genClusterTemplate creates a CloudFormation template for a standard overall cluster.
func (c *awsCloud) genClusterTemplate(target *ast.Target, doc *diag.Document) *cfTemplate {
func (c *awsCloud) genClusterTemplate(comp core.Compiland) *cfTemplate {
// TODO: this.
return nil
}
// genStackName creates a name for the stack, which must be globally unique within an account.
func (c *awsCloud) genStackName(target *ast.Target, doc *diag.Document, stack *ast.Stack) string {
return fmt.Sprintf("MuStack-%v-%v", target.Name, stack.Name)
func (c *awsCloud) genStackName(comp core.Compiland) string {
return fmt.Sprintf("MuStack-%v-%v", comp.Target.Name, comp.Stack.Name)
}
// genStackTemplate creates a CloudFormation template for an entire stack and all of its services.
func (c *awsCloud) genStackTemplate(target *ast.Target, doc *diag.Document, stack *ast.Stack) *cfTemplate {
func (c *awsCloud) genStackTemplate(comp core.Compiland) *cfTemplate {
// Allocate a new template object that we will populate and return.
cf := &cfTemplate{
AWSTemplateFormatVersion: cfVersion,
Description: stack.Description,
Description: comp.Stack.Description,
}
// TODO: add parameters.
@ -74,13 +74,13 @@ func (c *awsCloud) genStackTemplate(target *ast.Target, doc *diag.Document, stac
// Emit the services. Although services can depend on one another, the order in which we emit them here doesn't
// matter. The reason is that those dependencies are "runtime"-based and will get resolved elsewhere.
for _, svc := range ast.StableServices(stack.Services.Private) {
private := stack.Services.Private[svc]
cf.Resources[string(private.Name)] = *c.genServiceTemplate(target, doc, stack, &private)
for _, svc := range ast.StableServices(comp.Stack.Services.Private) {
private := comp.Stack.Services.Private[svc]
cf.Resources[string(private.Name)] = *c.genServiceTemplate(comp, &private)
}
for _, svc := range ast.StableServices(stack.Services.Public) {
public := stack.Services.Public[svc]
cf.Resources[string(public.Name)] = *c.genServiceTemplate(target, doc, stack, &public)
for _, svc := range ast.StableServices(comp.Stack.Services.Public) {
public := comp.Stack.Services.Public[svc]
cf.Resources[string(public.Name)] = *c.genServiceTemplate(comp, &public)
}
// TODO: emit output exports (public services) that can be consumed by other stacks.
@ -89,8 +89,6 @@ func (c *awsCloud) genStackTemplate(target *ast.Target, doc *diag.Document, stac
}
// genServiceTemplate creates a CloudFormation resource for a single service.
func (c *awsCloud) genServiceTemplate(target *ast.Target, doc *diag.Document, stack *ast.Stack,
svc *ast.Service) *cfResource {
func (c *awsCloud) genServiceTemplate(comp core.Compiland, svc *ast.Service) *cfResource {
return nil
}

View file

@ -118,7 +118,7 @@ func (c *compiler) buildDocument(doc *diag.Document, outp string) {
// Now get the backend cloud provider to process the stack from here on out.
be := backends.New(arch)
be.CodeGen(target, doc, stack)
be.CodeGen(core.Compiland{c.Diag(), target, doc, stack})
}
}

View file

@ -11,5 +11,13 @@ import (
type Backend interface {
Phase
// CodeGen lowers and emits code for the given target and stack.
CodeGen(target *ast.Target, doc *diag.Document, stack *ast.Stack)
CodeGen(comp Compiland)
}
// Compiland contains all of settings passed from front-end to back-end compiler phases.
type Compiland struct {
Diag diag.Sink // a shared diagnostics sink to use for warnings, errors, etc.
Target *ast.Target // the compilation target.
Doc *diag.Document // the document from which the root stack came.
Stack *ast.Stack // the root stack to compile.
}