addChildren(value, slice);
}
@Override
public NType resolve(Scope s) throws Exception {
NType vt = resolveExpr(value, s);
NType st = resolveExpr(slice, s);
// slicing
if (vt.isUnknownType()) {
if (st.isListType()) {
return setType(vt);
}
return setType(new NUnknownType());
}
if (st.isListType()) {
NType getslice_type = vt.getTable().lookupTypeAttr("__getslice__");
if (getslice_type == null) {
addError("The type can't be sliced: " + vt);
return setType(new NUnknownType());
}
if (!getslice_type.isFuncType()) {
addError("The type's __getslice__ method is not a function: "
+ getslice_type);
return setType(new NUnknownType());
}
return setType(getslice_type.asFuncType().getReturnType().follow());
}
// subscription
if (slice instanceof NIndex) {
if (vt.isListType()) {
warnUnlessNumIndex(st);
return setType(vt.asListType().getElementType());
}
if (vt.isTupleType()) {
warnUnlessNumIndex(st);
return setType(vt.asTupleType().toListType().getElementType());
}
if (vt.isStrType()) {
warnUnlessNumIndex(st);
return setType(Indexer.idx.builtins.BaseStr);
}
// XXX: unicode, buffer, xrange
if (vt.isDictType()) {
if (!st.follow().equals(vt.asDictType().getKeyType())) {
addWarning("Possible KeyError (wrong type for subscript)");
}
return setType(vt.asDictType().getValueType()); // infer it regardless
}
// else fall through
}
// subscription via delegation
if (vt.isUnionType()) {
for (NType u : vt.asUnionType().getTypes()) {
NType gt = vt.getTable().lookupTypeAttr("__getitem__");
if (gt != null) {
return setType(get__getitem__type(gt, gt));
}
}
}
NType gt = vt.getTable().lookupTypeAttr("__getitem__");
return setType(get__getitem__type(gt, vt));
}