Skip to content

Commit fd7f85a

Browse files
committed
cl: record builtin
1 parent 16cebf4 commit fd7f85a

File tree

8 files changed

+321
-49
lines changed

8 files changed

+321
-49
lines changed

cl/builtin.go

Lines changed: 37 additions & 28 deletions
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,6 +66,9 @@ 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
@@ -74,33 +78,35 @@ var builtinDefs = [...]struct {
7478
name string
7579
pkg string
7680
sym string
81+
fn bool
7782
}{
78-
{"bigint", "github.com/goplus/gop/builtin/ng", ""},
79-
{"bigrat", "github.com/goplus/gop/builtin/ng", ""},
80-
{"bigfloat", "github.com/goplus/gop/builtin/ng", ""},
81-
{"int128", "github.com/goplus/gop/builtin/ng", ""},
82-
{"uint128", "github.com/goplus/gop/builtin/ng", ""},
83-
{"lines", "github.com/goplus/gop/builtin/iox", ""},
84-
{"blines", "github.com/goplus/gop/builtin/iox", "BLines"},
85-
{"newRange", "github.com/goplus/gop/builtin", "NewRange__0"},
86-
{"echo", "fmt", "Println"},
87-
{"print", "fmt", ""},
88-
{"println", "fmt", ""},
89-
{"printf", "fmt", ""},
90-
{"errorf", "fmt", ""},
91-
{"fprint", "fmt", ""},
92-
{"fprintln", "fmt", ""},
93-
{"sprint", "fmt", ""},
94-
{"sprintln", "fmt", ""},
95-
{"sprintf", "fmt", ""},
96-
{"open", "os", ""},
97-
{"create", "os", ""},
98-
{"type", "reflect", "TypeOf"},
83+
{"bigint", "github.com/goplus/gop/builtin/ng", "", false},
84+
{"bigrat", "github.com/goplus/gop/builtin/ng", "", false},
85+
{"bigfloat", "github.com/goplus/gop/builtin/ng", "", false},
86+
{"int128", "github.com/goplus/gop/builtin/ng", "", false},
87+
{"uint128", "github.com/goplus/gop/builtin/ng", "", false},
88+
{"lines", "github.com/goplus/gop/builtin/iox", "", true},
89+
{"blines", "github.com/goplus/gop/builtin/iox", "BLines", true},
90+
{"newRange", "github.com/goplus/gop/builtin", "NewRange__0", true},
91+
{"echo", "fmt", "Println", true},
92+
{"print", "fmt", "", true},
93+
{"println", "fmt", "", true},
94+
{"printf", "fmt", "", true},
95+
{"errorf", "fmt", "", true},
96+
{"fprint", "fmt", "", true},
97+
{"fprintln", "fmt", "", true},
98+
{"sprint", "fmt", "", true},
99+
{"sprintln", "fmt", "", true},
100+
{"sprintf", "fmt", "", true},
101+
{"open", "os", "", true},
102+
{"create", "os", "", true},
103+
{"type", "reflect", "TypeOf", true},
99104
}
100105

101106
type defSym struct {
102107
name string
103108
sym string
109+
fn bool
104110
}
105111

106112
var (
@@ -114,22 +120,25 @@ func init() {
114120
if def.sym == "" {
115121
def.sym = string(def.name[0]-('a'-'A')) + def.name[1:]
116122
}
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}
123+
builtinSym[def.pkg] = append(builtinSym[def.pkg], defSym{name: def.name, sym: def.sym, fn: def.fn})
124+
obj := &Builtin{name: def.name, pkg: def.pkg, sym: def.sym, fn: def.fn}
119125
Universe.Insert(obj)
120126
}
121127
}
122128

123-
func initBuiltin(pkg *gogen.Package, builtin *types.Package) {
129+
func initBuiltin(pkg *gogen.Package, builtin *types.Package, conf *gogen.Config) {
124130
scope := builtin.Scope()
125131
for im, defs := range builtinSym {
126132
if p := pkg.TryImport(im); p.Types != nil {
127133
for _, def := range defs {
128134
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 {
135+
if def.fn {
132136
scope.Insert(gogen.NewOverloadFunc(token.NoPos, builtin, def.name, obj))
137+
} else {
138+
scope.Insert(types.NewTypeName(token.NoPos, builtin, def.name, obj.Type()))
139+
}
140+
if rec, ok := conf.Recorder.(*goxRecorder); ok {
141+
rec.Builtin(def.name, obj)
133142
}
134143
}
135144
}
@@ -147,7 +156,7 @@ func newBuiltinDefault(pkg *gogen.Package, conf *gogen.Config) *types.Package {
147156
if ng.Types != nil {
148157
initMathBig(pkg, conf, ng)
149158
}
150-
initBuiltin(pkg, builtin)
159+
initBuiltin(pkg, builtin, conf)
151160
gogen.InitBuiltin(pkg, builtin, conf)
152161
if strx.Types != nil {
153162
ti := pkg.BuiltinTI(types.Typ[types.String])

cl/cltest/recorder.go

Lines changed: 3 additions & 0 deletions
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+
}

cl/compile.go

Lines changed: 3 additions & 0 deletions
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
// -----------------------------------------------------------------------------

cl/internal/typesutil/api.go

Lines changed: 6 additions & 0 deletions
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+
}

cl/internal/typesutil/api_test.go

Lines changed: 4 additions & 0 deletions
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
}

cl/recorder.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ 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+
return &goxRecorder{Recorder: rec, types: types, referDefs: referDefs, referUses: referUses,
43+
builtin: make(map[*ast.Ident]struct{})}
4244
}
4345

4446
// Refer uses maps identifiers to name for ast.OverloadFuncDecl.
@@ -127,23 +129,22 @@ func (p *goxRecorder) Member(id ast.Node, obj types.Object) {
127129
p.Type(v, tv)
128130
}
129131
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))
132+
p.recordIdent(v, obj)
132133
}
133134
}
134135

135136
func (p *goxRecorder) Call(id ast.Node, obj types.Object) {
136137
switch v := id.(type) {
137138
case *ast.Ident:
138-
p.Use(v, obj)
139-
p.Type(v, typesutil.NewTypeAndValueForObject(obj))
139+
p.recordIdent(v, obj)
140140
case *ast.SelectorExpr:
141141
p.Use(v.Sel, obj)
142142
p.Type(v, typesutil.NewTypeAndValueForObject(obj))
143143
case *ast.CallExpr:
144144
switch id := v.Fun.(type) {
145145
case *ast.Ident:
146-
p.Use(id, obj)
146+
p.recordIdent(id, obj)
147+
return
147148
case *ast.SelectorExpr:
148149
p.Use(id.Sel, obj)
149150
}
@@ -253,10 +254,36 @@ func (rec *goxRecorder) recordType(typ ast.Expr, t types.Type) {
253254
}
254255

255256
func (rec *goxRecorder) recordIdent(ident *ast.Ident, obj types.Object) {
257+
if _, ok := rec.builtin[ident]; ok {
258+
return
259+
}
260+
if o, ok := isBuiltinFunc(ident, obj); ok {
261+
rec.builtin[ident] = struct{}{}
262+
rec.Use(ident, o)
263+
rec.Type(ident, typesutil.NewTypeAndValueForBuiltin(o))
264+
return
265+
}
256266
rec.Use(ident, obj)
257267
rec.Type(ident, typesutil.NewTypeAndValueForObject(obj))
258268
}
259269

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

x/typesutil/gopinfo.go

Lines changed: 13 additions & 0 deletions
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)