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