more additions to pkgctx
This commit is contained in:
parent
84c615ac58
commit
17004883e8
@ -1,5 +1,17 @@
|
||||
package pkgctx
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mediocregopher/ginger/seq"
|
||||
"github.com/mediocregopher/ginger/types"
|
||||
)
|
||||
|
||||
const (
|
||||
coreAbs = "github.com/mediocregopher/ginger/core"
|
||||
coreAlias = "gingercore"
|
||||
)
|
||||
|
||||
// PkgCtx is given to all macros and represents the package that they are being
|
||||
// evaluated within.
|
||||
type PkgCtx struct {
|
||||
@ -16,3 +28,86 @@ type PkgCtx struct {
|
||||
// use it during testing
|
||||
CallMap map[string]interface{}
|
||||
}
|
||||
|
||||
// Returns an empty PkgCtx
|
||||
func New() *PkgCtx {
|
||||
return &PkgCtx{
|
||||
Packages: map[string]string{},
|
||||
CallMap: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// A returns a new PkgCtx, which is a copy of a merge between p and p2. p2's
|
||||
// keys overwrite any conflicting keys in p. p and p2 are unaffected by this
|
||||
// operation
|
||||
func (p *PkgCtx) MergeLeft(p2 *PkgCtx) *PkgCtx {
|
||||
p3 := New()
|
||||
for pkg := range p.Packages {
|
||||
p3.Packages[pkg] = p.Packages[pkg]
|
||||
}
|
||||
for pkg := range p2.Packages {
|
||||
p3.Packages[pkg] = p2.Packages[pkg]
|
||||
}
|
||||
for fn := range p.CallMap {
|
||||
p3.CallMap[fn] = p.CallMap[fn]
|
||||
}
|
||||
for fn := range p2.CallMap {
|
||||
p3.CallMap[fn] = p2.CallMap[fn]
|
||||
}
|
||||
return p3
|
||||
}
|
||||
|
||||
// Returns a copy of p
|
||||
func (p *PkgCtx) Copy() *PkgCtx {
|
||||
return p.MergeLeft(New())
|
||||
}
|
||||
|
||||
func (p *PkgCtx) PopulateFromCode(el types.Elem) bool {
|
||||
if s, ok := el.(seq.Seq); ok {
|
||||
return seq.Traverse(p.PopulateFromCode, s)
|
||||
}
|
||||
|
||||
gt, ok := el.(types.GoType)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
str, ok := gt.V.(string)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(str) < 2 {
|
||||
return true
|
||||
}
|
||||
|
||||
if str[0] != ':' {
|
||||
return true
|
||||
}
|
||||
str = str[1:]
|
||||
|
||||
// At this point str is a reference to something. We check if it's already
|
||||
// pointing somewhere first
|
||||
if _, ok = p.CallMap[str]; ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// If there isn't a '.' in the string, it's not directly referencing another
|
||||
// package. Since it isn't in this context either, it must be referencing
|
||||
// something in core
|
||||
var i int
|
||||
if i = strings.IndexRune(str, '.'); i < 1 {
|
||||
p.Packages[coreAbs] = coreAlias
|
||||
p.CallMap[str] = nil
|
||||
|
||||
// TODO there needs to be a CodeGen interface or something. The
|
||||
// CallMap's value type needs to be that, because in all likelyhood the
|
||||
// CallMap will be directly translated to a map variable in the
|
||||
// generated package, with the values being different depending on what
|
||||
// they're being used for (external functions will be references to
|
||||
// those functions, local variables may just end up being just GoType's
|
||||
// of the actual value.
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user