]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/noder/expr.go
all: fix typos in go file comments
[gostls13.git] / src / cmd / compile / internal / noder / expr.go
1 // Copyright 2021 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package noder
6
7 import (
8         "fmt"
9
10         "cmd/compile/internal/base"
11         "cmd/compile/internal/ir"
12         "cmd/compile/internal/syntax"
13         "cmd/compile/internal/typecheck"
14         "cmd/compile/internal/types"
15         "cmd/compile/internal/types2"
16         "cmd/internal/src"
17 )
18
19 func (g *irgen) expr(expr syntax.Expr) ir.Node {
20         expr = unparen(expr) // skip parens; unneeded after parse+typecheck
21
22         if expr == nil {
23                 return nil
24         }
25
26         if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
27                 return ir.BlankNode
28         }
29
30         tv := g.typeAndValue(expr)
31         switch {
32         case tv.IsBuiltin():
33                 // Qualified builtins, such as unsafe.Add and unsafe.Slice.
34                 if expr, ok := expr.(*syntax.SelectorExpr); ok {
35                         if name, ok := expr.X.(*syntax.Name); ok {
36                                 if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
37                                         return g.use(expr.Sel)
38                                 }
39                         }
40                 }
41                 return g.use(expr.(*syntax.Name))
42         case tv.IsType():
43                 return ir.TypeNode(g.typ(tv.Type))
44         case tv.IsValue(), tv.IsVoid():
45                 // ok
46         default:
47                 base.FatalfAt(g.pos(expr), "unrecognized type-checker result")
48         }
49
50         base.Assert(g.exprStmtOK)
51
52         typ := idealType(tv)
53         if typ == nil {
54                 base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", tv.Type)
55         }
56
57         // Constant expression.
58         if tv.Value != nil {
59                 typ := g.typ(typ)
60                 value := FixValue(typ, tv.Value)
61                 return OrigConst(g.pos(expr), typ, value, constExprOp(expr), syntax.String(expr))
62         }
63
64         n := g.expr0(typ, expr)
65         if n.Typecheck() != 1 && n.Typecheck() != 3 {
66                 base.FatalfAt(g.pos(expr), "missed typecheck: %+v", n)
67         }
68         if n.Op() != ir.OFUNCINST && !g.match(n.Type(), typ, tv.HasOk()) {
69                 base.FatalfAt(g.pos(expr), "expected %L to have type %v", n, typ)
70         }
71         return n
72 }
73
74 func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
75         pos := g.pos(expr)
76         assert(pos.IsKnown())
77
78         // Set base.Pos for transformation code that still uses base.Pos, rather than
79         // the pos of the node being converted.
80         base.Pos = pos
81
82         switch expr := expr.(type) {
83         case *syntax.Name:
84                 if _, isNil := g.info.Uses[expr].(*types2.Nil); isNil {
85                         return Nil(pos, g.typ(typ))
86                 }
87                 return g.use(expr)
88
89         case *syntax.CompositeLit:
90                 return g.compLit(typ, expr)
91
92         case *syntax.FuncLit:
93                 return g.funcLit(typ, expr)
94
95         case *syntax.AssertExpr:
96                 return Assert(pos, g.expr(expr.X), g.typeExpr(expr.Type))
97
98         case *syntax.CallExpr:
99                 fun := g.expr(expr.Fun)
100                 return g.callExpr(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots)
101
102         case *syntax.IndexExpr:
103                 args := unpackListExpr(expr.Index)
104                 if len(args) == 1 {
105                         tv := g.typeAndValue(args[0])
106                         if tv.IsValue() {
107                                 // This is just a normal index expression
108                                 n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0]))
109                                 if !g.delayTransform() {
110                                         // transformIndex will modify n.Type() for OINDEXMAP.
111                                         transformIndex(n)
112                                 }
113                                 return n
114                         }
115                 }
116
117                 // expr.Index is a list of type args, so we ignore it, since types2 has
118                 // already provided this info with the Info.Instances map.
119                 return g.expr(expr.X)
120
121         case *syntax.SelectorExpr:
122                 // Qualified identifier.
123                 if name, ok := expr.X.(*syntax.Name); ok {
124                         if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
125                                 return g.use(expr.Sel)
126                         }
127                 }
128                 return g.selectorExpr(pos, typ, expr)
129
130         case *syntax.SliceExpr:
131                 n := Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2]))
132                 if !g.delayTransform() {
133                         transformSlice(n)
134                 }
135                 return n
136
137         case *syntax.Operation:
138                 if expr.Y == nil {
139                         n := Unary(pos, g.typ(typ), g.op(expr.Op, unOps[:]), g.expr(expr.X))
140                         if n.Op() == ir.OADDR && !g.delayTransform() {
141                                 transformAddr(n.(*ir.AddrExpr))
142                         }
143                         return n
144                 }
145                 switch op := g.op(expr.Op, binOps[:]); op {
146                 case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
147                         n := Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y))
148                         if !g.delayTransform() {
149                                 transformCompare(n)
150                         }
151                         return n
152                 case ir.OANDAND, ir.OOROR:
153                         x := g.expr(expr.X)
154                         y := g.expr(expr.Y)
155                         return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
156                 default:
157                         n := Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y))
158                         if op == ir.OADD && !g.delayTransform() {
159                                 return transformAdd(n)
160                         }
161                         return n
162                 }
163
164         default:
165                 g.unhandled("expression", expr)
166                 panic("unreachable")
167         }
168 }
169
170 // substType does a normal type substitution, but tparams is in the form of a field
171 // list, and targs is in terms of a slice of type nodes. substType records any newly
172 // instantiated types into g.instTypeList.
173 func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Ntype) *types.Type {
174         fields := tparams.FieldSlice()
175         tparams1 := make([]*types.Type, len(fields))
176         for i, f := range fields {
177                 tparams1[i] = f.Type
178         }
179         targs1 := make([]*types.Type, len(targs))
180         for i, n := range targs {
181                 targs1[i] = n.Type()
182         }
183         ts := typecheck.Tsubster{
184                 Tparams: tparams1,
185                 Targs:   targs1,
186         }
187         newt := ts.Typ(typ)
188         return newt
189 }
190
191 // callExpr creates a call expression (which might be a type conversion, built-in
192 // call, or a regular call) and does standard transforms, unless we are in a generic
193 // function.
194 func (g *irgen) callExpr(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node {
195         n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
196         n.IsDDD = dots
197         typed(typ, n)
198
199         if fun.Op() == ir.OTYPE {
200                 // Actually a type conversion, not a function call.
201                 if !g.delayTransform() {
202                         return transformConvCall(n)
203                 }
204                 return n
205         }
206
207         if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
208                 if !g.delayTransform() {
209                         return transformBuiltin(n)
210                 }
211                 return n
212         }
213
214         // Add information, now that we know that fun is actually being called.
215         switch fun := fun.(type) {
216         case *ir.SelectorExpr:
217                 if fun.Op() == ir.OMETHVALUE {
218                         op := ir.ODOTMETH
219                         if fun.X.Type().IsInterface() {
220                                 op = ir.ODOTINTER
221                         }
222                         fun.SetOp(op)
223                         // Set the type to include the receiver, since that's what
224                         // later parts of the compiler expect
225                         fun.SetType(fun.Selection.Type)
226                 }
227         }
228
229         // A function instantiation (even if fully concrete) shouldn't be
230         // transformed yet, because we need to add the dictionary during the
231         // transformation.
232         if fun.Op() != ir.OFUNCINST && !g.delayTransform() {
233                 transformCall(n)
234         }
235         return n
236 }
237
238 // selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually
239 // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
240 // than in typecheck.go.
241 func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
242         x := g.expr(expr.X)
243         if x.Type().HasTParam() {
244                 // Leave a method call on a type param as an OXDOT, since it can
245                 // only be fully transformed once it has an instantiated type.
246                 n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
247                 typed(g.typ(typ), n)
248                 return n
249         }
250
251         selinfo := g.info.Selections[expr]
252         // Everything up to the last selection is an implicit embedded field access,
253         // and the last selection is determined by selinfo.Kind().
254         index := selinfo.Index()
255         embeds, last := index[:len(index)-1], index[len(index)-1]
256
257         origx := x
258         for _, ix := range embeds {
259                 x = Implicit(DotField(pos, x, ix))
260         }
261
262         kind := selinfo.Kind()
263         if kind == types2.FieldVal {
264                 return DotField(pos, x, last)
265         }
266
267         var n ir.Node
268         method2 := selinfo.Obj().(*types2.Func)
269
270         if kind == types2.MethodExpr {
271                 // OMETHEXPR is unusual in using directly the node and type of the
272                 // original OTYPE node (origx) before passing through embedded
273                 // fields, even though the method is selected from the type
274                 // (x.Type()) reached after following the embedded fields. We will
275                 // actually drop any ODOT nodes we created due to the embedded
276                 // fields.
277                 n = MethodExpr(pos, origx, x.Type(), last)
278         } else {
279                 // Add implicit addr/deref for method values, if needed.
280                 if x.Type().IsInterface() {
281                         n = DotMethod(pos, x, last)
282                 } else {
283                         recvType2 := method2.Type().(*types2.Signature).Recv().Type()
284                         _, wantPtr := recvType2.(*types2.Pointer)
285                         havePtr := x.Type().IsPtr()
286
287                         if havePtr != wantPtr {
288                                 if havePtr {
289                                         x = Implicit(Deref(pos, x.Type().Elem(), x))
290                                 } else {
291                                         x = Implicit(Addr(pos, x))
292                                 }
293                         }
294                         recvType2Base := recvType2
295                         if wantPtr {
296                                 recvType2Base = types2.AsPointer(recvType2).Elem()
297                         }
298                         if recvType2Base.(*types2.Named).TypeParams().Len() > 0 {
299                                 // recvType2 is the original generic type that is
300                                 // instantiated for this method call.
301                                 // selinfo.Recv() is the instantiated type
302                                 recvType2 = recvType2Base
303                                 recvTypeSym := g.pkg(method2.Pkg()).Lookup(recvType2.(*types2.Named).Obj().Name())
304                                 recvType := recvTypeSym.Def.(*ir.Name).Type()
305                                 // method is the generic method associated with
306                                 // the base generic type. The instantiated type may not
307                                 // have method bodies filled in, if it was imported.
308                                 method := recvType.Methods().Index(last).Nname.(*ir.Name)
309                                 n = ir.NewSelectorExpr(pos, ir.OMETHVALUE, x, typecheck.Lookup(expr.Sel.Value))
310                                 n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
311                                 n.(*ir.SelectorExpr).Selection.Nname = method
312                                 typed(method.Type(), n)
313
314                                 xt := deref(x.Type())
315                                 targs := make([]ir.Ntype, len(xt.RParams()))
316                                 for i := range targs {
317                                         targs[i] = ir.TypeNode(xt.RParams()[i])
318                                 }
319
320                                 // Create function instantiation with the type
321                                 // args for the receiver type for the method call.
322                                 n = ir.NewInstExpr(pos, ir.OFUNCINST, n, targs)
323                                 typed(g.typ(typ), n)
324                                 return n
325                         }
326
327                         if !g.match(x.Type(), recvType2, false) {
328                                 base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
329                         } else {
330                                 n = DotMethod(pos, x, last)
331                         }
332                 }
333         }
334         if have, want := n.Sym(), g.selector(method2); have != want {
335                 base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
336         }
337         return n
338 }
339
340 func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
341         return g.exprs(unpackListExpr(expr))
342 }
343
344 func unpackListExpr(expr syntax.Expr) []syntax.Expr {
345         switch expr := expr.(type) {
346         case nil:
347                 return nil
348         case *syntax.ListExpr:
349                 return expr.ElemList
350         default:
351                 return []syntax.Expr{expr}
352         }
353 }
354
355 func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
356         nodes := make([]ir.Node, len(exprs))
357         for i, expr := range exprs {
358                 nodes[i] = g.expr(expr)
359         }
360         return nodes
361 }
362
363 func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
364         if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
365                 n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
366                 n.SetOp(ir.OPTRLIT)
367                 return typed(g.typ(typ), n)
368         }
369
370         _, isStruct := types2.CoreType(typ).(*types2.Struct)
371
372         exprs := make([]ir.Node, len(lit.ElemList))
373         for i, elem := range lit.ElemList {
374                 switch elem := elem.(type) {
375                 case *syntax.KeyValueExpr:
376                         var key ir.Node
377                         if isStruct {
378                                 key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name)))
379                         } else {
380                                 key = g.expr(elem.Key)
381                         }
382                         value := wrapname(g.pos(elem.Value), g.expr(elem.Value))
383                         if value.Op() == ir.OPAREN {
384                                 // Make sure any PAREN node added by wrapper has a type
385                                 typed(value.(*ir.ParenExpr).X.Type(), value)
386                         }
387                         exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value)
388                 default:
389                         exprs[i] = wrapname(g.pos(elem), g.expr(elem))
390                         if exprs[i].Op() == ir.OPAREN {
391                                 // Make sure any PAREN node added by wrapper has a type
392                                 typed(exprs[i].(*ir.ParenExpr).X.Type(), exprs[i])
393                         }
394                 }
395         }
396
397         n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs)
398         typed(g.typ(typ), n)
399         var r ir.Node = n
400         if !g.delayTransform() {
401                 r = transformCompLit(n)
402         }
403         return r
404 }
405
406 func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
407         fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != nil)
408         ir.NameClosure(fn.OClosure, ir.CurFunc)
409
410         typ := g.typ(typ2)
411         typed(typ, fn.Nname)
412         typed(typ, fn.OClosure)
413         fn.SetTypecheck(1)
414
415         g.funcBody(fn, nil, expr.Type, expr.Body)
416
417         ir.FinishCaptureNames(fn.Pos(), ir.CurFunc, fn)
418
419         // TODO(mdempsky): ir.CaptureName should probably handle
420         // copying these fields from the canonical variable.
421         for _, cv := range fn.ClosureVars {
422                 cv.SetType(cv.Canonical().Type())
423                 cv.SetTypecheck(1)
424         }
425
426         if g.topFuncIsGeneric {
427                 // Don't add any closure inside a generic function/method to the
428                 // g.target.Decls list, even though it may not be generic itself.
429                 // See issue #47514.
430                 return ir.UseClosure(fn.OClosure, nil)
431         } else {
432                 return ir.UseClosure(fn.OClosure, g.target)
433         }
434 }
435
436 func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
437         n := g.expr(typ)
438         if n.Op() != ir.OTYPE {
439                 base.FatalfAt(g.pos(typ), "expected type: %L", n)
440         }
441         return n.Type()
442 }
443
444 // constExprOp returns an ir.Op that represents the outermost
445 // operation of the given constant expression. It's intended for use
446 // with ir.RawOrigExpr.
447 func constExprOp(expr syntax.Expr) ir.Op {
448         switch expr := expr.(type) {
449         default:
450                 panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr))
451
452         case *syntax.BasicLit:
453                 return ir.OLITERAL
454         case *syntax.Name, *syntax.SelectorExpr:
455                 return ir.ONAME
456         case *syntax.CallExpr:
457                 return ir.OCALL
458         case *syntax.Operation:
459                 if expr.Y == nil {
460                         return unOps[expr.Op]
461                 }
462                 return binOps[expr.Op]
463         }
464 }
465
466 func unparen(expr syntax.Expr) syntax.Expr {
467         for {
468                 paren, ok := expr.(*syntax.ParenExpr)
469                 if !ok {
470                         return expr
471                 }
472                 expr = paren.X
473         }
474 }