gitee.com/wgliang/goreporter@v0.0.0-20180902115603-df1b20f7c5d0/linters/simpler/ssa/lvalue.go (about)

     1  // Copyright 2013 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  // +build go1.5
     6  
     7  package ssa
     8  
     9  // lvalues are the union of addressable expressions and map-index
    10  // expressions.
    11  
    12  import (
    13  	"go/ast"
    14  	"go/token"
    15  	"go/types"
    16  )
    17  
    18  // An lvalue represents an assignable location that may appear on the
    19  // left-hand side of an assignment.  This is a generalization of a
    20  // pointer to permit updates to elements of maps.
    21  //
    22  type lvalue interface {
    23  	store(fn *Function, v Value) // stores v into the location
    24  	load(fn *Function) Value     // loads the contents of the location
    25  	address(fn *Function) Value  // address of the location
    26  	typ() types.Type             // returns the type of the location
    27  }
    28  
    29  // An address is an lvalue represented by a true pointer.
    30  type address struct {
    31  	addr Value
    32  	pos  token.Pos // source position
    33  	expr ast.Expr  // source syntax of the value (not address) [debug mode]
    34  }
    35  
    36  func (a *address) load(fn *Function) Value {
    37  	load := emitLoad(fn, a.addr)
    38  	load.pos = a.pos
    39  	return load
    40  }
    41  
    42  func (a *address) store(fn *Function, v Value) {
    43  	store := emitStore(fn, a.addr, v, a.pos)
    44  	if a.expr != nil {
    45  		// store.Val is v, converted for assignability.
    46  		emitDebugRef(fn, a.expr, store.Val, false)
    47  	}
    48  }
    49  
    50  func (a *address) address(fn *Function) Value {
    51  	if a.expr != nil {
    52  		emitDebugRef(fn, a.expr, a.addr, true)
    53  	}
    54  	return a.addr
    55  }
    56  
    57  func (a *address) typ() types.Type {
    58  	return deref(a.addr.Type())
    59  }
    60  
    61  // An element is an lvalue represented by m[k], the location of an
    62  // element of a map or string.  These locations are not addressable
    63  // since pointers cannot be formed from them, but they do support
    64  // load(), and in the case of maps, store().
    65  //
    66  type element struct {
    67  	m, k Value      // map or string
    68  	t    types.Type // map element type or string byte type
    69  	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
    70  }
    71  
    72  func (e *element) load(fn *Function) Value {
    73  	l := &Lookup{
    74  		X:     e.m,
    75  		Index: e.k,
    76  	}
    77  	l.setPos(e.pos)
    78  	l.setType(e.t)
    79  	return fn.emit(l)
    80  }
    81  
    82  func (e *element) store(fn *Function, v Value) {
    83  	up := &MapUpdate{
    84  		Map:   e.m,
    85  		Key:   e.k,
    86  		Value: emitConv(fn, v, e.t),
    87  	}
    88  	up.pos = e.pos
    89  	fn.emit(up)
    90  }
    91  
    92  func (e *element) address(fn *Function) Value {
    93  	panic("map/string elements are not addressable")
    94  }
    95  
    96  func (e *element) typ() types.Type {
    97  	return e.t
    98  }
    99  
   100  // A blank is a dummy variable whose name is "_".
   101  // It is not reified: loads are illegal and stores are ignored.
   102  //
   103  type blank struct{}
   104  
   105  func (bl blank) load(fn *Function) Value {
   106  	panic("blank.load is illegal")
   107  }
   108  
   109  func (bl blank) store(fn *Function, v Value) {
   110  	s := &BlankStore{
   111  		Val: v,
   112  	}
   113  	fn.emit(s)
   114  }
   115  
   116  func (bl blank) address(fn *Function) Value {
   117  	panic("blank var is not addressable")
   118  }
   119  
   120  func (bl blank) typ() types.Type {
   121  	// This should be the type of the blank Ident; the typechecker
   122  	// doesn't provide this yet, but fortunately, we don't need it
   123  	// yet either.
   124  	panic("blank.typ is unimplemented")
   125  }