Typecheck1 is the recursive form of typecheck. It is like typecheck but adds to the information in typeof instead of allocating a new map.
(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, assign map[string][]interface{})
| 226 | // It is like typecheck but adds to the information in typeof |
| 227 | // instead of allocating a new map. |
| 228 | func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, assign map[string][]interface{}) { |
| 229 | // set sets the type of n to typ. |
| 230 | // If isDecl is true, n is being declared. |
| 231 | set := func(n ast.Expr, typ string, isDecl bool) { |
| 232 | if typeof[n] != "" || typ == "" { |
| 233 | if typeof[n] != typ { |
| 234 | assign[typ] = append(assign[typ], n) |
| 235 | } |
| 236 | return |
| 237 | } |
| 238 | typeof[n] = typ |
| 239 | |
| 240 | // If we obtained typ from the declaration of x |
| 241 | // propagate the type to all the uses. |
| 242 | // The !isDecl case is a cheat here, but it makes |
| 243 | // up in some cases for not paying attention to |
| 244 | // struct fields. The real type checker will be |
| 245 | // more accurate so we won't need the cheat. |
| 246 | if id, ok := n.(*ast.Ident); ok && id.Obj != nil && (isDecl || typeof[id.Obj] == "") { |
| 247 | typeof[id.Obj] = typ |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | // Type-check an assignment lhs = rhs. |
| 252 | // If isDecl is true, this is := so we can update |
| 253 | // the types of the objects that lhs refers to. |
| 254 | typecheckAssign := func(lhs, rhs []ast.Expr, isDecl bool) { |
| 255 | if len(lhs) > 1 && len(rhs) == 1 { |
| 256 | if _, ok := rhs[0].(*ast.CallExpr); ok { |
| 257 | t := split(typeof[rhs[0]]) |
| 258 | // Lists should have same length but may not; pair what can be paired. |
| 259 | for i := 0; i < len(lhs) && i < len(t); i++ { |
| 260 | set(lhs[i], t[i], isDecl) |
| 261 | } |
| 262 | return |
| 263 | } |
| 264 | } |
| 265 | if len(lhs) == 1 && len(rhs) == 2 { |
| 266 | // x = y, ok |
| 267 | rhs = rhs[:1] |
| 268 | } else if len(lhs) == 2 && len(rhs) == 1 { |
| 269 | // x, ok = y |
| 270 | lhs = lhs[:1] |
| 271 | } |
| 272 | |
| 273 | // Match as much as we can. |
| 274 | for i := 0; i < len(lhs) && i < len(rhs); i++ { |
| 275 | x, y := lhs[i], rhs[i] |
| 276 | if typeof[y] != "" { |
| 277 | set(x, typeof[y], isDecl) |
| 278 | } else { |
| 279 | set(y, typeof[x], false) |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | expand := func(s string) string { |
| 285 | typ := cfg.Type[s] |
no test coverage detected