org.python.compiler.ScopeInfo Maven / Gradle / Ivy
Go to download
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 java.util.*;
import org.python.parser.SimpleNode;
public class ScopeInfo extends Object implements ScopeConstants {
public SimpleNode scope_node;
public String scope_name;
public int level;
public int func_level;
public int list_comprehension_count;
public void dump() { // for debugging
if (org.python.core.Options.verbose < org.python.core.Py.DEBUG)
return;
for(int i=0; i nop
this.up = up;
this.distance = distance;
boolean func = kind == FUNCSCOPE;
Vector purecells = new Vector();
cell = 0;
boolean some_inner_free = inner_free.size() > 0;
for (Enumeration e = inner_free.keys(); e.hasMoreElements(); ) {
String name = (String)e.nextElement();
SymInfo info = (SymInfo)tbl.get(name);
if (info == null) {
tbl.put(name,new SymInfo(FREE));
continue;
}
int flags = info.flags;
if (func) {
// not func global and bound ?
if ((flags&NGLOBAL) == 0 && (flags&BOUND) != 0) {
info.flags |= CELL;
if ((info.flags&PARAM) != 0)
jy_paramcells.addElement(name);
cellvars.addElement(name);
info.env_index = cell++;
if ((flags&PARAM) == 0) purecells.addElement(name);
continue;
}
} else {
info.flags |= FREE;
}
}
boolean some_free = false;
boolean nested = up.kind != TOPSCOPE;
for (Enumeration e = tbl.keys(); e.hasMoreElements(); ) {
String name = (String)e.nextElement();
SymInfo info = (SymInfo)tbl.get(name);
int flags = info.flags;
if (nested && (flags&FREE) != 0) up.inner_free.put(name,PRESENT);
if ((flags&(GLOBAL|PARAM|CELL)) == 0) {
if ((flags&BOUND) != 0) { // ?? only func
// System.err.println("local: "+name);
names.addElement(name);
info.locals_index = local++;
continue;
}
info.flags |= FREE;
some_free = true;
if (nested) up.inner_free.put(name,PRESENT);
}
}
if ((jy_npurecell = purecells.size()) > 0) {
int sz = purecells.size();
for (int i = 0; i < sz; i++) {
names.addElement(purecells.elementAt(i));
}
}
if ((unqual_exec || from_import_star)) {
if(some_inner_free) dynastuff_trouble(true, ctxt);
else if(func_level > 1 && some_free)
dynastuff_trouble(false, ctxt);
}
}
private void dynastuff_trouble(boolean inner_free,
CompilationContext ctxt) throws Exception {
String illegal;
if (unqual_exec && from_import_star)
illegal = "function '"+scope_name+
"' uses import * and bare exec, which are illegal";
else if (unqual_exec)
illegal = "unqualified exec is not allowed in function '"+
scope_name+"'";
else
illegal = "import * is not allowed in function '"+scope_name+"'";
String why;
if (inner_free)
why = " because it contains a function with free variables";
else
why = " because it contains free variables";
ctxt.error(illegal + why, true, scope_node);
}
public Vector freevars = new Vector();
/**
* setup the closure on this scope using the scope passed into cook as up as
* the containing scope
*/
public void setup_closure() {
setup_closure(up);
}
/**
* setup the closure on this scope using the passed in scope. This is used
* by jythonc to setup its closures.
*/
public void setup_closure(ScopeInfo up){
int free = cell; // env = cell...,free...
Hashtable up_tbl = up.tbl;
boolean nested = up.kind != TOPSCOPE;
for (Enumeration e = tbl.keys(); e.hasMoreElements(); ) {
String name = (String)e.nextElement();
SymInfo info = (SymInfo)tbl.get(name);
int flags = info.flags;
if ((flags&FREE) != 0) {
SymInfo up_info = (SymInfo)up_tbl.get(name);
// ?? differs from CPython -- what is the intended behaviour?
if (up_info != null) {
int up_flags = up_info.flags;
if ((up_flags&(CELL|FREE)) != 0) {
info.env_index = free++;
freevars.addElement(name);
continue;
}
// ! func global affect nested scopes
if (nested && (up_flags&NGLOBAL) != 0) {
info.flags = NGLOBAL|BOUND;
continue;
}
}
info.flags &= ~FREE;
}
}
}
public String toString() {
return "ScopeInfo[" + scope_name + " " + kind + "]@" +
System.identityHashCode(this);
}
}