github.com/bir3/gocompiler@v0.9.2202/src/go/types/operand.go (about) 1 // Copyright 2012 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 5 // This file defines operands and associated operations. 6 7 package types 8 9 import ( 10 "bytes" 11 "github.com/bir3/gocompiler/src/go/ast" 12 "github.com/bir3/gocompiler/src/go/constant" 13 "github.com/bir3/gocompiler/src/go/token" 14 . "github.com/bir3/gocompiler/src/internal/types/errors" 15 ) 16 17 // An operandMode specifies the (addressing) mode of an operand. 18 type operandMode byte 19 20 const ( 21 invalid operandMode = iota // operand is invalid 22 novalue // operand represents no value (result of a function call w/o result) 23 builtin // operand is a built-in function 24 typexpr // operand is a type 25 constant_ // operand is a constant; the operand's typ is a Basic type 26 variable // operand is an addressable variable 27 mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment) 28 value // operand is a computed value 29 commaok // like value, but operand may be used in a comma,ok expression 30 commaerr // like commaok, but second value is error, not boolean 31 cgofunc // operand is a cgo function 32 ) 33 34 var operandModeString = [...]string{ 35 invalid: "invalid operand", 36 novalue: "no value", 37 builtin: "built-in", 38 typexpr: "type", 39 constant_: "constant", 40 variable: "variable", 41 mapindex: "map index expression", 42 value: "value", 43 commaok: "comma, ok expression", 44 commaerr: "comma, error expression", 45 cgofunc: "cgo function", 46 } 47 48 // An operand represents an intermediate value during type checking. 49 // Operands have an (addressing) mode, the expression evaluating to 50 // the operand, the operand's type, a value for constants, and an id 51 // for built-in functions. 52 // The zero value of operand is a ready to use invalid operand. 53 type operand struct { 54 mode operandMode 55 expr ast.Expr 56 typ Type 57 val constant.Value 58 id builtinId 59 } 60 61 // Pos returns the position of the expression corresponding to x. 62 // If x is invalid the position is nopos. 63 func (x *operand) Pos() token.Pos { 64 // x.expr may not be set if x is invalid 65 if x.expr == nil { 66 return nopos 67 } 68 return x.expr.Pos() 69 } 70 71 // Operand string formats 72 // (not all "untyped" cases can appear due to the type system, 73 // but they fall out naturally here) 74 // 75 // mode format 76 // 77 // invalid <expr> ( <mode> ) 78 // novalue <expr> ( <mode> ) 79 // builtin <expr> ( <mode> ) 80 // typexpr <expr> ( <mode> ) 81 // 82 // constant <expr> (<untyped kind> <mode> ) 83 // constant <expr> ( <mode> of type <typ>) 84 // constant <expr> (<untyped kind> <mode> <val> ) 85 // constant <expr> ( <mode> <val> of type <typ>) 86 // 87 // variable <expr> (<untyped kind> <mode> ) 88 // variable <expr> ( <mode> of type <typ>) 89 // 90 // mapindex <expr> (<untyped kind> <mode> ) 91 // mapindex <expr> ( <mode> of type <typ>) 92 // 93 // value <expr> (<untyped kind> <mode> ) 94 // value <expr> ( <mode> of type <typ>) 95 // 96 // commaok <expr> (<untyped kind> <mode> ) 97 // commaok <expr> ( <mode> of type <typ>) 98 // 99 // commaerr <expr> (<untyped kind> <mode> ) 100 // commaerr <expr> ( <mode> of type <typ>) 101 // 102 // cgofunc <expr> (<untyped kind> <mode> ) 103 // cgofunc <expr> ( <mode> of type <typ>) 104 func operandString(x *operand, qf Qualifier) string { 105 // special-case nil 106 if x.mode == value && x.typ == Typ[UntypedNil] { 107 return "nil" 108 } 109 110 var buf bytes.Buffer 111 112 var expr string 113 if x.expr != nil { 114 expr = ExprString(x.expr) 115 } else { 116 switch x.mode { 117 case builtin: 118 expr = predeclaredFuncs[x.id].name 119 case typexpr: 120 expr = TypeString(x.typ, qf) 121 case constant_: 122 expr = x.val.String() 123 } 124 } 125 126 // <expr> ( 127 if expr != "" { 128 buf.WriteString(expr) 129 buf.WriteString(" (") 130 } 131 132 // <untyped kind> 133 hasType := false 134 switch x.mode { 135 case invalid, novalue, builtin, typexpr: 136 // no type 137 default: 138 // should have a type, but be cautious (don't crash during printing) 139 if x.typ != nil { 140 if isUntyped(x.typ) { 141 buf.WriteString(x.typ.(*Basic).name) 142 buf.WriteByte(' ') 143 break 144 } 145 hasType = true 146 } 147 } 148 149 // <mode> 150 buf.WriteString(operandModeString[x.mode]) 151 152 // <val> 153 if x.mode == constant_ { 154 if s := x.val.String(); s != expr { 155 buf.WriteByte(' ') 156 buf.WriteString(s) 157 } 158 } 159 160 // <typ> 161 if hasType { 162 if isValid(x.typ) { 163 var intro string 164 if isGeneric(x.typ) { 165 intro = " of generic type " 166 } else { 167 intro = " of type " 168 } 169 buf.WriteString(intro) 170 WriteType(&buf, x.typ, qf) 171 if tpar, _ := x.typ.(*TypeParam); tpar != nil { 172 buf.WriteString(" constrained by ") 173 WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here 174 // If we have the type set and it's empty, say so for better error messages. 175 if hasEmptyTypeset(tpar) { 176 buf.WriteString(" with empty type set") 177 } 178 } 179 } else { 180 buf.WriteString(" with invalid type") 181 } 182 } 183 184 // ) 185 if expr != "" { 186 buf.WriteByte(')') 187 } 188 189 return buf.String() 190 } 191 192 func (x *operand) String() string { 193 return operandString(x, nil) 194 } 195 196 // setConst sets x to the untyped constant for literal lit. 197 func (x *operand) setConst(tok token.Token, lit string) { 198 var kind BasicKind 199 switch tok { 200 case token.INT: 201 kind = UntypedInt 202 case token.FLOAT: 203 kind = UntypedFloat 204 case token.IMAG: 205 kind = UntypedComplex 206 case token.CHAR: 207 kind = UntypedRune 208 case token.STRING: 209 kind = UntypedString 210 default: 211 unreachable() 212 } 213 214 val := constant.MakeFromLiteral(lit, tok, 0) 215 if val.Kind() == constant.Unknown { 216 x.mode = invalid 217 x.typ = Typ[Invalid] 218 return 219 } 220 x.mode = constant_ 221 x.typ = Typ[kind] 222 x.val = val 223 } 224 225 // isNil reports whether x is the (untyped) nil value. 226 func (x *operand) isNil() bool { return x.mode == value && x.typ == Typ[UntypedNil] } 227 228 // assignableTo reports whether x is assignable to a variable of type T. If the 229 // result is false and a non-nil cause is provided, it may be set to a more 230 // detailed explanation of the failure (result != ""). The returned error code 231 // is only valid if the (first) result is false. The check parameter may be nil 232 // if assignableTo is invoked through an exported API call, i.e., when all 233 // methods have been type-checked. 234 func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Code) { 235 if x.mode == invalid || !isValid(T) { 236 return true, 0 // avoid spurious errors 237 } 238 239 V := x.typ 240 241 // x's type is identical to T 242 if Identical(V, T) { 243 return true, 0 244 } 245 246 Vu := under(V) 247 Tu := under(T) 248 Vp, _ := V.(*TypeParam) 249 Tp, _ := T.(*TypeParam) 250 251 // x is an untyped value representable by a value of type T. 252 if isUntyped(Vu) { 253 assert(Vp == nil) 254 if Tp != nil { 255 // T is a type parameter: x is assignable to T if it is 256 // representable by each specific type in the type set of T. 257 return Tp.is(func(t *term) bool { 258 if t == nil { 259 return false 260 } 261 // A term may be a tilde term but the underlying 262 // type of an untyped value doesn't change so we 263 // don't need to do anything special. 264 newType, _, _ := check.implicitTypeAndValue(x, t.typ) 265 return newType != nil 266 }), IncompatibleAssign 267 } 268 newType, _, _ := check.implicitTypeAndValue(x, T) 269 return newType != nil, IncompatibleAssign 270 } 271 // Vu is typed 272 273 // x's type V and T have identical underlying types 274 // and at least one of V or T is not a named type 275 // and neither V nor T is a type parameter. 276 if Identical(Vu, Tu) && (!hasName(V) || !hasName(T)) && Vp == nil && Tp == nil { 277 return true, 0 278 } 279 280 // T is an interface type, but not a type parameter, and V implements T. 281 // Also handle the case where T is a pointer to an interface so that we get 282 // the Checker.implements error cause. 283 if _, ok := Tu.(*Interface); ok && Tp == nil || isInterfacePtr(Tu) { 284 if check.implements(x.Pos(), V, T, false, cause) { 285 return true, 0 286 } 287 // V doesn't implement T but V may still be assignable to T if V 288 // is a type parameter; do not report an error in that case yet. 289 if Vp == nil { 290 return false, InvalidIfaceAssign 291 } 292 if cause != nil { 293 *cause = "" 294 } 295 } 296 297 // If V is an interface, check if a missing type assertion is the problem. 298 if Vi, _ := Vu.(*Interface); Vi != nil && Vp == nil { 299 if check.implements(x.Pos(), T, V, false, nil) { 300 // T implements V, so give hint about type assertion. 301 if cause != nil { 302 *cause = "need type assertion" 303 } 304 return false, IncompatibleAssign 305 } 306 } 307 308 // x is a bidirectional channel value, T is a channel 309 // type, x's type V and T have identical element types, 310 // and at least one of V or T is not a named type. 311 if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv { 312 if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) { 313 return !hasName(V) || !hasName(T), InvalidChanAssign 314 } 315 } 316 317 // optimization: if we don't have type parameters, we're done 318 if Vp == nil && Tp == nil { 319 return false, IncompatibleAssign 320 } 321 322 errorf := func(format string, args ...any) { 323 if check != nil && cause != nil { 324 msg := check.sprintf(format, args...) 325 if *cause != "" { 326 msg += "\n\t" + *cause 327 } 328 *cause = msg 329 } 330 } 331 332 // x's type V is not a named type and T is a type parameter, and 333 // x is assignable to each specific type in T's type set. 334 if !hasName(V) && Tp != nil { 335 ok := false 336 code := IncompatibleAssign 337 Tp.is(func(T *term) bool { 338 if T == nil { 339 return false // no specific types 340 } 341 ok, code = x.assignableTo(check, T.typ, cause) 342 if !ok { 343 errorf("cannot assign %s to %s (in %s)", x.typ, T.typ, Tp) 344 return false 345 } 346 return true 347 }) 348 return ok, code 349 } 350 351 // x's type V is a type parameter and T is not a named type, 352 // and values x' of each specific type in V's type set are 353 // assignable to T. 354 if Vp != nil && !hasName(T) { 355 x := *x // don't clobber outer x 356 ok := false 357 code := IncompatibleAssign 358 Vp.is(func(V *term) bool { 359 if V == nil { 360 return false // no specific types 361 } 362 x.typ = V.typ 363 ok, code = x.assignableTo(check, T, cause) 364 if !ok { 365 errorf("cannot assign %s (in %s) to %s", V.typ, Vp, T) 366 return false 367 } 368 return true 369 }) 370 return ok, code 371 } 372 373 return false, IncompatibleAssign 374 }