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