Skip to content

Commit 874e3a1

Browse files
committed
cl: record builtin
1 parent 669ffaa commit 874e3a1

File tree

8 files changed

+320
-34
lines changed

8 files changed

+320
-34
lines changed

Diff for: cl/builtin.go

+35-13
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type Builtin struct {
3636
name string
3737
pkg string
3838
sym string
39+
fn bool
3940
}
4041

4142
func (t *Builtin) Parent() *types.Scope {
@@ -65,12 +66,15 @@ func (t *Builtin) String() string {
6566
func (t *Builtin) Sym() string {
6667
return t.pkg + "." + t.sym
6768
}
69+
func (t *Builtin) IsFunc() bool {
70+
return t.fn
71+
}
6872

6973
var (
7074
Universe *types.Scope
7175
)
7276

73-
var builtinDefs = [...]struct {
77+
var builtinTypes = [...]struct {
7478
name string
7579
pkg string
7680
sym string
@@ -80,6 +84,13 @@ var builtinDefs = [...]struct {
8084
{"bigfloat", "github.com/goplus/gop/builtin/ng", ""},
8185
{"int128", "github.com/goplus/gop/builtin/ng", ""},
8286
{"uint128", "github.com/goplus/gop/builtin/ng", ""},
87+
}
88+
89+
var builtinFuncs = [...]struct {
90+
name string
91+
pkg string
92+
sym string
93+
}{
8394
{"lines", "github.com/goplus/gop/builtin/iox", ""},
8495
{"blines", "github.com/goplus/gop/builtin/iox", "BLines"},
8596
{"newRange", "github.com/goplus/gop/builtin", "NewRange__0"},
@@ -101,35 +112,46 @@ var builtinDefs = [...]struct {
101112
type defSym struct {
102113
name string
103114
sym string
115+
fn bool
104116
}
105117

106118
var (
107119
builtinSym map[string][]defSym
108120
)
109121

122+
func insertBuiltin(name, pkg, sym string, fn bool) {
123+
if sym == "" {
124+
sym = string(name[0]-('a'-'A')) + name[1:]
125+
}
126+
builtinSym[pkg] = append(builtinSym[pkg], defSym{name: name, sym: sym, fn: fn})
127+
obj := &Builtin{name: name, pkg: pkg, sym: sym, fn: fn}
128+
Universe.Insert(obj)
129+
}
130+
110131
func init() {
111132
Universe = types.NewScope(nil, 0, 0, "universe")
112133
builtinSym = make(map[string][]defSym)
113-
for _, def := range builtinDefs {
114-
if def.sym == "" {
115-
def.sym = string(def.name[0]-('a'-'A')) + def.name[1:]
116-
}
117-
builtinSym[def.pkg] = append(builtinSym[def.pkg], defSym{name: def.name, sym: def.sym})
118-
obj := &Builtin{name: def.name, pkg: def.pkg, sym: def.sym}
119-
Universe.Insert(obj)
134+
for _, def := range builtinTypes {
135+
insertBuiltin(def.name, def.pkg, def.sym, false)
136+
}
137+
for _, def := range builtinFuncs {
138+
insertBuiltin(def.name, def.pkg, def.sym, true)
120139
}
121140
}
122141

123-
func initBuiltin(pkg *gogen.Package, builtin *types.Package) {
142+
func initBuiltin(pkg *gogen.Package, builtin *types.Package, conf *gogen.Config) {
124143
scope := builtin.Scope()
125144
for im, defs := range builtinSym {
126145
if p := pkg.TryImport(im); p.Types != nil {
127146
for _, def := range defs {
128147
obj := p.Ref(def.sym)
129-
if _, ok := obj.Type().(*types.Named); ok {
130-
scope.Insert(types.NewTypeName(token.NoPos, builtin, def.name, obj.Type()))
131-
} else {
148+
if def.fn {
132149
scope.Insert(gogen.NewOverloadFunc(token.NoPos, builtin, def.name, obj))
150+
} else {
151+
scope.Insert(types.NewTypeName(token.NoPos, builtin, def.name, obj.Type()))
152+
}
153+
if rec, ok := conf.Recorder.(*goxRecorder); ok {
154+
rec.Builtin(def.name, obj)
133155
}
134156
}
135157
}
@@ -147,7 +169,7 @@ func newBuiltinDefault(pkg *gogen.Package, conf *gogen.Config) *types.Package {
147169
if ng.Types != nil {
148170
initMathBig(pkg, conf, ng)
149171
}
150-
initBuiltin(pkg, builtin)
172+
initBuiltin(pkg, builtin, conf)
151173
gogen.InitBuiltin(pkg, builtin, conf)
152174
if strx.Types != nil {
153175
ti := pkg.BuiltinTI(types.Typ[types.String])

Diff for: cl/cltest/recorder.go

+3
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,6 @@ func (info gopRecorder) Select(e *ast.SelectorExpr, sel *types.Selection) {
121121
// *ast.RangeStmt
122122
func (info gopRecorder) Scope(n ast.Node, scope *types.Scope) {
123123
}
124+
125+
func (info gopRecorder) Builtin(name string, obj types.Object) {
126+
}

Diff for: cl/compile.go

+3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ type Recorder interface {
163163
// *ast.LambdaExpr2
164164
//
165165
Scope(ast.Node, *types.Scope)
166+
167+
// Go+ builtin name object
168+
Builtin(name string, obj types.Object)
166169
}
167170

168171
// -----------------------------------------------------------------------------

Diff for: cl/internal/typesutil/api.go

+6
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,9 @@ func NewTypeAndValueForObject(obj types.Object) (ret types.TypeAndValue) {
114114
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = mode
115115
return
116116
}
117+
118+
func NewTypeAndValueForBuiltin(obj types.Object) (ret types.TypeAndValue) {
119+
ret.Type = obj.Type()
120+
(*TypeAndValue)(unsafe.Pointer(&ret)).mode = Builtin
121+
return
122+
}

Diff for: cl/internal/typesutil/api_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,8 @@ func TestTypeAndValue(t *testing.T) {
8080
if !ret.IsBuiltin() {
8181
t.Fatal("NewTypeAndValueForObject: not builtin?")
8282
}
83+
ret = NewTypeAndValueForBuiltin(types.Universe.Lookup("len"))
84+
if !ret.IsBuiltin() {
85+
t.Fatal("NewTypeAndValueForObject: not builtin?")
86+
}
8387
}

Diff for: cl/recorder.go

+34-6
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ type goxRecorder struct {
3232
types map[ast.Expr]types.TypeAndValue
3333
referDefs map[*ast.Ident]ast.Node
3434
referUses map[string][]*ast.Ident
35+
builtin map[*ast.Ident]struct{}
3536
}
3637

3738
func newRecorder(rec Recorder) *goxRecorder {
3839
types := make(map[ast.Expr]types.TypeAndValue)
3940
referDefs := make(map[*ast.Ident]ast.Node)
4041
referUses := make(map[string][]*ast.Ident)
41-
return &goxRecorder{rec, types, referDefs, referUses}
42+
builtin := make(map[*ast.Ident]struct{})
43+
return &goxRecorder{Recorder: rec, types: types, referDefs: referDefs,
44+
referUses: referUses, builtin: builtin}
4245
}
4346

4447
// Refer uses maps identifiers to name for ast.OverloadFuncDecl.
@@ -127,23 +130,22 @@ func (p *goxRecorder) Member(id ast.Node, obj types.Object) {
127130
p.Type(v, tv)
128131
}
129132
case *ast.Ident: // it's in a classfile and impossible converted from Go
130-
p.Use(v, obj)
131-
p.Type(v, typesutil.NewTypeAndValueForObject(obj))
133+
p.recordIdent(v, obj)
132134
}
133135
}
134136

135137
func (p *goxRecorder) Call(id ast.Node, obj types.Object) {
136138
switch v := id.(type) {
137139
case *ast.Ident:
138-
p.Use(v, obj)
139-
p.Type(v, typesutil.NewTypeAndValueForObject(obj))
140+
p.recordIdent(v, obj)
140141
case *ast.SelectorExpr:
141142
p.Use(v.Sel, obj)
142143
p.Type(v, typesutil.NewTypeAndValueForObject(obj))
143144
case *ast.CallExpr:
144145
switch id := v.Fun.(type) {
145146
case *ast.Ident:
146-
p.Use(id, obj)
147+
p.recordIdent(id, obj)
148+
return
147149
case *ast.SelectorExpr:
148150
p.Use(id.Sel, obj)
149151
}
@@ -253,10 +255,36 @@ func (rec *goxRecorder) recordType(typ ast.Expr, t types.Type) {
253255
}
254256

255257
func (rec *goxRecorder) recordIdent(ident *ast.Ident, obj types.Object) {
258+
if _, ok := rec.builtin[ident]; ok {
259+
return
260+
}
261+
if o, ok := isBuiltinFunc(ident, obj); ok {
262+
rec.builtin[ident] = struct{}{}
263+
rec.Use(ident, o)
264+
rec.Type(ident, typesutil.NewTypeAndValueForBuiltin(o))
265+
return
266+
}
256267
rec.Use(ident, obj)
257268
rec.Type(ident, typesutil.NewTypeAndValueForObject(obj))
258269
}
259270

271+
func isBuiltinFunc(ident *ast.Ident, obj types.Object) (types.Object, bool) {
272+
if pkg := obj.Pkg(); pkg == nil || (pkg.Path() == "" && pkg.Name() == "") {
273+
if o := Universe.Lookup(ident.Name); o != nil && o.(*Builtin).IsFunc() {
274+
return o, true
275+
}
276+
switch ident.Name {
277+
case "append", "cap", "clear", "close", "complex", "copy",
278+
"delete", "imag", "len", "make", "max", "min", "new",
279+
"panic", "real", "recover":
280+
if o := types.Universe.Lookup(ident.Name); o != nil {
281+
return o, true
282+
}
283+
}
284+
}
285+
return nil, false
286+
}
287+
260288
func (rec *goxRecorder) recordExpr(ctx *blockCtx, expr ast.Expr, _ bool) {
261289
switch v := expr.(type) {
262290
case *ast.Ident:

Diff for: x/typesutil/gopinfo.go

+13
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ type Info struct {
138138

139139
// Overloads maps identifiers to the overload decl object.
140140
Overloads map[*ast.Ident]types.Object
141+
142+
// Builtins maps identifiers the Go+ builtin name object.
143+
Builtins map[string]types.Object
141144
}
142145

143146
// ObjectOf returns the object denoted by the specified id,
@@ -188,6 +191,9 @@ type gopRecorder struct {
188191

189192
// NewRecorder creates a new recorder for cl.NewPackage.
190193
func NewRecorder(info *Info) cl.Recorder {
194+
if info == nil {
195+
return nil
196+
}
191197
return gopRecorder{info}
192198
}
193199

@@ -334,4 +340,11 @@ func (info gopRecorder) Scope(n ast.Node, scope *types.Scope) {
334340
}
335341
}
336342

343+
// Go+ builtin name object
344+
func (info gopRecorder) Builtin(name string, obj types.Object) {
345+
if info.Builtins != nil {
346+
info.Builtins[name] = obj
347+
}
348+
}
349+
337350
// -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)