src.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 Show documentation
Show all versions of jython 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);
}
}
}