2018-11-30 20:43:31 -08:00
|
|
|
package build
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
2018-12-17 21:20:21 -08:00
|
|
|
"go/types"
|
2018-12-08 21:16:03 -08:00
|
|
|
|
2018-11-30 20:43:31 -08:00
|
|
|
"github.com/mmcloughlin/avo"
|
2019-01-02 21:35:17 -08:00
|
|
|
"github.com/mmcloughlin/avo/buildtags"
|
2018-12-11 00:18:22 -08:00
|
|
|
"github.com/mmcloughlin/avo/gotypes"
|
2018-12-21 00:30:59 -08:00
|
|
|
"github.com/mmcloughlin/avo/operand"
|
2018-12-03 20:40:43 -08:00
|
|
|
"github.com/mmcloughlin/avo/reg"
|
2018-12-17 20:52:26 -08:00
|
|
|
"golang.org/x/tools/go/packages"
|
2018-11-30 20:43:31 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Context struct {
|
2018-12-17 20:52:26 -08:00
|
|
|
pkg *packages.Package
|
2018-11-30 20:43:31 -08:00
|
|
|
file *avo.File
|
|
|
|
|
function *avo.Function
|
2018-12-27 11:57:46 -08:00
|
|
|
global *avo.Global
|
2018-11-30 20:43:31 -08:00
|
|
|
errs []error
|
2018-12-03 20:40:43 -08:00
|
|
|
reg.Collection
|
2018-11-30 20:43:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewContext() *Context {
|
|
|
|
|
return &Context{
|
2018-12-03 20:40:43 -08:00
|
|
|
file: avo.NewFile(),
|
|
|
|
|
Collection: *reg.NewCollection(),
|
2018-11-30 20:43:31 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-17 20:52:26 -08:00
|
|
|
func (c *Context) Package(path string) {
|
|
|
|
|
cfg := &packages.Config{
|
|
|
|
|
Mode: packages.LoadTypes,
|
|
|
|
|
}
|
|
|
|
|
pkgs, err := packages.Load(cfg, path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
pkg := pkgs[0]
|
|
|
|
|
if len(pkg.Errors) > 0 {
|
|
|
|
|
for _, err := range pkg.Errors {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.pkg = pkg
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-02 21:55:43 -08:00
|
|
|
func (c *Context) Constraints(t buildtags.ConstraintsConvertable) {
|
2019-01-02 21:35:17 -08:00
|
|
|
cs := t.ToConstraints()
|
|
|
|
|
if err := cs.Validate(); err != nil {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.file.Constraints = cs
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-02 21:55:43 -08:00
|
|
|
func (c *Context) Constraint(t buildtags.ConstraintConvertable) {
|
|
|
|
|
c.Constraints(append(c.file.Constraints, t.ToConstraint()))
|
2019-01-02 21:35:17 -08:00
|
|
|
}
|
|
|
|
|
|
2019-01-02 21:55:43 -08:00
|
|
|
func (c *Context) ConstraintExpr(expr string) {
|
2019-01-02 21:35:17 -08:00
|
|
|
constraint, err := buildtags.ParseConstraint(expr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-01-02 21:55:43 -08:00
|
|
|
c.Constraint(constraint)
|
2019-01-02 21:35:17 -08:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:58:51 -08:00
|
|
|
func (c *Context) Function(name string) {
|
2018-11-30 20:43:31 -08:00
|
|
|
c.function = avo.NewFunction(name)
|
2018-12-27 11:57:46 -08:00
|
|
|
c.file.AddSection(c.function)
|
2018-11-30 20:43:31 -08:00
|
|
|
}
|
|
|
|
|
|
2018-12-27 23:01:27 -08:00
|
|
|
func (c *Context) Doc(lines ...string) {
|
|
|
|
|
c.activefunc().Doc = lines
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-30 23:35:49 -08:00
|
|
|
func (c *Context) Attributes(a avo.Attribute) {
|
|
|
|
|
c.activefunc().Attributes = a
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-08 21:16:03 -08:00
|
|
|
func (c *Context) Signature(s *gotypes.Signature) {
|
|
|
|
|
c.activefunc().SetSignature(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) SignatureExpr(expr string) {
|
2018-12-17 21:20:21 -08:00
|
|
|
s, err := gotypes.ParseSignatureInPackage(c.types(), expr)
|
2018-12-08 21:16:03 -08:00
|
|
|
if err != nil {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
c.Signature(s)
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-17 21:20:21 -08:00
|
|
|
func (c *Context) types() *types.Package {
|
|
|
|
|
if c.pkg == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return c.pkg.Types
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-21 00:30:59 -08:00
|
|
|
func (c *Context) AllocLocal(size int) operand.Mem {
|
|
|
|
|
return c.activefunc().AllocLocal(size)
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-02 23:59:29 -08:00
|
|
|
func (c *Context) Instruction(i *avo.Instruction) {
|
2018-12-08 21:16:03 -08:00
|
|
|
c.activefunc().AddNode(i)
|
2018-11-30 21:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) Label(l avo.Label) {
|
2018-12-08 21:16:03 -08:00
|
|
|
c.activefunc().AddLabel(l)
|
2018-11-30 21:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2018-12-08 21:16:03 -08:00
|
|
|
func (c *Context) activefunc() *avo.Function {
|
2018-11-30 20:43:31 -08:00
|
|
|
if c.function == nil {
|
|
|
|
|
c.AddErrorMessage("no active function")
|
2018-12-08 21:16:03 -08:00
|
|
|
return avo.NewFunction("")
|
2018-11-30 20:43:31 -08:00
|
|
|
}
|
2018-12-08 21:16:03 -08:00
|
|
|
return c.function
|
2018-11-30 20:43:31 -08:00
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:58:51 -08:00
|
|
|
//go:generate avogen -output zinstructions.go build
|
|
|
|
|
|
2018-12-27 11:57:46 -08:00
|
|
|
func (c *Context) StaticGlobal(name string) operand.Mem {
|
|
|
|
|
c.global = avo.NewStaticGlobal(name)
|
|
|
|
|
c.file.AddSection(c.global)
|
|
|
|
|
return c.global.Base()
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-31 19:04:14 -08:00
|
|
|
func (c *Context) DataAttributes(a avo.Attribute) {
|
|
|
|
|
c.activeglobal().Attributes = a
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-27 11:57:46 -08:00
|
|
|
func (c *Context) AddDatum(offset int, v operand.Constant) {
|
|
|
|
|
if err := c.activeglobal().AddDatum(avo.NewDatum(offset, v)); err != nil {
|
|
|
|
|
c.AddError(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) AppendDatum(v operand.Constant) {
|
|
|
|
|
c.activeglobal().Append(v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) activeglobal() *avo.Global {
|
|
|
|
|
if c.global == nil {
|
|
|
|
|
c.AddErrorMessage("no active global")
|
|
|
|
|
return avo.NewStaticGlobal("")
|
|
|
|
|
}
|
|
|
|
|
return c.global
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-30 20:43:31 -08:00
|
|
|
func (c *Context) AddError(err error) {
|
|
|
|
|
c.errs = append(c.errs, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) AddErrorMessage(msg string) {
|
|
|
|
|
c.AddError(errors.New(msg))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Context) Result() (*avo.File, []error) {
|
|
|
|
|
return c.file, c.errs
|
|
|
|
|
}
|