src.org.python.compiler.ScopesCompiler 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.
// (C) Copyright 2001 Samuele Pedroni
package org.python.compiler;
import org.python.antlr.Visitor;
import org.python.antlr.PythonTree;
import org.python.antlr.ast.ClassDef;
import org.python.antlr.ast.Exec;
import org.python.antlr.ast.Expression;
import org.python.antlr.ast.FunctionDef;
import org.python.antlr.ast.GeneratorExp;
import org.python.antlr.ast.Global;
import org.python.antlr.ast.Import;
import org.python.antlr.ast.ImportFrom;
import org.python.antlr.ast.Interactive;
import org.python.antlr.ast.Lambda;
import org.python.antlr.ast.ListComp;
import org.python.antlr.ast.Name;
import org.python.antlr.ast.Return;
import org.python.antlr.ast.With;
import org.python.antlr.ast.Yield;
import org.python.antlr.ast.arguments;
import org.python.antlr.ast.expr_contextType;
import org.python.antlr.base.expr;
import org.python.antlr.base.stmt;
import org.python.core.ParserFacade;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Stack;
import java.util.List;
public class ScopesCompiler extends Visitor implements ScopeConstants {
private CompilationContext code_compiler;
private Stack scopes;
private ScopeInfo cur = null;
private Hashtable nodeScopes;
private int level = 0;
private int func_level = 0;
public ScopesCompiler(CompilationContext code_compiler, Hashtable nodeScopes) {
this.code_compiler = code_compiler;
this.nodeScopes = nodeScopes;
scopes = new Stack();
}
public void beginScope(String name, int kind, PythonTree node,
ArgListCompiler ac) {
if (cur != null) {
scopes.push(cur);
}
if (kind == FUNCSCOPE) {
func_level++;
}
cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
nodeScopes.put(node, cur);
}
public void endScope() throws Exception {
if (cur.kind == FUNCSCOPE) {
func_level--;
}
level--;
ScopeInfo up = null;
if (!scopes.empty()) {
up = scopes.pop();
}
//Go into the stack to find a non class containing scope to use making the closure
//See PEP 227
int dist = 1;
ScopeInfo referenceable = up;
for (int i = scopes.size() - 1; i >= 0
&& referenceable.kind == CLASSSCOPE; i--, dist++) {
referenceable = (scopes.get(i));
}
cur.cook(referenceable, dist, code_compiler);
cur.dump(); // debug
cur = up;
}
public void parse(PythonTree node) throws Exception {
try {
visit(node);
} catch (Throwable t) {
throw ParserFacade.fixParseError(null, t, code_compiler.getFilename());
}
}
@Override
public Object visitInteractive(Interactive node) throws Exception {
beginScope("", TOPSCOPE, node, null);
suite(node.getInternalBody());
endScope();
return null;
}
@Override
public Object visitModule(org.python.antlr.ast.Module node)
throws Exception {
beginScope("", TOPSCOPE, node, null);
suite(node.getInternalBody());
endScope();
return null;
}
@Override
public Object visitExpression(Expression node) throws Exception {
beginScope("", TOPSCOPE, node, null);
visit(new Return(node,node.getInternalBody()));
endScope();
return null;
}
private void def(String name) {
cur.addBound(name);
}
@Override
public Object visitFunctionDef(FunctionDef node) throws Exception {
def(node.getInternalName());
ArgListCompiler ac = new ArgListCompiler();
ac.visitArgs(node.getInternalArgs());
List defaults = ac.getDefaults();
for (int i = 0; i < defaults.size(); i++) {
visit(defaults.get(i));
}
List decs = node.getInternalDecorator_list();
for (int i = decs.size() - 1; i >= 0; i--) {
visit(decs.get(i));
}
beginScope(node.getInternalName(), FUNCSCOPE, node, ac);
int n = ac.names.size();
for (int i = 0; i < n; i++) {
cur.addParam(ac.names.get(i));
}
for (int i = 0; i < ac.init_code.size(); i++) {
visit(ac.init_code.get(i));
}
cur.markFromParam();
suite(node.getInternalBody());
endScope();
return null;
}
@Override
public Object visitLambda(Lambda node) throws Exception {
ArgListCompiler ac = new ArgListCompiler();
ac.visitArgs(node.getInternalArgs());
List extends PythonTree> defaults = ac.getDefaults();
for (int i = 0; i < defaults.size(); i++) {
visit(defaults.get(i));
}
beginScope("", FUNCSCOPE, node, ac);
for (Object o : ac.names) {
cur.addParam((String) o);
}
for (Object o : ac.init_code) {
visit((stmt) o);
}
cur.markFromParam();
visit(node.getInternalBody());
endScope();
return null;
}
public void suite(List stmts) throws Exception {
for (int i = 0; i < stmts.size(); i++)
visit(stmts.get(i));
}
@Override
public Object visitImport(Import node) throws Exception {
for (int i = 0; i < node.getInternalNames().size(); i++) {
if (node.getInternalNames().get(i).getInternalAsname() != null) {
cur.addBound(node.getInternalNames().get(i).getInternalAsname());
} else {
String name = node.getInternalNames().get(i).getInternalName();
if (name.indexOf('.') > 0) {
name = name.substring(0, name.indexOf('.'));
}
cur.addBound(name);
}
}
return null;
}
@Override
public Object visitImportFrom(ImportFrom node) throws Exception {
Future.checkFromFuture(node); // future stmt support
int n = node.getInternalNames().size();
if (n == 0) {
cur.from_import_star = true;
return null;
}
for (int i = 0; i < n; i++) {
if (node.getInternalNames().get(i).getInternalAsname() != null) {
cur.addBound(node.getInternalNames().get(i).getInternalAsname());
} else {
cur.addBound(node.getInternalNames().get(i).getInternalName());
}
}
return null;
}
@Override
public Object visitGlobal(Global node) throws Exception {
int n = node.getInternalNames().size();
for (int i = 0; i < n; i++) {
String name = node.getInternalNames().get(i);
int prev = cur.addGlobal(name);
if (prev >= 0) {
if ((prev & FROM_PARAM) != 0) {
code_compiler.error("name '" + name
+ "' is local and global", true, node);
}
if ((prev & GLOBAL) != 0) {
continue;
}
String what;
if ((prev & BOUND) != 0) {
what = "assignment";
} else {
what = "use";
}
code_compiler.error("name '" + name
+ "' declared global after " + what, false, node);
}
}
return null;
}
@Override
public Object visitExec(Exec node) throws Exception {
cur.exec = true;
if (node.getInternalGlobals() == null && node.getInternalLocals() == null) {
cur.unqual_exec = true;
}
traverse(node);
return null;
}
@Override
public Object visitClassDef(ClassDef node) throws Exception {
def(node.getInternalName());
int n = node.getInternalBases().size();
for (int i = 0; i < n; i++) {
visit(node.getInternalBases().get(i));
}
beginScope(node.getInternalName(), CLASSSCOPE, node, null);
suite(node.getInternalBody());
endScope();
return null;
}
@Override
public Object visitName(Name node) throws Exception {
String name = node.getInternalId();
if (node.getInternalCtx() != expr_contextType.Load) {
if (name.equals("__debug__")) {
code_compiler.error("can not assign to __debug__", true, node);
}
cur.addBound(name);
} else {
cur.addUsed(name);
}
return null;
}
@Override
public Object visitListComp(ListComp node) throws Exception {
String tmp = "_[" + node.getLine() + "_" + node.getCharPositionInLine()
+ "]";
cur.addBound(tmp);
traverse(node);
return null;
}
@Override
public Object visitYield(Yield node) throws Exception {
cur.defineAsGenerator(node);
cur.yield_count++;
traverse(node);
return null;
}
@Override
public Object visitReturn(Return node) throws Exception {
if (node.getInternalValue() != null) {
cur.noteReturnValue(node);
}
traverse(node);
return null;
}
@Override
public Object visitGeneratorExp(GeneratorExp node) throws Exception {
// The first iterator is evaluated in the outer scope
if (node.getInternalGenerators() != null && node.getInternalGenerators().size() > 0) {
visit(node.getInternalGenerators().get(0).getInternalIter());
}
String bound_exp = "_(x)";
String tmp = "_(" + node.getLine() + "_" + node.getCharPositionInLine()
+ ")";
def(tmp);
ArgListCompiler ac = new ArgListCompiler();
List args = new ArrayList();
args.add(new Name(node.getToken(), bound_exp, expr_contextType.Param));
ac.visitArgs(new arguments(node, args, null, null, new ArrayList()));
beginScope(tmp, FUNCSCOPE, node, ac);
cur.addParam(bound_exp);
cur.markFromParam();
cur.defineAsGenerator(node);
cur.yield_count++;
// The reset of the iterators are evaluated in the inner scope
if (node.getInternalElt() != null) {
visit(node.getInternalElt());
}
if (node.getInternalGenerators() != null) {
for (int i = 0; i < node.getInternalGenerators().size(); i++) {
if (node.getInternalGenerators().get(i) != null) {
if (i == 0) {
visit(node.getInternalGenerators().get(i).getInternalTarget());
if (node.getInternalGenerators().get(i).getInternalIfs() != null) {
for (expr cond : node.getInternalGenerators().get(i).getInternalIfs()) {
if (cond != null) {
visit(cond);
}
}
}
} else {
visit(node.getInternalGenerators().get(i));
}
}
}
}
endScope();
return null;
}
@Override
public Object visitWith(With node) throws Exception {
cur.max_with_count++;
traverse(node);
return null;
}
}