package types
import (
"go/ast"
"go/constant"
)
func (check *Checker ) record (x *operand ) {
var typ Type
var val constant .Value
switch x .mode () {
case invalid :
typ = Typ [Invalid ]
case novalue :
typ = (*Tuple )(nil )
case constant_ :
typ = x .typ ()
val = x .val
default :
typ = x .typ ()
}
assert (x .expr != nil && typ != nil )
if isUntyped (typ ) {
check .rememberUntyped (x .expr , false , x .mode (), typ .(*Basic ), val )
} else {
check .recordTypeAndValue (x .expr , x .mode (), typ , val )
}
}
func (check *Checker ) recordUntyped () {
if !debug && !check .recordTypes () {
return
}
for x , info := range check .untyped {
if debug && isTyped (info .typ ) {
check .dump ("%v: %s (type %s) is typed" , x .Pos (), x , info .typ )
panic ("unreachable" )
}
check .recordTypeAndValue (x , info .mode , info .typ , info .val )
}
}
func (check *Checker ) recordTypeAndValue (x ast .Expr , mode operandMode , typ Type , val constant .Value ) {
assert (x != nil )
assert (typ != nil )
if mode == invalid {
return
}
if mode == constant_ {
assert (val != nil )
assert (!isValid (typ ) || allBasic (typ , IsConstType ))
}
if m := check .Types ; m != nil {
m [x ] = TypeAndValue {mode , typ , val }
}
check .recordTypeAndValueInSyntax (x , mode , typ , val )
}
func (check *Checker ) recordBuiltinType (f ast .Expr , sig *Signature ) {
for {
check .recordTypeAndValue (f , builtin , sig , nil )
switch p := f .(type ) {
case *ast .Ident , *ast .SelectorExpr :
return
case *ast .ParenExpr :
f = p .X
default :
panic ("unreachable" )
}
}
}
func (check *Checker ) recordCommaOkTypes (x ast .Expr , a []*operand ) {
assert (x != nil )
assert (len (a ) == 2 )
if a [0 ].mode () == invalid {
return
}
t0 , t1 := a [0 ].typ (), a [1 ].typ ()
assert (isTyped (t0 ) && isTyped (t1 ) && (allBoolean (t1 ) || t1 == universeError ))
if m := check .Types ; m != nil {
for {
tv := m [x ]
assert (tv .Type != nil )
pos := x .Pos ()
tv .Type = NewTuple (
newVar (LocalVar , pos , check .pkg , "" , t0 ),
newVar (LocalVar , pos , check .pkg , "" , t1 ),
)
m [x ] = tv
p , _ := x .(*ast .ParenExpr )
if p == nil {
break
}
x = p .X
}
}
check .recordCommaOkTypesInSyntax (x , t0 , t1 )
}
func (check *Checker ) recordInstance (expr ast .Expr , targs []Type , typ Type ) {
ident := instantiatedIdent (expr )
assert (ident != nil )
assert (typ != nil )
if m := check .Instances ; m != nil {
if sig , _ := typ .(*Signature ); sig != nil && sig .recvold != nil {
copy := *sig
copy .recvold = nil
if sig .recvold == methodExprSentinel {
pars := *copy .params
copy .recv = pars .vars [0 ]
pars .vars = pars .vars [1 :]
copy .params = &pars
m [ident ] = Instance {newTypeList (targs ), © }
return
}
copy .recv = sig .recvold
m [ident ] = Instance {newTypeList (targs ), © }
return
}
m [ident ] = Instance {newTypeList (targs ), typ }
}
}
func (check *Checker ) recordDef (id *ast .Ident , obj Object ) {
assert (id != nil )
if m := check .Defs ; m != nil {
m [id ] = obj
}
}
func (check *Checker ) recordUse (id *ast .Ident , obj Object ) {
assert (id != nil )
assert (obj != nil )
if m := check .Uses ; m != nil {
m [id ] = obj
}
}
func (check *Checker ) recordImplicit (node ast .Node , obj Object ) {
assert (node != nil )
assert (obj != nil )
if m := check .Implicits ; m != nil {
m [node ] = obj
}
}
func (check *Checker ) recordSelection (x *ast .SelectorExpr , kind SelectionKind , recv Type , obj Object , index []int , indirect bool ) {
assert (obj != nil && (recv == nil || len (index ) > 0 ))
check .recordUse (x .Sel , obj )
if m := check .Selections ; m != nil {
m [x ] = &Selection {kind , recv , obj , index , indirect }
}
}
func (check *Checker ) recordScope (node ast .Node , scope *Scope ) {
assert (node != nil )
assert (scope != nil )
if m := check .Scopes ; m != nil {
m [node ] = scope
}
}
The pages are generated with Golds v0.8.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .