// (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 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(); 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); } }