org.python.indexer.ast.NSubscript Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-slim Show documentation
Show all versions of jython-slim Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
/**
* Copyright 2009, Google Inc. All rights reserved.
* Licensed to PSF under a Contributor Agreement.
*/
package org.python.indexer.ast;
import org.python.indexer.Indexer;
import org.python.indexer.Scope;
import org.python.indexer.types.NFuncType;
import org.python.indexer.types.NListType;
import org.python.indexer.types.NType;
import org.python.indexer.types.NUnknownType;
public class NSubscript extends NNode {
static final long serialVersionUID = -493854491438387425L;
public NNode value;
public NNode slice; // an NIndex or NSlice
public NSubscript(NNode value, NNode slice) {
this(value, slice, 0, 1);
}
public NSubscript(NNode value, NNode slice, int start, int end) {
super(start, end);
this.value = value;
this.slice = slice;
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));
}
private void warnUnlessNumIndex(NType subscriptType) {
NType follow = subscriptType.follow();
if (!follow.isNumType() && !follow.isUnknownType()) {
addWarning("Possible KeyError: subscript should be a number; found " + follow);
}
}
private NType get__getitem__type(NType gt, NType vt) {
if (gt == null) {
addError("indexing type without __getitem__ method: " + vt);
return new NUnknownType();
}
if (!gt.isFuncType()) {
addError("The type's __getitem__ method is not a function: " + gt);
return new NUnknownType();
}
return gt.asFuncType().getReturnType().follow();
}
@Override
public String toString() {
return "";
}
@Override
public void visit(NNodeVisitor v) {
if (v.visit(this)) {
visitNode(value, v);
visitNode(slice, v);
}
}
}