1/*
2 * gomacro - A Go interpreter with Lisp-like macros
3 *
4 * Copyright (C) 2017-2019 Massimiliano Ghilardi
5 *
6 *     This Source Code Form is subject to the terms of the Mozilla Public
7 *     License, v. 2.0. If a copy of the MPL was not distributed with this
8 *     file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 *
11 * import.go
12 *
13 *  Created on Apr 02, 2017
14 *      Author Massimiliano Ghilardi
15 */
16
17package fast
18
19import (
20	"go/ast"
21	r "reflect"
22	"strconv"
23	"strings"
24	"unsafe"
25
26	. "github.com/cosmos72/gomacro/base"
27	"github.com/cosmos72/gomacro/base/genimport"
28	"github.com/cosmos72/gomacro/base/output"
29	"github.com/cosmos72/gomacro/base/paths"
30	"github.com/cosmos72/gomacro/base/reflect"
31	"github.com/cosmos72/gomacro/base/untyped"
32	xr "github.com/cosmos72/gomacro/xreflect"
33)
34
35// =========================== forget package ==================================
36
37// remove package 'path' from the list of known packages.
38// later attempts to import it again will trigger a recompile.
39func (cg *CompGlobals) UnloadPackage(path string) {
40	cg.Globals.UnloadPackage(path)
41	delete(cg.KnownImports, path)
42}
43
44// ========================== switch to package ================================
45
46func (ir *Interp) ChangePackage(name, path string) {
47	if len(path) == 0 {
48		path = name
49	} else {
50		name = paths.FileName(path)
51	}
52	c := ir.Comp
53	if path == c.Path {
54		return
55	}
56	// load requested package if it exists, but do not define any binding in current one
57	newp, err := c.ImportPackageOrError("_", path)
58	if err != nil {
59		c.Debugf("%v", err)
60	}
61	oldp := ir.asImport()
62
63	c.CompGlobals.KnownImports[oldp.Path] = oldp // overwrite any cached import with same path as current Interp
64
65	trace := c.Globals.Options&OptShowPrompt != 0
66	top := &Interp{c.TopComp(), ir.env.Top()}
67	if newp != nil {
68		newp.Name = name
69		*ir = newp.asInterpreter(top)
70		if trace {
71			c.Debugf("switched to package %v", newp)
72		}
73	} else {
74		// requested package does not exist - create an empty one
75		ir.Comp = NewComp(top.Comp, nil)
76		ir.env = NewEnv(top.env, 0, 0)
77		if c.Globals.Options&OptDebugger != 0 {
78			ir.env.DebugComp = ir.Comp
79		}
80		ir.Comp.Name = name
81		ir.Comp.Path = path
82		if trace {
83			c.Debugf("switched to new package %v", path)
84		}
85	}
86	ir.env.Run.Globals.PackagePath = path
87}
88
89// convert *Interp to *Import. used to change package from 'ir'
90func (ir *Interp) asImport() *Import {
91	env := ir.env
92	env.MarkUsedByClosure() // do not try to recycle this Env
93	return &Import{
94		CompBinds: ir.Comp.CompBinds,
95		EnvBinds:  &ir.env.EnvBinds,
96		env:       env,
97	}
98}
99
100// convert *Import to *Interp. used to change package to 'imp'
101func (imp *Import) asInterpreter(outer *Interp) Interp {
102	c := NewComp(outer.Comp, nil)
103	c.CompBinds = imp.CompBinds
104	env := imp.env
105	// preserve env.IP, env.Code[], env.DebugPos[]
106	if env.Outer == nil {
107		env.Outer = outer.env
108	}
109	env.Run = outer.env.Run
110	return Interp{c, env}
111}
112
113// =========================== import package =================================
114
115// ImportPackage imports a package. Panics if the import fails.
116// If name is the empty string, it defaults to the identifier
117// specified in the package clause of the imported package
118func (ir *Interp) ImportPackage(name, path string) *Import {
119	return ir.Comp.ImportPackage(name, path)
120}
121
122// ImportPackageOrError imports a package.
123// If name is the empty string, it defaults to the identifier
124// specified in the package clause of the imported package
125func (ir *Interp) ImportPackageOrError(name, path string) (*Import, error) {
126	return ir.Comp.ImportPackageOrError(name, path)
127}
128
129// ImportPackage imports a package. Panics if the import fails.
130// Usually invoked as Comp.FileComp().ImportPackage(name, path)
131// because imports are usually top-level statements in a source file.
132// But we also support local imports, i.e. import statements inside a function or block.
133func (c *Comp) ImportPackage(name, path string) *Import {
134	imp, err := c.ImportPackageOrError(name, path)
135	if err != nil {
136		panic(err)
137	}
138	return imp
139}
140
141// ImportPackageOrError imports a package.
142// If name is the empty string, it defaults to the identifier
143// specified in the package clause of the imported package
144func (c *Comp) ImportPackageOrError(name, path string) (*Import, error) {
145	g := c.CompGlobals
146	imp := g.KnownImports[path]
147	if imp == nil {
148		pkgref, err := g.Importer.ImportPackageOrError(name, path)
149		if err != nil {
150			return nil, err
151		}
152		imp = g.NewImport(pkgref)
153	}
154	if name == "." {
155		c.declDotImport0(imp)
156	} else if name != "_" {
157		// https://golang.org/ref/spec#Package_clause states:
158		// If the PackageName is omitted, it defaults to the identifier
159		// specified in the package clause of the imported package
160		if len(name) == 0 {
161			name = imp.Name
162		}
163		c.declImport0(name, imp)
164	}
165	g.KnownImports[path] = imp
166	return imp, nil
167}
168
169// Import compiles an import statement
170func (c *Comp) Import(node ast.Spec) {
171	switch node := node.(type) {
172	case *ast.ImportSpec:
173		str := node.Path.Value
174		path, err := strconv.Unquote(str)
175		if err != nil {
176			c.Errorf("error unescaping import path %q: %v", str, err)
177		}
178		path = c.sanitizeImportPath(path)
179		var name string
180		if node.Name != nil {
181			name = node.Name.Name
182		}
183		// yes, we support local imports
184		// i.e. a function or block can import packages
185		c.ImportPackage(name, path)
186	default:
187		c.Errorf("unimplemented import: %v", node)
188	}
189}
190
191func (g *CompGlobals) sanitizeImportPath(path string) string {
192	path = strings.Replace(path, "\\", "/", -1)
193	l := len(path)
194	if path == ".." || l >= 3 && (path[:3] == "../" || path[l-3:] == "/..") || strings.Contains(path, "/../") {
195		g.Errorf("invalid import %q: contains \"..\"", path)
196	}
197	if path == "." || l >= 2 && (path[:2] == "./" || path[l-2:] == "/.") || strings.Contains(path, "/./") {
198		g.Errorf("invalid import %q: contains \".\"", path)
199	}
200	return path
201}
202
203// declDotImport0 compiles an import declaration.
204// Note: does not loads proxies, use ImportPackage for that
205func (c *Comp) declImport0(name string, imp *Import) {
206	// treat imported package as a constant,
207	// because to compile code we need the declarations it contains:
208	// importing them at runtime would be too late.
209	bind := c.NewBind(name, ConstBind, c.TypeOfPtrImport())
210	bind.Value = imp // Comp.Binds[] is a map[string]*Bind => changes to *Bind propagate to the map
211}
212
213// declDotImport0 compiles an import . "path" declaration, i.e. a dot-import.
214// Note: does not loads proxies, use ImportPackage for that
215func (c *Comp) declDotImport0(imp *Import) {
216	// Note 2: looking at the difference between the above Comp.declImport0() and this ugly monster,
217	// shows one more reason why dot-imports are dirty and discouraged.
218	if c.Types == nil {
219		c.Types = make(map[string]xr.Type)
220	}
221	for name, typ := range imp.Types {
222		if t, exists := c.Types[name]; exists {
223			c.Warnf("redefined type: %v", t)
224		}
225		c.Types[name] = typ
226	}
227
228	var indexv, cindexv []int // mapping between Import.Vals[index] and Env.Vals[cindex]
229
230	var funv []func(*Env) r.Value
231	var findexv []int
232
233	for name, bind := range imp.Binds {
234		// use c.CompBinds.NewBind() to prevent optimization VarBind -> IntBind
235		// also, if class == IntBind, we must preserve the address of impenv.Ints[idx]
236		// thus we must convert it into a VarBind (argh!)
237		class := bind.Desc.Class()
238		if class == IntBind {
239			class = VarBind
240		}
241		cbind := c.CompBinds.NewBind(&c.Output, name, class, bind.Type)
242		cidx := cbind.Desc.Index()
243		switch bind.Desc.Class() {
244		case ConstBind:
245			cbind.Value = bind.Value
246		case IntBind:
247			if cidx == NoIndex {
248				continue
249			}
250			// this is painful. and slow
251			fun := imp.intPlace(c, bind, PlaceSettable).Fun
252			funv = append(funv, fun)
253			findexv = append(findexv, cidx)
254		default:
255			if cidx == NoIndex {
256				continue
257			}
258			indexv = append(indexv, bind.Desc.Index())
259			cindexv = append(cindexv, cidx)
260		}
261	}
262	if len(indexv) != 0 || len(funv) != 0 {
263		impvals := imp.Vals
264		c.append(func(env *Env) (Stmt, *Env) {
265			for i, index := range indexv {
266				env.Vals[cindexv[i]] = impvals[index]
267			}
268			for i, fun := range funv {
269				env.Vals[findexv[i]] = fun(nil) // fun(env) is unnecessary
270			}
271			env.IP++
272			return env.Code[env.IP], env
273		})
274	}
275}
276
277func (g *CompGlobals) NewImport(pkgref *genimport.PackageRef) *Import {
278	env := &Env{
279		UsedByClosure: true, // do not try to recycle this Env
280	}
281	imp := &Import{
282		EnvBinds: &env.EnvBinds,
283		env:      env,
284	}
285	if pkgref != nil {
286		imp.Name = pkgref.Name
287		imp.Path = pkgref.Path
288		imp.loadTypes(g, pkgref)
289		imp.loadBinds(g, pkgref)
290		g.loadProxies(pkgref.Proxies, imp.Types)
291	}
292	return imp
293}
294
295func (imp *Import) loadBinds(g *CompGlobals, pkgref *genimport.PackageRef) {
296	vals := make([]r.Value, len(pkgref.Binds))
297	untypeds := pkgref.Untypeds
298	o := &g.Output
299	for name, val := range pkgref.Binds {
300		if untyped, ok := untypeds[name]; ok {
301			untypedlit, typ := g.parseUntyped(untyped)
302			if typ != nil {
303				bind := imp.CompBinds.NewBind(o, name, ConstBind, typ)
304				bind.Value = untypedlit
305				continue
306			}
307		}
308		k := val.Kind()
309		class := FuncBind
310		// distinguish typed constants, variables and functions
311		if val.IsValid() && val.CanAddr() && val.CanSet() {
312			class = VarBind
313		} else if k == r.Invalid || (reflect.IsOptimizedKind(k) && val.CanInterface()) {
314			class = ConstBind
315		}
316		typ := g.Universe.FromReflectType(val.Type())
317		bind := imp.CompBinds.NewBind(o, name, class, typ)
318		if class == ConstBind && k != r.Invalid {
319			bind.Value = val.Interface()
320		}
321		idx := bind.Desc.Index()
322		if idx == NoIndex {
323			continue
324		}
325		if len(vals) <= idx {
326			tmp := make([]r.Value, idx*2)
327			copy(tmp, vals)
328			vals = tmp
329		}
330		vals[idx] = val
331	}
332	imp.Vals = vals
333}
334
335func (g *CompGlobals) parseUntyped(untypedstr string) (UntypedLit, xr.Type) {
336	kind, value := untyped.Unmarshal(untypedstr)
337	if kind == untyped.None {
338		return UntypedLit{}, nil
339	}
340	lit := untyped.MakeLit(kind, value, &g.Universe.BasicTypes)
341	return lit, g.TypeOfUntypedLit()
342}
343
344func (imp *Import) loadTypes(g *CompGlobals, pkgref *genimport.PackageRef) {
345	v := g.Universe
346	types := make(map[string]xr.Type)
347	wrappers := pkgref.Wrappers
348	for name, rtype := range pkgref.Types {
349		// Universe.FromReflectType uses cached *types.Package if possible
350		t := v.FromReflectType(rtype)
351		if twrappers := wrappers[name]; len(twrappers) != 0 {
352			t.RemoveMethods(twrappers, "")
353		}
354		types[name] = t
355	}
356	imp.Types = types
357}
358
359// loadProxies adds to thread-global maps the proxies found in import
360func (g *CompGlobals) loadProxies(proxies map[string]r.Type, xtypes map[string]xr.Type) {
361	for name, proxy := range proxies {
362		xtype := xtypes[name]
363		if xtype == nil {
364			g.Warnf("import %q: type not found for proxy <%v>", proxy.PkgPath(), proxy)
365			continue
366		}
367		if xtype.Kind() != r.Interface {
368			g.Warnf("import %q: type for proxy <%v> is not an interface: %v", proxy.PkgPath(), proxy, xtype)
369			continue
370		}
371		rtype := xtype.ReflectType()
372		g.interf2proxy[rtype] = proxy
373		g.proxy2interf[proxy] = xtype
374	}
375}
376
377// ======================== use package symbols ===============================
378
379// selectorPlace compiles pkgname.varname returning a settable and/or addressable Place
380func (imp *Import) selectorPlace(c *Comp, name string, opt PlaceOption) *Place {
381	bind, ok := imp.Binds[name]
382	if !ok {
383		c.Errorf("package %v %q has no symbol %s", imp.Name, imp.Path, name)
384	}
385	class := bind.Desc.Class()
386	if bind.Desc.Index() != NoIndex {
387		switch class {
388		case IntBind:
389			return imp.intPlace(c, bind, opt)
390		case VarBind:
391			// optimization: read imp.Vals[] at compile time:
392			// val remains valid even if imp.Vals[] is reallocated
393			val := imp.Vals[bind.Desc.Index()]
394			// a settable reflect.Value is always addressable.
395			// the converse is not guaranteed: unexported fields can be addressed but not set.
396			// see implementation of reflect.Value.CanAddr() and reflect.Value.CanSet() for details
397			if val.IsValid() && val.CanAddr() && val.CanSet() {
398				return &Place{
399					Var: Var{Type: bind.Type},
400					Fun: func(*Env) r.Value {
401						return val
402					},
403					Addr: func(*Env) r.Value {
404						return val.Addr()
405					},
406				}
407			}
408		}
409	}
410	c.Errorf("%v %v %v.%v", opt, class, bind.Type.Kind(), imp.Name, name)
411	return nil
412}
413
414// selector compiles foo.bar where 'foo' is an imported package
415func (imp *Import) selector(name string, st *output.Stringer) *Expr {
416	bind, ok := imp.Binds[name]
417	if !ok {
418		st.Errorf("package %v %q has no symbol %s", imp.Name, imp.Path, name)
419	}
420	switch bind.Desc.Class() {
421	case ConstBind:
422		return exprLit(bind.Lit, bind.AsSymbol(0))
423	case FuncBind, VarBind:
424		return imp.symbol(bind, st)
425	case IntBind:
426		return imp.intSymbol(bind, st)
427	default:
428		st.Errorf("package symbol %s.%s has unknown class %s", imp.Name, name, bind.Desc.Class())
429		return nil
430	}
431}
432
433// create an expression that will return the value of imported variable described by bind.
434//
435// mandatory optimization: for basic kinds, unwrap reflect.Value
436func (imp *Import) symbol(bind *Bind, st *output.Stringer) *Expr {
437	idx := bind.Desc.Index()
438	if idx == NoIndex {
439		st.Errorf("undefined identifier %s._", imp.Name)
440	}
441	// optimization: read imp.Vals[] at compile time:
442	// v remains valid even if imp.Vals[] is reallocated
443	v := imp.Vals[idx]
444	t := bind.Type
445	if !v.IsValid() {
446		return exprValue(t, xr.Zero(t).Interface())
447	}
448	var fun I
449	switch t.Kind() {
450	case r.Bool:
451		fun = func(*Env) bool {
452			return v.Bool()
453		}
454	case r.Int:
455		fun = func(*Env) int {
456			return int(v.Int())
457		}
458	case r.Int8:
459		fun = func(*Env) int8 {
460			return int8(v.Int())
461		}
462	case r.Int16:
463		fun = func(*Env) int16 {
464			return int16(v.Int())
465		}
466	case r.Int32:
467		fun = func(*Env) int32 {
468			return int32(v.Int())
469		}
470	case r.Int64:
471		fun = func(*Env) int64 {
472			return v.Int()
473		}
474	case r.Uint:
475		fun = func(*Env) uint {
476			return uint(v.Uint())
477		}
478	case r.Uint8:
479		fun = func(*Env) uint8 {
480			return uint8(v.Uint())
481		}
482	case r.Uint16:
483		fun = func(*Env) uint16 {
484			return uint16(v.Uint())
485		}
486	case r.Uint32:
487		fun = func(*Env) uint32 {
488			return uint32(v.Uint())
489		}
490	case r.Uint64:
491		fun = func(*Env) uint64 {
492			return v.Uint()
493		}
494	case r.Uintptr:
495		fun = func(*Env) uintptr {
496			return uintptr(v.Uint())
497		}
498	case r.Float32:
499		fun = func(*Env) float32 {
500			return float32(v.Float())
501		}
502	case r.Float64:
503		fun = func(*Env) float64 {
504			return v.Float()
505		}
506	case r.Complex64:
507		fun = func(*Env) complex64 {
508			return complex64(v.Complex())
509		}
510	case r.Complex128:
511		fun = func(*Env) complex128 {
512			return v.Complex()
513		}
514	case r.String:
515		fun = func(*Env) string {
516			return v.String()
517		}
518	default:
519		fun = func(*Env) r.Value {
520			return v
521		}
522	}
523	// v is an imported variable. do NOT store its value in *Expr,
524	// because that's how constants are represented:
525	// fast interpreter will then (incorrectly) perform constant propagation.
526	return exprFun(t, fun)
527}
528
529// create an expression that will return the value of imported variable described by bind.
530//
531// mandatory optimization: for basic kinds, do not wrap in reflect.Value
532func (imp *Import) intSymbol(bind *Bind, st *output.Stringer) *Expr {
533	idx := bind.Desc.Index()
534	if idx == NoIndex {
535		st.Errorf("undefined identifier %s._", imp.Name)
536	}
537	t := bind.Type
538	env := imp.env
539	var fun I
540	switch t.Kind() {
541	case r.Bool:
542		fun = func(*Env) bool {
543			return *(*bool)(unsafe.Pointer(&env.Ints[idx]))
544		}
545	case r.Int:
546		fun = func(*Env) int {
547			return *(*int)(unsafe.Pointer(&env.Ints[idx]))
548		}
549	case r.Int8:
550		fun = func(*Env) int8 {
551			return *(*int8)(unsafe.Pointer(&env.Ints[idx]))
552		}
553	case r.Int16:
554		fun = func(*Env) int16 {
555			return *(*int16)(unsafe.Pointer(&env.Ints[idx]))
556		}
557	case r.Int32:
558		fun = func(*Env) int32 {
559			return *(*int32)(unsafe.Pointer(&env.Ints[idx]))
560		}
561	case r.Int64:
562		fun = func(*Env) int64 {
563			return *(*int64)(unsafe.Pointer(&env.Ints[idx]))
564		}
565	case r.Uint:
566		fun = func(*Env) uint {
567			return *(*uint)(unsafe.Pointer(&env.Ints[idx]))
568		}
569	case r.Uint8:
570		fun = func(*Env) uint8 {
571			return *(*uint8)(unsafe.Pointer(&env.Ints[idx]))
572		}
573	case r.Uint16:
574		fun = func(*Env) uint16 {
575			return *(*uint16)(unsafe.Pointer(&env.Ints[idx]))
576		}
577	case r.Uint32:
578		fun = func(*Env) uint32 {
579			return *(*uint32)(unsafe.Pointer(&env.Ints[idx]))
580		}
581	case r.Uint64:
582		fun = func(*Env) uint64 {
583			return env.Ints[idx]
584		}
585	case r.Uintptr:
586		fun = func(*Env) uintptr {
587			return *(*uintptr)(unsafe.Pointer(&env.Ints[idx]))
588		}
589	case r.Float32:
590		fun = func(*Env) float32 {
591			return *(*float32)(unsafe.Pointer(&env.Ints[idx]))
592		}
593	case r.Float64:
594		fun = func(*Env) float64 {
595			return *(*float64)(unsafe.Pointer(&env.Ints[idx]))
596		}
597	case r.Complex64:
598		fun = func(*Env) complex64 {
599			return *(*complex64)(unsafe.Pointer(&env.Ints[idx]))
600		}
601	case r.Complex128:
602		fun = func(*Env) complex128 {
603			return *(*complex128)(unsafe.Pointer(&env.Ints[idx]))
604		}
605	default:
606		st.Errorf("unsupported symbol type, cannot use for optimized read: %v %v.%v <%v>",
607			bind.Desc.Class(), imp.Name, bind.Name, bind.Type)
608		return nil
609	}
610	// Do NOT store env.Ints[idx] into *Expr, because that's how constants are represented:
611	// fast interpreter will then (incorrectly) perform constant propagation.
612	return exprFun(t, fun)
613}
614
615// return a Place representing the imported variable described by bind.
616//
617// mandatory optimization: for basic kinds, do not wrap in reflect.Value
618func (imp *Import) intPlace(c *Comp, bind *Bind, opt PlaceOption) *Place {
619	idx := bind.Desc.Index()
620	if idx == NoIndex {
621		c.Errorf("%v %v %v.%v", opt, bind.Desc.Class(), imp.Name, bind.Name)
622	}
623	t := bind.Type
624	var addr func(*Env) r.Value
625	impenv := imp.env
626	switch t.Kind() {
627	case r.Bool:
628		addr = func(env *Env) r.Value {
629			return r.ValueOf((*bool)(unsafe.Pointer(&impenv.Ints[idx])))
630		}
631	case r.Int:
632		addr = func(env *Env) r.Value {
633			return r.ValueOf((*int)(unsafe.Pointer(&impenv.Ints[idx])))
634		}
635	case r.Int8:
636		addr = func(env *Env) r.Value {
637			return r.ValueOf((*int8)(unsafe.Pointer(&impenv.Ints[idx])))
638		}
639	case r.Int16:
640		addr = func(env *Env) r.Value {
641			return r.ValueOf((*int16)(unsafe.Pointer(&impenv.Ints[idx])))
642		}
643	case r.Int32:
644		addr = func(env *Env) r.Value {
645			return r.ValueOf((*int32)(unsafe.Pointer(&impenv.Ints[idx])))
646		}
647	case r.Int64:
648		addr = func(env *Env) r.Value {
649			return r.ValueOf((*int64)(unsafe.Pointer(&impenv.Ints[idx])))
650		}
651	case r.Uint:
652		addr = func(env *Env) r.Value {
653			return r.ValueOf((*uint)(unsafe.Pointer(&impenv.Ints[idx])))
654		}
655	case r.Uint8:
656		addr = func(env *Env) r.Value {
657			return r.ValueOf((*uint8)(unsafe.Pointer(&impenv.Ints[idx])))
658		}
659	case r.Uint16:
660		addr = func(env *Env) r.Value {
661			return r.ValueOf((*uint16)(unsafe.Pointer(&impenv.Ints[idx])))
662		}
663	case r.Uint32:
664		addr = func(env *Env) r.Value {
665			return r.ValueOf((*uint32)(unsafe.Pointer(&impenv.Ints[idx])))
666		}
667	case r.Uint64:
668		addr = func(env *Env) r.Value {
669			return r.ValueOf(&impenv.Ints[idx])
670		}
671	case r.Uintptr:
672		addr = func(env *Env) r.Value {
673			return r.ValueOf((*uintptr)(unsafe.Pointer(&impenv.Ints[idx])))
674		}
675	case r.Float32:
676		addr = func(env *Env) r.Value {
677			return r.ValueOf((*float32)(unsafe.Pointer(&impenv.Ints[idx])))
678		}
679	case r.Float64:
680		addr = func(env *Env) r.Value {
681			return r.ValueOf((*float64)(unsafe.Pointer(&impenv.Ints[idx])))
682		}
683	case r.Complex64:
684		addr = func(env *Env) r.Value {
685			return r.ValueOf((*complex64)(unsafe.Pointer(&impenv.Ints[idx])))
686		}
687	case r.Complex128:
688		addr = func(env *Env) r.Value {
689			return r.ValueOf((*complex128)(unsafe.Pointer(&impenv.Ints[idx])))
690		}
691	default:
692		c.Errorf("%s unsupported variable type <%v>: %s %s.%s",
693			opt, t, bind.Desc.Class(), imp.Name, bind.Name)
694		return nil
695	}
696	return &Place{
697		Var: Var{Type: bind.Type, Name: bind.Name},
698		Fun: func(env *Env) r.Value {
699			return addr(env).Elem()
700		},
701		Addr: addr,
702	}
703}
704