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