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 * type.go
12 *
13 *  Created on Apr 01, 2017
14 *      Author Massimiliano Ghilardi
15 */
16
17package fast
18
19import (
20	"fmt"
21	"go/ast"
22	"go/token"
23	r "reflect"
24
25	"github.com/cosmos72/gomacro/base/strings"
26
27	. "github.com/cosmos72/gomacro/base"
28	"github.com/cosmos72/gomacro/base/reflect"
29	"github.com/cosmos72/gomacro/base/untyped"
30	xr "github.com/cosmos72/gomacro/xreflect"
31)
32
33// DeclType compiles a type declaration.
34func (c *Comp) DeclType(spec ast.Spec) {
35	node, ok := spec.(*ast.TypeSpec)
36	if !ok {
37		c.Errorf("unexpected type declaration, expecting *ast.TypeSpec, found: %v // %T", spec, spec)
38	}
39	if GENERICS_V1 {
40		if lit, _ := node.Type.(*ast.CompositeLit); lit != nil {
41			c.DeclTemplateType(node)
42			return
43		}
44	}
45	name := node.Name.Name
46	// support type aliases
47	if node.Assign != token.NoPos {
48		t := c.Type(node.Type)
49		c.DeclTypeAlias(name, t)
50		return
51	}
52	// support self-referencing types, as for example: type List struct { First int; Rest *List }
53	oldt := c.Types[name]
54	panicking := true
55	defer func() {
56		// On compile error, restore pre-existing declaration
57		if !panicking || c.Types == nil {
58			// nothing to do
59		} else if oldt != nil {
60			c.Types[name] = oldt
61		} else {
62			delete(c.Types, name)
63		}
64	}()
65	t := c.DeclNamedType(name)
66	u := c.Type(node.Type)
67	if t != nil { // t == nil means name == "_", discard the result of type declaration
68		c.SetUnderlyingType(t, u)
69	}
70	panicking = false
71}
72
73// DeclTypeAlias compiles a typealias declaration, i.e. type Foo = /*...*/
74// Returns the second argument.
75func (c *Comp) DeclTypeAlias(name string, t xr.Type) xr.Type {
76	if name == "_" {
77		return t
78	}
79	if et := c.Types[name]; et != nil {
80		// forward-declared types have kind == r.Invalid, see Comp.DeclNamedType() below
81		if et.Kind() != r.Invalid {
82			c.Warnf("redefined type alias: %v", name)
83		}
84		c.Universe.InvalidateCache()
85	} else if c.Types == nil {
86		c.Types = make(map[string]xr.Type)
87	}
88	c.Types[name] = t
89	return t
90}
91
92// DeclTypeAlias0 declares a type alias
93// in Go, types are computed only at compile time - no need for a runtime *Env
94func (c *Comp) declTypeAlias(alias string, t xr.Type) xr.Type {
95	if alias == "" || alias == "_" {
96		// never define bindings for "_"
97		return t
98	}
99	if _, ok := c.Types[alias]; ok {
100		c.Warnf("redefined type: %v", alias)
101	} else if c.Types == nil {
102		c.Types = make(map[string]xr.Type)
103	}
104	c.Types[alias] = t
105	return t
106}
107
108// DeclNamedType executes a named type forward declaration.
109// Returns nil if name == "_"
110// Otherwise it must be followed by Comp.SetUnderlyingType(t) where t is the returned type
111func (c *Comp) DeclNamedType(name string) xr.Type {
112	if name == "_" {
113		return nil
114	}
115	if t := c.Types[name]; t != nil {
116		if t.Kind() != r.Invalid {
117			c.Warnf("redefined type: %v", name)
118		}
119		if xr.QName1(t) != xr.QName2(name, c.FileComp().Path) {
120			// the current type "name" is an alias, discard it
121			c.Universe.InvalidateCache()
122		} else {
123			// reuse t, change only its underlying type
124			return t
125		}
126	} else if c.Types == nil {
127		c.Types = make(map[string]xr.Type)
128	}
129	t := c.Universe.NamedOf(name, c.FileComp().Path, r.Invalid /*kind not yet known*/)
130	c.Types[name] = t
131	return t
132}
133
134func (c *Comp) SetUnderlyingType(t, underlying xr.Type) {
135	t.SetUnderlying(underlying)
136}
137
138// DeclType0 declares a type
139// in Go, types are computed only at compile time - no need for a runtime *Env
140func (c *Comp) DeclType0(t xr.Type) xr.Type {
141	if t == nil {
142		return nil
143	}
144	return c.declTypeAlias(t.Name(), t)
145}
146
147// Type compiles a type expression.
148func (c *Comp) Type(node ast.Expr) xr.Type {
149	t, _ := c.compileType2(node, false)
150	return t
151}
152
153// compileTypeOrNil compiles a type expression. as a special case used by type switch, compiles *ast.Ident{Name:"nil"} to nil
154func (c *Comp) compileTypeOrNil(node ast.Expr) xr.Type {
155	for {
156		switch expr := node.(type) {
157		case *ast.ParenExpr:
158			node = expr.X
159			continue
160		case *ast.Ident:
161			if expr.Name == "nil" {
162				sym := c.TryResolve(expr.Name)
163				if sym != nil && sym.Type == nil {
164					return nil
165				}
166			}
167		}
168		break
169	}
170	t, _ := c.compileType2(node, false)
171	return t
172}
173
174// compileType2 compiles a type expression.
175// if allowEllipsis is true, it supports the special case &ast.Ellipsis{/*expression*/}
176// that represents ellipsis in the last argument of a function declaration.
177// The second return value is true both in the case above, and for array types whose length is [...]
178func (c *Comp) compileType2(node ast.Expr, allowEllipsis bool) (t xr.Type, ellipsis bool) {
179	stars := 0
180	for {
181		switch expr := node.(type) {
182		case *ast.StarExpr:
183			stars++
184			node = expr.X
185			continue
186		case *ast.ParenExpr:
187			node = expr.X
188			continue
189		case *ast.Ellipsis:
190			if allowEllipsis {
191				node = expr.Elt
192				ellipsis = true
193				continue
194			}
195		}
196		break
197	}
198	if node != nil {
199		c.Pos = node.Pos()
200	}
201	universe := c.Universe
202	var ellipsisArray bool
203
204	switch node := node.(type) {
205	case *ast.ArrayType: // also for slices
206		t, ellipsisArray = c.TypeArray(node)
207	case *ast.ChanType:
208		telem := c.Type(node.Value)
209		dir := r.BothDir
210		if node.Dir == ast.SEND {
211			dir = r.SendDir
212		} else if node.Dir == ast.RECV {
213			dir = r.RecvDir
214		}
215		t = universe.ChanOf(dir, telem)
216	case *ast.FuncType:
217		t, _, _ = c.TypeFunction(node)
218	case *ast.Ident:
219		t = c.ResolveType(node.Name)
220	case *ast.IndexExpr:
221		if GENERICS_V1 {
222			t = c.TemplateType(node)
223		} else {
224			c.Errorf("unimplemented type: %v <%v>", node, r.TypeOf(node))
225		}
226	case *ast.InterfaceType:
227		t = c.TypeInterface(node)
228	case *ast.MapType:
229		kt := c.Type(node.Key)
230		vt := c.Type(node.Value)
231		t = universe.MapOf(kt, vt)
232	case *ast.SelectorExpr:
233		ident, ok := node.X.(*ast.Ident)
234		if !ok {
235			c.Errorf("invalid qualified type, expecting packagename.identifier, found: %v <%v>", node, r.TypeOf(node))
236		}
237		// this could be Package.Type, or other non-type expressions: Type.Method, Value.Method, Struct.Field...
238		// check for Package.Type
239		name := ident.Name
240		var bind *Bind
241		for o := c; o != nil; o = o.Outer {
242			if bind = o.Binds[name]; bind != nil {
243				break
244			}
245		}
246		if bind == nil {
247			c.Errorf("undefined %q in %v <%v>", name, node, r.TypeOf(node))
248		} else if !bind.Const() || bind.Type.ReflectType() != rtypeOfPtrImport {
249			c.Errorf("not a package: %q in %v <%v>", name, node, r.TypeOf(node))
250		}
251		imp, ok := bind.Value.(*Import)
252		if !ok {
253			c.Errorf("not a package: %q in %v <%v>", name, node, r.TypeOf(node))
254		}
255		name = node.Sel.Name
256		t, ok = imp.Types[name]
257		if !ok || t == nil {
258			c.Errorf("not a type: %v <%v>", node, r.TypeOf(node))
259		}
260		if !ast.IsExported(name) {
261			c.Errorf("cannot refer to unexported name %v", node)
262		}
263	case *ast.StructType:
264		// c.Debugf("evalType() struct declaration: %v <%v>", node, r.TypeOf(node))
265		types, names := c.TypeFields(node.Fields)
266		tags := c.fieldsTags(node.Fields)
267		// c.Debugf("evalType() struct names = %v types = %v tags = %v", names, types, tags)
268		pkg := universe.LoadPackage(c.FileComp().Path)
269		fields := c.makeStructFields(pkg, names, types, tags)
270		// c.Debugf("compileType2() declaring struct type. fields=%#v", fields)
271		t = universe.StructOf(fields)
272	case nil:
273		// type can be omitted in many case - then we must perform type inference
274		break
275	default:
276		// which types are still missing?
277		c.Errorf("unimplemented type: %v <%v>", node, r.TypeOf(node))
278	}
279	if t != nil {
280		for i := 0; i < stars; i++ {
281			t = universe.PtrTo(t)
282		}
283		if allowEllipsis && ellipsis {
284			// ellipsis in the last argument of a function declaration
285			t = universe.SliceOf(t)
286		}
287	}
288	return t, ellipsis || ellipsisArray
289}
290
291func (c *Comp) TypeArray(node *ast.ArrayType) (t xr.Type, ellipsis bool) {
292	universe := c.Universe
293	t = c.Type(node.Elt)
294	n := node.Len
295	switch n := n.(type) {
296	case *ast.Ellipsis:
297		t = universe.ArrayOf(0, t)
298		ellipsis = true
299	case nil:
300		t = universe.SliceOf(t)
301	default:
302		// as stated by https://golang.org/ref/spec#Array_types
303		// "The length is part of the array's type; it must evaluate to a non-negative constant
304		// representable by a value of type int. "
305		var count int
306		init := c.expr(n, nil)
307		if !init.Const() {
308			c.Errorf("array length is not a constant: %v", node)
309			return
310		} else if init.Untyped() {
311			count = init.ConstTo(c.TypeOfInt()).(int)
312		} else {
313			count = untyped.ConvertLiteralCheckOverflow(init.Value, c.TypeOfInt()).(int)
314		}
315		if count < 0 {
316			c.Errorf("array length [%v] is negative: %v", count, node)
317		}
318		t = universe.ArrayOf(count, t)
319	}
320	return t, ellipsis
321}
322
323func (c *Comp) TypeFunction(node *ast.FuncType) (t xr.Type, paramNames []string, resultNames []string) {
324	return c.TypeFunctionOrMethod(nil, node)
325}
326
327// TypeFunctionOrMethod compiles a function type corresponding to given receiver and function declaration
328// If receiver is not null, the returned tFunc will have it as receiver.
329func (c *Comp) TypeFunctionOrMethod(recv *ast.Field, node *ast.FuncType) (t xr.Type, paramNames []string, resultNames []string) {
330	paramTypes, paramNames, variadic := c.typeFieldOrParamList(node.Params, true)
331	resultTypes, resultNames := c.TypeFields(node.Results)
332
333	var recvType xr.Type
334	if recv != nil {
335		// methods are functions with receiver. xreflect allows functions to be treated as methods
336		// (using the first parameter as receiver), but go/types.Type loaded by go/importer.Default()
337		// will have methods as functions with receivers.
338		//
339		// So be uniform with those.
340		//
341		// Alas, go/types.Type.String() does *not* print the receiver, making it cumbersome to debug.
342		recvTypes, recvNames, _ := c.typeFieldsOrParams([]*ast.Field{recv}, false)
343		recvType = recvTypes[0]
344
345		// anyway, return the receiver *name* as first element of paramNames
346		paramNames = append(recvNames, paramNames...)
347	}
348	t = c.Universe.MethodOf(recvType, paramTypes, resultTypes, variadic)
349	return t, paramNames, resultNames
350}
351
352func (c *Comp) TypeFields(fields *ast.FieldList) (types []xr.Type, names []string) {
353	types, names, _ = c.typeFieldOrParamList(fields, false)
354	return types, names
355}
356
357func (c *Comp) typeFieldOrParamList(fields *ast.FieldList, allowEllipsis bool) (types []xr.Type, names []string, ellipsis bool) {
358	var list []*ast.Field
359	if fields != nil {
360		list = fields.List
361	}
362	return c.typeFieldsOrParams(list, allowEllipsis)
363}
364
365func (c *Comp) typeFieldsOrParams(list []*ast.Field, allowEllipsis bool) (types []xr.Type, names []string, ellipsis bool) {
366	types = make([]xr.Type, 0)
367	names = ZeroStrings
368	n := len(list)
369	if n == 0 {
370		return types, names, ellipsis
371	}
372	var t xr.Type
373	for i, f := range list {
374		t, ellipsis = c.compileType2(f.Type, i == n-1)
375		if len(f.Names) == 0 {
376			types = append(types, t)
377			names = append(names, "")
378			// c.Debugf("evalTypeFields() %v -> %v", f.Type, t)
379		} else {
380			for _, ident := range f.Names {
381				types = append(types, t)
382				names = append(names, ident.Name)
383				// Debugf("evalTypeFields() %v %v -> %v", ident.Name, f.Type, t)
384			}
385		}
386	}
387	return types, names, ellipsis
388}
389
390func (c *Comp) TryResolveType(name string) xr.Type {
391	var t xr.Type
392	for ; c != nil; c = c.Outer {
393		if t = c.Types[name]; t != nil {
394			break
395		}
396	}
397	return t
398}
399
400func (c *Comp) ResolveType(name string) xr.Type {
401	t := c.TryResolveType(name)
402	if t == nil {
403		c.Errorf("undefined identifier: %v", name)
404	}
405	return t
406}
407
408func (c *Comp) makeStructFields(pkg *xr.Package, names []string, types []xr.Type, tags []string) []xr.StructField {
409	// pkgIdentifier := sanitizeIdentifier(pkgPath)
410	fields := make([]xr.StructField, len(names))
411	for i, name := range names {
412		fields[i] = xr.StructField{
413			Name:      name,
414			Pkg:       pkg,
415			Type:      types[i],
416			Tag:       r.StructTag(tags[i]),
417			Anonymous: len(name) == 0,
418		}
419	}
420	return fields
421}
422
423func (c *Comp) fieldsTags(fields *ast.FieldList) []string {
424	var tags []string
425	if fields != nil {
426		for _, field := range fields.List {
427			var tag string
428			if lit := field.Tag; lit != nil && lit.Kind == token.STRING {
429				tag = strings.MaybeUnescapeString(lit.Value)
430			}
431			if len(field.Names) == 0 {
432				tags = append(tags, tag)
433			} else {
434				for range field.Names {
435					tags = append(tags, tag)
436				}
437			}
438		}
439	}
440	return tags
441}
442
443func rtypeof(v r.Value, t xr.Type) r.Type {
444	if t != nil {
445		return t.ReflectType()
446	}
447	return reflect.Type(v)
448}
449
450// TypeAssert2 compiles a multi-valued type assertion
451func (c *Comp) TypeAssert2(node *ast.TypeAssertExpr) *Expr {
452	val := c.Expr1(node.X, nil)
453	tin := val.Type
454	tout := c.Type(node.Type)
455	rtout := tout.ReflectType()
456	if tin == nil || tin.Kind() != r.Interface {
457		c.Errorf("invalid type assertion: %v (non-interface type <%v> on left)", node, tin)
458		return nil
459	}
460	kout := tout.Kind()
461	if kout != r.Interface && !tout.Implements(tin) {
462		c.Errorf("impossible type assertion: <%v> does not implement <%v>", tout, tin)
463	}
464	// extractor to unwrap value from proxy or emulated interface
465	extractor := c.extractor(tin)
466
467	fun := val.Fun.(func(*Env) r.Value) // val returns an interface... must be already wrapped in a reflect.Value
468
469	var ret func(env *Env) (r.Value, []r.Value)
470
471	fail := []r.Value{xr.Zero(tout), False} // returned by type assertion in case of failure
472	switch {
473	case reflect.IsOptimizedKind(kout):
474		ret = func(env *Env) (r.Value, []r.Value) {
475			v, t := extractor(fun(env))
476			if reflect.Type(v) != rtout || (t != nil && !t.AssignableTo(tout)) {
477				return fail[0], fail
478			}
479			return v, []r.Value{v, True}
480		}
481
482	case kout == r.Interface:
483		if tout.NumMethod() == 0 {
484			// type assertion to empty interface.
485			// everything, excluding nil, implements an empty interface
486			ret = func(env *Env) (r.Value, []r.Value) {
487				v, _ := extractor(fun(env))
488				if v == Nil {
489					return fail[0], fail
490				}
491				v = convert(v, rtout)
492				return v, []r.Value{v, True}
493			}
494			break
495		}
496		if tin.Implements(tout) {
497			// type assertion to interface.
498			// expression type implements such interface, can only fail if value is nil
499			ret = func(env *Env) (r.Value, []r.Value) {
500				v, _ := extractor(fun(env))
501				// nil is not a valid tout, check for it.
502				// IsNil() can be invoked only on nillable types...
503				if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
504					return fail[0], fail
505				}
506				v = convert(v, rtout)
507				return v, []r.Value{v, True}
508			}
509			break
510		}
511		// type assertion to interface
512		// must check at runtime whether concrete type implements asserted interface
513		ret = func(env *Env) (r.Value, []r.Value) {
514			v, t := extractor(fun(env))
515			// nil is not a valid tout, check for it.
516			// IsNil() can be invoked only on nillable types...
517			if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
518				return fail[0], fail
519			}
520			rt := rtypeof(v, t)
521			if (rt != rtout && !rt.Implements(rtout)) ||
522				(t != nil && !t.IdenticalTo(tout) && !t.Implements(tout)) {
523				return fail[0], fail
524			}
525			v = convert(v, rtout)
526			return v, []r.Value{v, True}
527		}
528
529	case reflect.IsNillableKind(kout):
530		// type assertion to concrete (nillable) type
531		ret = func(env *Env) (r.Value, []r.Value) {
532			v, t := extractor(fun(env))
533			// nil is not a valid tout, check for it.
534			// IsNil() can be invoked only on nillable types...
535			if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
536				return fail[0], fail
537			}
538			rt := rtypeof(v, t)
539			if rt != rtout || (t != nil && !t.IdenticalTo(tout)) {
540				return fail[0], fail
541			}
542			return v, []r.Value{v, True}
543		}
544	default:
545		// type assertion to concrete (non-nillable) type
546		ret = func(env *Env) (r.Value, []r.Value) {
547			v, t := extractor(fun(env))
548			rt := rtypeof(v, t)
549			if rt != rtout || (t != nil && !t.IdenticalTo(tout)) {
550				return fail[0], fail
551			}
552			return v, []r.Value{v, True}
553		}
554	}
555	e := exprXV([]xr.Type{tout, c.TypeOfBool()}, ret)
556	e.EFlags = EIsTypeAssert
557	return e
558}
559
560// TypeAssert1 compiles a single-valued type assertion
561func (c *Comp) TypeAssert1(node *ast.TypeAssertExpr) *Expr {
562	if node.Type == nil {
563		c.Errorf("invalid type assertion: expecting actual type, found type switch: %v", node)
564	}
565	val := c.Expr1(node.X, nil)
566	tin := val.Type
567	tout := c.Type(node.Type)
568	kout := tout.Kind()
569	if tin == nil || tin.Kind() != r.Interface {
570		c.Errorf("invalid type assertion: %v (non-interface type <%v> on left)", node, tin)
571		return nil
572	}
573	if tout.Kind() != r.Interface && !tout.Implements(tin) {
574		c.Errorf("impossible type assertion: <%v> does not implement <%v>", tout, tin)
575	}
576	// extractor to unwrap value from proxy or emulated interface
577	extractor := c.extractor(tin)
578
579	fun := val.Fun.(func(*Env) r.Value) // val returns an interface... must be already wrapped in a reflect.Value
580
581	rtout := tout.ReflectType()
582	var ret I
583	switch kout {
584	case r.Bool:
585		ret = func(env *Env) bool {
586			v, t := extractor(fun(env))
587			v = typeassert(v, t, tin, tout)
588			return v.Bool()
589		}
590	case r.Int:
591		ret = func(env *Env) int {
592			v, t := extractor(fun(env))
593			v = typeassert(v, t, tin, tout)
594			return int(v.Int())
595		}
596	case r.Int8:
597		ret = func(env *Env) int8 {
598			v, t := extractor(fun(env))
599			v = typeassert(v, t, tin, tout)
600			return int8(v.Int())
601		}
602	case r.Int16:
603		ret = func(env *Env) int16 {
604			v, t := extractor(fun(env))
605			v = typeassert(v, t, tin, tout)
606			return int16(v.Int())
607		}
608	case r.Int32:
609		ret = func(env *Env) int32 {
610			v, t := extractor(fun(env))
611			v = typeassert(v, t, tin, tout)
612			return int32(v.Int())
613		}
614	case r.Int64:
615		ret = func(env *Env) int64 {
616			v, t := extractor(fun(env))
617			v = typeassert(v, t, tin, tout)
618			return v.Int()
619		}
620	case r.Uint:
621		ret = func(env *Env) uint {
622			v, t := extractor(fun(env))
623			v = typeassert(v, t, tin, tout)
624			return uint(v.Uint())
625		}
626	case r.Uint8:
627		ret = func(env *Env) uint8 {
628			v, t := extractor(fun(env))
629			v = typeassert(v, t, tin, tout)
630			return uint8(v.Uint())
631		}
632	case r.Uint16:
633		ret = func(env *Env) uint16 {
634			v, t := extractor(fun(env))
635			v = typeassert(v, t, tin, tout)
636			return uint16(v.Uint())
637		}
638	case r.Uint32:
639		ret = func(env *Env) uint32 {
640			v, t := extractor(fun(env))
641			v = typeassert(v, t, tin, tout)
642			return uint32(v.Uint())
643		}
644	case r.Uint64:
645		ret = func(env *Env) uint64 {
646			v, t := extractor(fun(env))
647			v = typeassert(v, t, tin, tout)
648			return v.Uint()
649		}
650	case r.Uintptr:
651		ret = func(env *Env) uintptr {
652			v, t := extractor(fun(env))
653			v = typeassert(v, t, tin, tout)
654			return uintptr(v.Uint())
655		}
656	case r.Float32:
657		ret = func(env *Env) float32 {
658			v, t := extractor(fun(env))
659			v = typeassert(v, t, tin, tout)
660			return float32(v.Float())
661		}
662	case r.Float64:
663		ret = func(env *Env) float64 {
664			v, t := extractor(fun(env))
665			v = typeassert(v, t, tin, tout)
666			return v.Float()
667		}
668	case r.Complex64:
669		ret = func(env *Env) complex64 {
670			v, t := extractor(fun(env))
671			v = typeassert(v, t, tin, tout)
672			return complex64(v.Complex())
673		}
674	case r.Complex128:
675		ret = func(env *Env) complex128 {
676			v, t := extractor(fun(env))
677			v = typeassert(v, t, tin, tout)
678			return v.Complex()
679		}
680	case r.String:
681		ret = func(env *Env) string {
682			v, t := extractor(fun(env))
683			v = typeassert(v, t, tin, tout)
684			return v.String()
685		}
686	case r.Interface:
687		if tout.NumMethod() == 0 {
688			// type assertion to empty interface.
689			// everything, excluding untyped nil, implements an empty interface
690			ret = func(env *Env) r.Value {
691				v, _ := extractor(fun(env))
692				if v == Nil {
693					typeassertpanic(nil, nil, tin, tout)
694				}
695				return convert(v, rtout)
696			}
697		} else if tin.Implements(tout) {
698			// type assertion to interface.
699			// expression type implements such interface, can only fail if value is nil
700			ret = func(env *Env) r.Value {
701				v, _ := extractor(fun(env))
702				// nil is not a valid tout, check for it.
703				// IsNil() can be invoked only on nillable types...
704				if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
705					typeassertpanic(nil, nil, tin, tout)
706				}
707				return convert(v, rtout)
708			}
709		} else {
710			// type assertion to interface.
711			// must check at runtime whether concrete type implements asserted interface
712			ret = func(env *Env) r.Value {
713				v, t := extractor(fun(env))
714				// nil is not a valid tout, check for it.
715				// IsNil() can be invoked only on nillable types...
716				if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
717					typeassertpanic(nil, nil, tin, tout)
718				}
719				rt := rtypeof(v, t)
720				if (rt != rtout && !rt.AssignableTo(rtout) && !rt.Implements(rtout)) ||
721					(t != nil && !t.AssignableTo(tout) && !t.Implements(tout)) {
722					typeassertpanic(rt, t, tin, tout)
723				}
724				return convert(v, rtout)
725			}
726		}
727	default:
728		if reflect.IsNillableKind(kout) {
729			// type assertion to concrete (nillable) type
730			ret = func(env *Env) r.Value {
731				v, t := extractor(fun(env))
732				// nil is not a valid tout, check for it.
733				// IsNil() can be invoked only on nillable types...
734				if reflect.IsNillableKind(v.Kind()) && (v == Nil || v.IsNil()) {
735					typeassertpanic(nil, nil, tin, tout)
736				}
737				rt := rtypeof(v, t)
738				if rt != rtout || (t != nil && !t.IdenticalTo(tout)) {
739					panic(&TypeAssertionError{
740						Interface:       tin,
741						Concrete:        t,
742						ReflectConcrete: rt,
743						Asserted:        tout,
744					})
745				}
746				return v
747			}
748		} else {
749			// type assertion to concrete (non-nillable) type
750			ret = func(env *Env) r.Value {
751				v, t := extractor(fun(env))
752				rt := rtypeof(v, t)
753				if rt != rtout || (t != nil && !t.IdenticalTo(tout)) {
754					panic(&TypeAssertionError{
755						Interface:       tin,
756						Concrete:        t,
757						ReflectConcrete: rt,
758						Asserted:        tout,
759					})
760				}
761				return v
762			}
763		}
764	}
765	e := exprFun(tout, ret)
766	e.EFlags = EIsTypeAssert
767	return e
768}
769
770func typeassert(v r.Value, t xr.Type, tin xr.Type, tout xr.Type) r.Value {
771	rt := rtypeof(v, t)
772	if rt != tout.ReflectType() || t != nil && !t.IdenticalTo(tout) {
773		panic(&TypeAssertionError{
774			Interface:       tin,
775			Concrete:        t,
776			ReflectConcrete: rt,
777			Asserted:        tout,
778		})
779	}
780	return v
781}
782
783func typeassertpanic(rt r.Type, t xr.Type, tin xr.Type, tout xr.Type) {
784	var missingmethod *xr.Method
785	if t != nil && tout.Kind() == r.Interface {
786		missingmethod = xr.MissingMethod(t, tout)
787	}
788	panic(&TypeAssertionError{
789		Interface:       tin,
790		Concrete:        t,
791		ReflectConcrete: rt,
792		Asserted:        tout,
793		MissingMethod:   missingmethod,
794	})
795}
796
797func (g *CompGlobals) TypeOfBool() xr.Type {
798	return g.Universe.BasicTypes[r.Bool]
799}
800
801func (g *CompGlobals) TypeOfInt() xr.Type {
802	return g.Universe.BasicTypes[r.Int]
803}
804
805func (g *CompGlobals) TypeOfInt8() xr.Type {
806	return g.Universe.BasicTypes[r.Int8]
807}
808
809func (g *CompGlobals) TypeOfInt16() xr.Type {
810	return g.Universe.BasicTypes[r.Int16]
811}
812
813func (g *CompGlobals) TypeOfInt32() xr.Type {
814	return g.Universe.BasicTypes[r.Int32]
815}
816
817func (g *CompGlobals) TypeOfInt64() xr.Type {
818	return g.Universe.BasicTypes[r.Int64]
819}
820
821func (g *CompGlobals) TypeOfUint() xr.Type {
822	return g.Universe.BasicTypes[r.Uint]
823}
824
825func (g *CompGlobals) TypeOfUint8() xr.Type {
826	return g.Universe.BasicTypes[r.Uint8]
827}
828
829func (g *CompGlobals) TypeOfUint16() xr.Type {
830	return g.Universe.BasicTypes[r.Uint16]
831}
832
833func (g *CompGlobals) TypeOfUint32() xr.Type {
834	return g.Universe.BasicTypes[r.Uint32]
835}
836
837func (g *CompGlobals) TypeOfUint64() xr.Type {
838	return g.Universe.BasicTypes[r.Uint64]
839}
840
841func (g *CompGlobals) TypeOfUintptr() xr.Type {
842	return g.Universe.BasicTypes[r.Uintptr]
843}
844
845func (g *CompGlobals) TypeOfFloat32() xr.Type {
846	return g.Universe.BasicTypes[r.Float32]
847}
848
849func (g *CompGlobals) TypeOfFloat64() xr.Type {
850	return g.Universe.BasicTypes[r.Float64]
851}
852
853func (g *CompGlobals) TypeOfComplex64() xr.Type {
854	return g.Universe.BasicTypes[r.Complex64]
855}
856
857func (g *CompGlobals) TypeOfComplex128() xr.Type {
858	return g.Universe.BasicTypes[r.Complex128]
859}
860
861func (g *CompGlobals) TypeOfString() xr.Type {
862	return g.Universe.BasicTypes[r.String]
863}
864
865func (g *CompGlobals) TypeOfError() xr.Type {
866	return g.Universe.TypeOfError
867}
868
869func (g *CompGlobals) TypeOfInterface() xr.Type {
870	return g.Universe.TypeOfInterface
871}
872
873var (
874	rtypeOfInterface = r.TypeOf((*interface{})(nil)).Elem()
875	rtypeOfForward   = r.TypeOf((*xr.Forward)(nil)).Elem()
876
877	rtypeOfBuiltin         = r.TypeOf(Builtin{})
878	rtypeOfFunction        = r.TypeOf(Function{})
879	rtypeOfMacro           = r.TypeOf(Macro{})
880	rtypeOfPtrImport       = r.TypeOf((*Import)(nil))
881	rtypeOfPtrTemplateFunc = r.TypeOf((*TemplateFunc)(nil))
882	rtypeOfPtrTemplateType = r.TypeOf((*TemplateType)(nil))
883	rtypeOfReflectType     = r.TypeOf((*r.Type)(nil)).Elem()
884	rtypeOfUntypedLit      = r.TypeOf((*UntypedLit)(nil)).Elem()
885
886	zeroOfReflectType = r.Zero(rtypeOfReflectType)
887)
888
889func (g *CompGlobals) TypeOfBuiltin() xr.Type {
890	return g.Universe.ReflectTypes[rtypeOfBuiltin]
891}
892
893func (g *CompGlobals) TypeOfFunction() xr.Type {
894	return g.Universe.ReflectTypes[rtypeOfFunction]
895}
896
897func (g *CompGlobals) TypeOfMacro() xr.Type {
898	return g.Universe.ReflectTypes[rtypeOfMacro]
899}
900
901func (g *CompGlobals) TypeOfPtrImport() xr.Type {
902	return g.Universe.ReflectTypes[rtypeOfPtrImport]
903}
904
905func (g *CompGlobals) TypeOfPtrTemplateFunc() xr.Type {
906	return g.Universe.ReflectTypes[rtypeOfPtrTemplateFunc]
907}
908
909func (g *CompGlobals) TypeOfPtrTemplateType() xr.Type {
910	return g.Universe.ReflectTypes[rtypeOfPtrTemplateType]
911}
912
913func (g *CompGlobals) TypeOfUntypedLit() xr.Type {
914	return g.Universe.ReflectTypes[rtypeOfUntypedLit]
915}
916
917// A TypeAssertionError explains a failed type assertion.
918type TypeAssertionError struct {
919	Interface       xr.Type
920	Concrete        xr.Type
921	ReflectConcrete r.Type // in case Concrete is not available
922	Asserted        xr.Type
923	MissingMethod   *xr.Method // one method needed by Interface, missing from Concrete
924}
925
926func (*TypeAssertionError) RuntimeError() {}
927
928func (e *TypeAssertionError) Error() string {
929	in := e.Interface
930	var concr interface{}
931	if e.Concrete != nil {
932		concr = e.Concrete
933	} else if e.ReflectConcrete != nil {
934		concr = e.ReflectConcrete
935	}
936	if concr == nil {
937		return fmt.Sprintf("interface conversion: <%v> is nil, not <%v>", in, e.Asserted)
938	}
939	if e.MissingMethod == nil {
940		return fmt.Sprintf("interface conversion: <%v> is <%v>, not <%v>", in, concr, e.Asserted)
941	}
942	return fmt.Sprintf("interface conversion: <%v> does not implement <%v>: missing method %s", concr, e.Asserted, e.MissingMethod.String())
943}
944