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 }