Process a binding use of a name by adding a binding to the current block if not already bound, and associate the identifier with it. @param hasType true if this binding use has a type annotation associated with it and is not a function parameter; an error is reported when hasType is true but th
(
Identifier id, boolean isLoad, boolean hasType, @Nullable DocComments docComments)
| 1214 | * @return true if the name was newly bound in this block, or false if it already existed |
| 1215 | */ |
| 1216 | private boolean bind( |
| 1217 | Identifier id, boolean isLoad, boolean hasType, @Nullable DocComments docComments) { |
| 1218 | String name = id.getName(); |
| 1219 | boolean isNew = false; |
| 1220 | Binding bind; |
| 1221 | |
| 1222 | // TODO(adonovan): factor out bindLocal/bindGlobal cases |
| 1223 | // and simply the condition below. |
| 1224 | |
| 1225 | // outside any function/comprehension, and not a (local) load? => global binding. |
| 1226 | if (locals.syntax instanceof StarlarkFile && !(isLoad && !options.loadBindsGlobally())) { |
| 1227 | bind = toplevel.get(name); |
| 1228 | if (bind == null) { |
| 1229 | // New global binding: add to module and to toplevel cache. |
| 1230 | isNew = true; |
| 1231 | bind = new Binding(Scope.GLOBAL, globals.size(), /* isSyntactic= */ true, id); |
| 1232 | globals.add(name); |
| 1233 | if (docComments != null && docCommentsMap != null) { |
| 1234 | docCommentsMap.put(name, docComments); |
| 1235 | } |
| 1236 | toplevel.put(name, bind); |
| 1237 | |
| 1238 | // Does this new global binding conflict with a file-local load binding? |
| 1239 | Binding prevLocal = locals.bindings.get(name); |
| 1240 | if (prevLocal != null) { |
| 1241 | globalLocalConflict(id, bind.scope, prevLocal); // global, local |
| 1242 | } |
| 1243 | |
| 1244 | } else { |
| 1245 | toplevelRebinding(id, bind); // global, global |
| 1246 | } |
| 1247 | |
| 1248 | } else { |
| 1249 | // Binding is local to file, function, or comprehension. |
| 1250 | bind = locals.bindings.get(name); |
| 1251 | if (bind == null) { |
| 1252 | // New local binding: add to current block's bindings map, current function's frame. |
| 1253 | // (These are distinct entities in the case where the current block is a comprehension.) |
| 1254 | isNew = true; |
| 1255 | if (locals.syntax instanceof Comprehension comprehension) { |
| 1256 | // Assumption: any block nested in a comprehension is either another comprehension or has |
| 1257 | // its own frame (e.g. a lambda). |
| 1258 | bind = new ComprehensionBinding(locals.frame.size(), id, comprehension); |
| 1259 | } else { |
| 1260 | bind = new Binding(Scope.LOCAL, locals.frame.size(), /* isSyntactic= */ true, id); |
| 1261 | } |
| 1262 | locals.bindings.put(name, bind); |
| 1263 | locals.frame.add(bind); |
| 1264 | } |
| 1265 | |
| 1266 | if (isLoad) { |
| 1267 | // Does this (file-local) load binding conflict with a previous one? |
| 1268 | if (!isNew) { |
| 1269 | toplevelRebinding(id, bind); // local, local |
| 1270 | } |
| 1271 | |
| 1272 | // ...or a previous global? |
| 1273 | Binding prev = toplevel.get(name); |