From: Samuele P. <ped...@us...> - 2001-03-08 23:42:07
|
Update of /cvsroot/jython/jython/org/python/compiler In directory usw-pr-cvs1:/tmp/cvs-serv850/compiler Modified Files: CodeCompiler.java Module.java Added Files: CompilerFlags.java Future.java ScopeConstants.java ScopeInfo.java ScopesCompiler.java SymInfo.java Log Message: nested scopes *future* support (as CPython 2.1) --- NEW FILE --- package org.python.compiler; public class CompilerFlags extends Object { public boolean nested_scopes; } --- NEW FILE --- // (C) Copyright 2001 Samuele Pedroni package org.python.compiler; import org.python.parser.*; public class Future extends Object { private boolean nested_scopes; private static final String FUTURE = "__future__"; private boolean check(SimpleNode cand) throws Exception { SimpleNode dotted_name = cand.getChild(0); if (dotted_name.getNumChildren() != 1 || !((String)dotted_name.getChild(0).getInfo()).equals(FUTURE)) return false; int n = cand.getNumChildren(); if (n == 1) { throw new ParseException("future statement does not support import *",cand); } for (int i = 1; i < n; i++) { SimpleNode imp = cand.getChild(i); String feature; switch(imp.id) { default: case PythonGrammarTreeConstants.JJTNAME: feature = (String)imp.getInfo(); break; case PythonGrammarTreeConstants.JJTIMPORT_AS_NAME: feature = (String)imp.getChild(0).getInfo(); break; } // *known* features if (feature.equals("nested_scopes")) { nested_scopes = true; continue; } throw new ParseException("future feature "+feature+" is not defined"); } return true; } public void preprocessFutures(SimpleNode node,CompilerFlags cflags) throws Exception { if (cflags != null) { nested_scopes = cflags.nested_scopes; } if ( node.id != PythonGrammarTreeConstants.JJTFILE_INPUT && node.id != PythonGrammarTreeConstants.JJTSINGLE_INPUT) return; int n = node.getNumChildren(); if (n == 0) return; int beg = 0; if (node.id == PythonGrammarTreeConstants.JJTFILE_INPUT && node.getChild(0).id == PythonGrammarTreeConstants.JJTEXPR_STMT && node.getChild(0).getChild(0).id == PythonGrammarTreeConstants.JJTSTRING) beg++; for (int i = beg; i < n; i++) { SimpleNode stmt = node.getChild(i); if (stmt.id != PythonGrammarTreeConstants.JJTIMPORTFROM) break; stmt.from_future_checked = true; if (!check(stmt)) break; } if (cflags != null) { cflags.nested_scopes = cflags.nested_scopes || nested_scopes; } } public static void checkFromFuture(SimpleNode node) throws Exception { if (node.from_future_checked) return; SimpleNode dotted_name = node.getChild(0); if (dotted_name.getNumChildren() == 1 && ((String)dotted_name.getChild(0).getInfo()).equals(FUTURE)) { throw new ParseException("from __future__ imports must occur at the beginning of the file",node); } node.from_future_checked = true; } public boolean areNestedScopesOn() { return nested_scopes; } } --- NEW FILE --- package org.python.compiler; public interface ScopeConstants { public final static int BOUND = 1; public final static int GLOBAL = 2; public final static int PARAM = 4; public final static int FROM_PARAM = 8; public final static int CELL = 16; public final static int FREE = 32; public final static int TOPSCOPE = 0; public final static int FUNCSCOPE = 1; public final static int CLASSSCOPE = 2; } --- NEW FILE --- // (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 void dump() { // for debugging if (org.python.core.Options.verbose < org.python.core.Py.DEBUG) return; for(int i=0; i<level; i++) System.err.print(' '); System.err.print(((kind != CLASSSCOPE)?scope_name:"class "+scope_name)+": "); for (Enumeration e = tbl.keys(); e.hasMoreElements(); ) { String name = (String)e.nextElement(); SymInfo info = (SymInfo)tbl.get(name); int flags = info.flags; System.err.print(name); if ((flags&BOUND) != 0) System.err.print('='); if ((flags&GLOBAL) != 0) System.err.print('G'); if ((flags&PARAM) != 0) System.err.print('P'); else if ((flags&FROM_PARAM) != 0) System.err.print('p'); if ((flags&CELL) != 0) System.err.print('!'); if ((flags&FREE) != 0) System.err.print(",f"); System.err.print(" "); } System.err.println(); } public ScopeInfo(String name,SimpleNode node,int level,int kind,int func_level,ArgListCompiler ac,boolean nested_scopes) { scope_name = name; scope_node = node; this.level = level; this.kind = kind; this.func_level = func_level; this.ac = ac; this.nested_scopes = nested_scopes; } public int kind; public boolean nested_scopes; public boolean unqual_exec; public boolean exec; public boolean from_import_star; public ArgListCompiler ac; public Hashtable tbl = new Hashtable(); public Vector names = new Vector(); public int addGlobal(String name) { SymInfo info = (SymInfo)tbl.get(name); if (info == null) { tbl.put(name,new SymInfo(GLOBAL|BOUND)); return -1; } int prev = info.flags; info.flags |= GLOBAL|BOUND; return prev; } public int local = 0; public void addParam(String name) { tbl.put(name, new SymInfo(PARAM|BOUND,local++)); names.addElement(name); } public void markFromParam() { for (Enumeration e=tbl.elements(); e.hasMoreElements(); ) { SymInfo info = (SymInfo)e.nextElement(); info.flags |= FROM_PARAM; } } public void addBound(String name) { SymInfo info = (SymInfo)tbl.get(name); if (info == null) { tbl.put(name, new SymInfo(BOUND)); return; } info.flags |= BOUND; } public void addUsed(String name) { if (tbl.get(name) == null) { tbl.put(name, new SymInfo(0)); return; } } private final static Object PRESENT = new Object(); public Hashtable inner_free = new Hashtable(); public Vector cellvars = new Vector(); public Vector xxx_paramcells = new Vector(); public int xxx_npurecell; // ?? xxx public int cell; public void cook(ScopeInfo up,CodeCompiler ctxt) throws Exception { if (up == null) return; // top level => nop boolean nested_scopes = this.nested_scopes; 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) { if ((flags&GLOBAL) == 0 && (flags&BOUND) != 0) { if (nested_scopes) { info.flags |= CELL; if ((info.flags&PARAM) != 0) xxx_paramcells.addElement(name); cellvars.addElement(name); info.env_index = cell++; if ((flags&PARAM) == 0) purecells.addElement(name); continue; } ctxt.error("local name '"+name+"' in '"+scope_name+"' shadows use as global in nested scopes",false,scope_node); } } 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 ((xxx_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,CodeCompiler 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 ,nested_scopes,scope_node); } public Vector freevars = new Vector(); public void setup_closure(ScopeInfo up) { if (!nested_scopes) return; 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); if (up_info != null) { // ?? differs from CPython -- what is the intended behaviour? int up_flags = up_info.flags; if ((up_flags&(CELL|FREE)) != 0) { info.env_index = free++; freevars.addElement(name); continue; } if (nested && (up_flags&GLOBAL) != 0) { info.flags = GLOBAL|BOUND; continue; } } info.flags &= ~FREE; } } } } --- NEW FILE --- // (C) Copyright 2001 Samuele Pedroni package org.python.compiler; import org.python.parser.*; import java.util.*; public class ScopesCompiler extends Visitor implements ScopeConstants { private CodeCompiler code_compiler; private boolean nested_scopes = false; private Stack scopes; private ScopeInfo cur = null; private int mode; private static final int GET=0; private static final int SET=1; private static final int DEL=2; private static final int AUGSET=4; private int level = 0; private int func_level = 0; public ScopesCompiler(CodeCompiler code_compiler) { // ?? polish this.code_compiler = code_compiler; scopes = new Stack(); mode = GET; String nested_scopes_opt = org.python.core.PySystemState.registry.getProperty("python.xfutures.nested_scopes"); if (nested_scopes_opt != null && nested_scopes_opt.equals("on")) nested_scopes = true; else nested_scopes = code_compiler.futures.areNestedScopesOn(); // System.err.println("nested-scopes: "+nested_scopes); } public Object set(SimpleNode node) throws Exception { return modal(node,SET); } public Object del(SimpleNode node) throws Exception { return modal(node,DEL); } public Object augset(SimpleNode node) throws Exception { return modal(node,AUGSET); } public Object modal(SimpleNode node, int newmode)throws Exception { mode = newmode; node.visit(this); mode = GET; return null; } public void beginScope(String name,int kind,SimpleNode node,ArgListCompiler ac) { if (cur != null) { scopes.push(cur); } if (kind == FUNCSCOPE) func_level++; node.scope = cur = new ScopeInfo(name,node,level++,kind,func_level,ac,nested_scopes); } public void endScope() throws Exception { if (cur.kind == FUNCSCOPE) func_level--; level--; ScopeInfo up = (!scopes.empty())?(ScopeInfo)scopes.pop():null; cur.cook(up,code_compiler); cur.dump(); // dbg cur = up; } public void parse(SimpleNode node) throws Exception { node.visit(this); } public Object single_input(SimpleNode node) throws Exception { beginScope("<single-top>",TOPSCOPE,node,null); suite(node); endScope(); return null; } public Object file_input(SimpleNode node) throws Exception { beginScope("<file-top>",TOPSCOPE,node,null); suite(node); endScope(); return null; } public Object eval_input(SimpleNode node) throws Exception { beginScope("<eval-top>",TOPSCOPE,node,null); return_stmt(node); endScope(); return null; } private String def(SimpleNode node) { String name = (String)node.getChild(0).getInfo(); cur.addBound(name); return name; } public Object funcdef(SimpleNode node) throws Exception { String my_name = def(node); ArgListCompiler ac = new ArgListCompiler(); SimpleNode suite; if (node.getNumChildren() == 3) { suite = node.getChild(2); //Parse arguments node.getChild(1).visit(ac); } else { suite = node.getChild(1); } SimpleNode[] defaults = ac.getDefaults(); int defc = defaults.length; for(int i=0; i<defc; i++) { defaults[i].visit(this); } beginScope(my_name,FUNCSCOPE,node,ac); int n = ac.names.size(); for (int i=0; i<n; i++) { cur.addParam((String)ac.names.elementAt(i)); } ac.init_code.visit(this); cur.markFromParam(); suite.visit(this); endScope(); return null; } public Object expr_stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); node.getChild(n-1).visit(this); for (int i=0; i<n-1; i++) { set(node.getChild(i)); } return null; } public Object print_ext(SimpleNode node) throws Exception { node.getChild(0).visit(this); return null; } public Object print_stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); if ( n > 0 ) { for (int i=0; i<n-1; i++) { node.getChild(i).visit(this); } if(node.getChild(n-1).id != PythonGrammarTreeConstants.JJTCOMMA) node.getChild(n-1).visit(this); } return null; } public Object del_stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); for (int i=0; i<n; i++) { del(node.getChild(i)); } return null; } public Object pass_stmt(SimpleNode n) throws Exception { return null; } public Object break_stmt(SimpleNode n) throws Exception { return null; } public Object continue_stmt(SimpleNode n) throws Exception { return null; } public Object return_stmt(SimpleNode node) throws Exception { if (node.getNumChildren() == 1) node.getChild(0).visit(this); return null; } public void stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); for (int i=0; i<n; i++) node.getChild(i).visit(this); } public Object raise_stmt(SimpleNode node) throws Exception { stmt(node); return null; } public Object Import(SimpleNode node) throws Exception { int n = node.getNumChildren(); for(int i = 0; i < n; i++) { SimpleNode imp = node.getChild(i); switch(imp.id) { case PythonGrammarTreeConstants.JJTDOTTED_NAME: cur.addBound((String)imp.getChild(0).getInfo()); break; case PythonGrammarTreeConstants.JJTDOTTED_AS_NAME: cur.addBound((String)imp.getChild(1).getInfo()); break; } } return null; } public Object ImportFrom(SimpleNode node) throws Exception { Future.checkFromFuture(node); // future stmt support int n = node.getNumChildren(); if (n == 1) { cur.from_import_star = true; return null; } for (int i = 1; i < n; i++) { SimpleNode imp = node.getChild(i); switch(imp.id) { case PythonGrammarTreeConstants.JJTNAME: cur.addBound((String)imp.getInfo()); break; case PythonGrammarTreeConstants.JJTIMPORT_AS_NAME: cur.addBound((String)imp.getChild(1).getInfo()); break; } } return null; } public Object global_stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); for(int i = 0; i < n; i++) { String name = (String)node.getChild(i).getInfo(); 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 = "assignement"; else what = "use"; code_compiler.error("name '"+name+"' declared global after "+what,false,node); } } return null; } public Object exec_stmt(SimpleNode node) throws Exception { cur.exec = true; int n = node.getNumChildren(); if (n == 1) cur.unqual_exec = true; for (int i = 0; i < n; i++) node.getChild(i).visit(this); return null; } public Object assert_stmt(SimpleNode node) throws Exception { stmt(node); return null; } public Object if_stmt(SimpleNode node) throws Exception { stmt(node); return null; } public Object while_stmt(SimpleNode node) throws Exception { stmt(node); return null; } public Object for_stmt(SimpleNode node) throws Exception { if (mode != GET) illassign(node); set(node.getChild(0)); node.getChild(1).visit(this); node.getChild(2).visit(this); if (node.getNumChildren()>3) node.getChild(3).visit(this); return null; } public Object try_stmt(SimpleNode node) throws Exception { int n = node.getNumChildren(); for (int i=0; i<n; i++) { if (i%2 == 1 && i != n-1) { switch(node.getChild(i).getNumChildren()) { case 2: set(node.getChild(i).getChild(1)); case 1: node.getChild(i).getChild(0).visit(this); } continue; } node.getChild(i).visit(this); } return null; } public Object suite(SimpleNode node) throws Exception { stmt(node); return null; } private static void illassign(SimpleNode node) throws Exception { String target = "operator"; if (node.id == PythonGrammarTreeConstants.JJTCALL_OP) { target = "function call"; } else if ((node.id == PythonGrammarTreeConstants.JJTFOR_STMT)) { target = "list comprehension"; } throw new ParseException("can't assign to "+target,node); } public void binaryop(SimpleNode node) throws Exception { if (mode != GET) illassign(node); node.getChild(0).visit(this); node.getChild(1).visit(this); } public void unaryop(SimpleNode node) throws Exception { if (mode != GET) illassign(node); node.getChild(0).visit(this); } public Object or_boolean(SimpleNode node) throws Exception { binaryop(node); return null; } public Object and_boolean(SimpleNode node) throws Exception { binaryop(node); return null; } public Object not_1op(SimpleNode node) throws Exception { unaryop(node); return null; } public Object comparision(SimpleNode node) throws Exception { if (mode != GET) illassign(node); int n = node.getNumChildren(); for (int i=0; i<n; i++) { if (i%2 == 0) node.getChild(i).visit(this); } return null; } public Object or_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object xor_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object and_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object lshift_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object rshift_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object add_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object sub_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object mul_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object div_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object mod_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object pos_1op(SimpleNode node) throws Exception { unaryop(node); return null; } public Object neg_1op(SimpleNode node) throws Exception { unaryop(node); return null; } public Object invert_1op(SimpleNode node) throws Exception { unaryop(node); return null; } public Object pow_2op(SimpleNode node) throws Exception { binaryop(node); return null; } public Object str_1op(SimpleNode node) throws Exception { unaryop(node); return null; } public Object strjoin(SimpleNode node) throws Exception { binaryop(node); return null; } public Object Call_Op(SimpleNode node) throws Exception { if (mode != GET) illassign(node); node.getChild(0).visit(this); if (node.getNumChildren()>1) { SimpleNode args=node.getChild(1); int n = args.getNumChildren(); for (int i=0; i<n; i++) { SimpleNode arg = args.getChild(i); switch(arg.id) { case PythonGrammarTreeConstants.JJTKEYWORD: arg.getChild(1).visit(this); break; case PythonGrammarTreeConstants.JJTEXTRAARGVALUELIST: case PythonGrammarTreeConstants.JJTEXTRAKEYWORDVALUELIST: arg.getChild(0).visit(this); break; default: arg.visit(this); } } } return null; } public Object Index_Op(SimpleNode node) throws Exception { int prevmode= mode; mode = GET; node.getChild(0).visit(this); node.getChild(1).visit(this); mode = prevmode; return null; } public Object Dot_Op(SimpleNode node) throws Exception { int prevmode = mode; mode = GET; node.getChild(0).visit(this); mode = prevmode; return null; } public Object tuple(SimpleNode node) throws Exception { if (mode ==AUGSET) { throw new ParseException( "augmented assign to tuple not possible", node); } int n = node.getNumChildren(); if (n > 0) { for (int i=0; i<n-1; i++) node.getChild(i).visit(this); if (node.getChild(n-1).id != PythonGrammarTreeConstants.JJTCOMMA) node.getChild(n-1).visit(this); } return null; } public Object fplist(SimpleNode node) throws Exception { return list(node); } public Object list(SimpleNode node) throws Exception { if (mode ==AUGSET) { throw new ParseException( "augmented assign to list not possible", node); } int n = node.getNumChildren(); if (n > 0) { for (int i=0; i<n-1; i++) node.getChild(i).visit(this); if (node.getChild(n-1).id != PythonGrammarTreeConstants.JJTCOMMA) node.getChild(n-1).visit(this); } return null; } public Object list_iter(SimpleNode node) throws Exception { if (node.getNumChildren() == 1) node.getChild(0).visit(this); return null; } public Object dictionary(SimpleNode node) throws Exception { if (mode != GET) illassign(node); stmt(node); return null; } public Object lambdef(SimpleNode node) throws Exception { if (mode != GET) illassign(node); ArgListCompiler ac = new ArgListCompiler(); SimpleNode expr; if (node.getNumChildren() == 2) { expr = node.getChild(1); //Parse arguments node.getChild(0).visit(ac); } else { expr = node.getChild(0); } SimpleNode[] defaults = ac.getDefaults(); int defc = defaults.length; for(int i=0; i<defc; i++) { defaults[i].visit(this); } beginScope("<lambda>",FUNCSCOPE,node,ac); int n = ac.names.size(); for (int i=0; i<n; i++) { cur.addParam((String)ac.names.elementAt(i)); } ac.init_code.visit(this); cur.markFromParam(); expr.visit(this); endScope(); return null; } public Object Ellipses(SimpleNode n) throws Exception { return null; } public Object Slice(SimpleNode node) throws Exception { int n = node.getNumChildren(); for (int i=0; i<n; i++) { SimpleNode snode = node.getChild(i); if (snode.id != PythonGrammarTreeConstants.JJTCOLON) { snode.visit(this); } } return null; } public Object classdef(SimpleNode node) throws Exception { String cl_name = def(node); int n = node.getNumChildren(); SimpleNode suite = node.getChild(n-1); for (int i=1; i<n-1; i++) node.getChild(i).visit(this); beginScope(cl_name,CLASSSCOPE,node,null); suite.visit(this); endScope(); return null; } public Object Int(SimpleNode node) throws Exception { if (mode != GET) illassign(node); return null; } public Object Float(SimpleNode node) throws Exception { if (mode != GET) illassign(node); return null; } public Object Complex(SimpleNode node) throws Exception { if (mode != GET) illassign(node); return null; } public Object Name(SimpleNode node) throws Exception { String name = (String)node.getInfo(); if ( mode != GET) cur.addBound(name); else cur.addUsed(name); return null; } public Object String(SimpleNode node) throws Exception { if (mode != GET) illassign(node); return null; } public void aug_assign(SimpleNode node) throws Exception { augset(node.getChild(0)); node.getChild(1).visit(this); } public Object aug_plus(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_minus(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_multiply(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_divide(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_modulo(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_and(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_or(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_xor(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_lshift(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_rshift(SimpleNode node) throws Exception { aug_assign(node); return null; } public Object aug_power(SimpleNode node) throws Exception { aug_assign(node); return null; } } --- NEW FILE --- package org.python.compiler; public class SymInfo extends Object { public SymInfo(int flags) { this.flags = flags; } public SymInfo(int flags,int locals_index) { this.flags = flags; this.locals_index = locals_index; } public int flags; public int locals_index; public int env_index; } Index: CodeCompiler.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/compiler/CodeCompiler.java,v retrieving revision 2.11 retrieving revision 2.12 diff -C2 -r2.11 -r2.12 *** CodeCompiler.java 2001/02/07 09:21:23 2.11 --- CodeCompiler.java 2001/03/08 23:43:51 2.12 *************** *** 4,7 **** --- 4,10 ---- import org.python.parser.*; + import org.python.core.Py; + import org.python.core.PyObject; + import org.python.core.PyException; import java.io.IOException; import java.util.Stack; *************** *** 31,36 **** public boolean fast_locals, print_results; ! public Hashtable locals; ! public Hashtable globals; boolean optimizeGlobals = true; public Vector names; --- 34,42 ---- public boolean fast_locals, print_results; ! ! public Future futures; ! public Hashtable tbl; ! public ScopeInfo my_scope; ! boolean optimizeGlobals = true; public Vector names; *************** *** 161,167 **** public void parse(SimpleNode node, Code code, boolean fast_locals, String className, ! boolean classBody, ArgListCompiler ac) throws Exception { --- 167,186 ---- + public void error(String msg,boolean err,SimpleNode node) throws Exception { + if (!err) { + try { + Py.warning(Py.SyntaxWarning,msg,(module.sfilename!=null)?module.sfilename:"?", + node.beginLine,null,Py.None); + return; + } catch(PyException e) { + if (!Py.matchException(e,Py.SyntaxWarning)) throw e; + } + } + throw new ParseException(msg,node); + } + public void parse(SimpleNode node, Code code, boolean fast_locals, String className, ! boolean classBody, ScopeInfo scope) throws Exception { *************** *** 170,185 **** this.code = code; ! //Check out locals if fast_locals is on ! LocalsCompiler lc = new LocalsCompiler(); ! int n = ac.names.size(); ! for (int i=0; i<n; i++) { ! lc.addLocal((String)ac.names.elementAt(i)); } ! lc.parse(node); ! names = lc.names; ! locals = lc.locals; ! globals = lc.globals; ! optimizeGlobals = lc.optimizeGlobals; mode = GET; --- 189,204 ---- this.code = code; ! if (scope == null) { ! futures = new Future(); ! futures.preprocessFutures(node,null); ! new ScopesCompiler(this).parse(node); ! scope = node.scope; } ! ! my_scope = scope; ! names = scope.names; ! tbl = scope.tbl; ! optimizeGlobals = !scope.exec&&!scope.from_import_star; mode = GET; *************** *** 190,194 **** loadFrame(); code.invokevirtual("org/python/core/PyFrame", "getf_locals", ! "()Lorg/python/core/PyObject;"); code.areturn(); } else { --- 209,213 ---- loadFrame(); code.invokevirtual("org/python/core/PyFrame", "getf_locals", ! "()Lorg/python/core/PyObject;"); code.areturn(); } else { *************** *** 295,308 **** } ! int f_globals, PyFunction_init; public Object funcdef(SimpleNode node) throws Exception { String name = getName(node.getChild(0)); - ArgListCompiler ac = new ArgListCompiler(); SimpleNode suite; if (node.getNumChildren() == 3) { suite = node.getChild(2); //Parse arguments - node.getChild(1).visit(ac); } else { suite = node.getChild(1); --- 314,360 ---- } ! int getclosure; ! ! public boolean makeClosure(Vector freenames) throws Exception { ! if (freenames == null) return false; ! int n = freenames.size(); ! if (n == 0) return false; ! ! if (mrefs.getclosure == 0) { ! mrefs.getclosure = code.pool.Methodref( ! "org/python/core/PyFrame", "getclosure", ! "(I)Lorg/python/core/PyObject;"); ! } ! ! int tmp = code.getLocal(); ! code.iconst(n); ! code.anewarray(code.pool.Class("org/python/core/PyObject")); ! code.astore(tmp); + for(int i=0; i<n; i++) { + code.aload(tmp); + code.iconst(i); + code.aload(1); // get frame + code.iconst(((SymInfo)tbl.get(freenames.elementAt(i))).env_index); + code.invokevirtual(getclosure); + code.aastore(); + } + + code.aload(tmp); + code.freeLocal(tmp); + + return true; + } + + + + int f_globals, PyFunction_init, PyFunction_closure_init; + public Object funcdef(SimpleNode node) throws Exception { String name = getName(node.getChild(0)); SimpleNode suite; if (node.getNumChildren() == 3) { suite = node.getChild(2); //Parse arguments } else { suite = node.getChild(1); *************** *** 321,337 **** code.getfield(mrefs.f_globals); ! makeArray(ac.getDefaults()); ! ! module.PyCode(suite, name, ac, true, className, false, false, ! node.beginLine).get(code); ! getDocString(suite); ! if (mrefs.PyFunction_init == 0) { ! mrefs.PyFunction_init = code.pool.Methodref( "org/python/core/PyFunction", "<init>", "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;)V"); } - code.invokespecial(mrefs.PyFunction_init); set(node.getChild(0)); --- 373,403 ---- code.getfield(mrefs.f_globals); ! makeArray(node.scope.ac.getDefaults()); ! ! node.scope.setup_closure(my_scope); ! node.scope.dump(); ! module.PyCode(suite, name, true, className, false, false, ! node.beginLine, node.scope).get(code); ! Vector freenames = node.scope.freevars; ! node.scope = null; // release scope info ! getDocString(suite); ! if (!makeClosure(freenames)) { ! if (mrefs.PyFunction_init == 0) { ! mrefs.PyFunction_init = code.pool.Methodref( "org/python/core/PyFunction", "<init>", "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;)V"); + } + code.invokespecial(mrefs.PyFunction_init); + } else { + if (mrefs.PyFunction_closure_init == 0) { + mrefs.PyFunction_closure_init = code.pool.Methodref( + "org/python/core/PyFunction", "<init>", + "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;[Lorg/python/core/PyObject;)V"); + } + code.invokespecial(mrefs.PyFunction_closure_init); + } set(node.getChild(0)); *************** *** 628,631 **** --- 694,698 ---- public Object ImportFrom(SimpleNode node) throws Exception { + Future.checkFromFuture(node); // future stmt support setline(node); String name = (String)node.getChild(0).visit(this); *************** *** 677,685 **** public Object global_stmt(SimpleNode node) throws Exception { - int n = node.getNumChildren(); - for (int i=0; i<n; i++) { - Object name = node.getChild(i).getInfo(); - globals.put(name, name); - } return null; } --- 744,747 ---- *************** *** 716,720 **** public int assert1, assert2; ! public Object assert_stmt(SimpleNode node) throws Exception { setline(node); Label end_of_assert = code.getLabel(); --- 778,782 ---- public int assert1, assert2; ! public Object assert_stmt(SimpleNode node) throws Exception { // ?? pending __debug__ should be treated as temp global setline(node); Label end_of_assert = code.getLabel(); *************** *** 1875,1881 **** public int PyTuple_init, PyList_init, PyDictionary_init; public Object tuple(SimpleNode node) throws Exception { ! if (mode ==AUGSET) throw new ParseException( ! "augmented assign to tuple not possible", node); if (mode == SET) return seqSet(node); if (mode == DEL) return seqDel(node); --- 1937,1943 ---- public int PyTuple_init, PyList_init, PyDictionary_init; public Object tuple(SimpleNode node) throws Exception { ! /* if (mode ==AUGSET) throw new ParseException( ! "augmented assign to tuple not possible", node); */ if (mode == SET) return seqSet(node); if (mode == DEL) return seqDel(node); *************** *** 1899,1905 **** public Object list(SimpleNode node) throws Exception { ! if (mode ==AUGSET) throw new ParseException( ! "augmented assign to list not possible", node); if (node.getNumChildren() > 1 && node.getChild(1).id == --- 1961,1967 ---- public Object list(SimpleNode node) throws Exception { ! /* if (mode ==AUGSET) throw new ParseException( ! "augmented assign to list not possible", node); */ if (node.getNumChildren() > 1 && node.getChild(1).id == *************** *** 2004,2016 **** } ! public int PyFunction_init1; public Object lambdef(SimpleNode node) throws Exception { String name = "<lambda>"; - ArgListCompiler ac = new ArgListCompiler(); SimpleNode suite; if (node.getNumChildren() == 2) { suite = node.getChild(1); - //Parse arguments - node.getChild(0).visit(ac); } else { suite = node.getChild(0); --- 2066,2075 ---- } ! public int PyFunction_init1,PyFunction_closure_init1; public Object lambdef(SimpleNode node) throws Exception { String name = "<lambda>"; SimpleNode suite; if (node.getNumChildren() == 2) { suite = node.getChild(1); } else { suite = node.getChild(0); *************** *** 2034,2048 **** code.getfield(mrefs.f_globals); ! makeArray(ac.getDefaults()); ! ! module.PyCode(retSuite, name, ac, true, className, ! false, false, node.beginLine).get(code); ! ! if (mrefs.PyFunction_init1 == 0) { ! mrefs.PyFunction_init1 = code.pool.Methodref( "org/python/core/PyFunction", "<init>", "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;)V"); } ! code.invokespecial(mrefs.PyFunction_init1); return null; } --- 2093,2121 ---- code.getfield(mrefs.f_globals); ! makeArray(node.scope.ac.getDefaults()); ! ! node.scope.setup_closure(my_scope); ! node.scope.dump(); ! module.PyCode(retSuite, name, true, className, ! false, false, node.beginLine, node.scope).get(code); ! Vector freenames = node.scope.freevars; ! node.scope = null; // release scope info ! ! if (!makeClosure(freenames)) { ! if (mrefs.PyFunction_init1 == 0) { ! mrefs.PyFunction_init1 = code.pool.Methodref( "org/python/core/PyFunction", "<init>", "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;)V"); + } + code.invokespecial(mrefs.PyFunction_init1); + } else { + if (mrefs.PyFunction_closure_init1 == 0) { + mrefs.PyFunction_closure_init1 = code.pool.Methodref( + "org/python/core/PyFunction", "<init>", + "(Lorg/python/core/PyObject;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;[Lorg/python/core/PyObject;)V"); + } + code.invokespecial(mrefs.PyFunction_closure_init1); } ! return null; } *************** *** 2091,2095 **** } ! public int makeClass; public Object classdef(SimpleNode node) throws Exception { setline(node); --- 2164,2168 ---- } ! public int makeClass,makeClass_closure; public Object classdef(SimpleNode node) throws Exception { setline(node); *************** *** 2107,2114 **** makeArray(bases); //Make code object out of suite ! module.PyCode(node.getChild(n-1), name, ! new ArgListCompiler(), false, name, true, false, ! node.beginLine).get(code); //Get doc string (if there) --- 2180,2190 ---- makeArray(bases); + node.scope.setup_closure(my_scope); + node.scope.dump(); //Make code object out of suite ! module.PyCode(node.getChild(n-1), name, false, name, true, false, ! node.beginLine, node.scope).get(code); ! Vector freenames = node.scope.freevars; ! node.scope = null; // release scope info //Get doc string (if there) *************** *** 2116,2126 **** //Make class out of name, bases, and code ! if (mrefs.makeClass == 0) { ! mrefs.makeClass = code.pool.Methodref( "org/python/core/Py", "makeClass", "(Ljava/lang/String;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;)Lorg/python/core/PyObject;"); } ! code.invokestatic(mrefs.makeClass); ! //Assign this new class to the given name set(node.getChild(0)); --- 2192,2211 ---- //Make class out of name, bases, and code ! if (!makeClosure(freenames)) { ! if (mrefs.makeClass == 0) { ! mrefs.makeClass = code.pool.Methodref( "org/python/core/Py", "makeClass", "(Ljava/lang/String;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;)Lorg/python/core/PyObject;"); + } + code.invokestatic(mrefs.makeClass); + } else { + if (mrefs.makeClass_closure == 0) { + mrefs.makeClass_closure = code.pool.Methodref( + "org/python/core/Py", "makeClass", + "(Ljava/lang/String;[Lorg/python/core/PyObject;Lorg/python/core/PyCode;Lorg/python/core/PyObject;[Lorg/python/core/PyObject;)Lorg/python/core/PyObject;"); + } + code.invokestatic(mrefs.makeClass_closure); } ! //Assign this new class to the given name set(node.getChild(0)); *************** *** 2162,2165 **** --- 2247,2251 ---- int setglobal, setlocal1, setlocal2; int delglobal, dellocal1, dellocal2; + int getderef,setderef; public Object Name(SimpleNode node) throws Exception { *************** *** 2175,2201 **** mode = SET; switch (mode) { case GET: loadFrame(); ! if (fast_locals) { ! Integer i = (Integer)locals.get(name); ! if (i == null && optimizeGlobals) { ! code.ldc(name); ! if (mrefs.getglobal == 0) { ! mrefs.getglobal = code.pool.Methodref( "org/python/core/PyFrame", "getglobal", "(Ljava/lang/String;)Lorg/python/core/PyObject;"); } ! code.invokevirtual(mrefs.getglobal); ! return null; ! } ! if (i != null) { ! code.iconst(i.intValue()); ! if (mrefs.getlocal2 == 0) { ! mrefs.getlocal2 = code.pool.Methodref( "org/python/core/PyFrame", "getlocal", "(I)Lorg/python/core/PyObject;"); } ! code.invokevirtual(mrefs.getlocal2); return null; } --- 2261,2310 ---- mode = SET; + SymInfo syminf = (SymInfo)tbl.get(name); + switch (mode) { case GET: loadFrame(); ! if (syminf != null) { ! if (fast_locals) { ! if ((syminf.flags&ScopeInfo.GLOBAL) !=0 && optimizeGlobals) { ! code.ldc(name); ! if (mrefs.getglobal == 0) { ! mrefs.getglobal = code.pool.Methodref( "org/python/core/PyFrame", "getglobal", "(Ljava/lang/String;)Lorg/python/core/PyObject;"); + } + code.invokevirtual(mrefs.getglobal); + return null; } ! if ((syminf.flags&ScopeInfo.GLOBAL)==0 && (syminf.flags&ScopeInfo.CELL)!=0) { ! code.iconst(syminf.env_index); ! if (mrefs.getderef == 0) { ! mrefs.getderef = code.pool.Methodref( ! "org/python/core/PyFrame", "getderef", ! "(I)Lorg/python/core/PyObject;"); ! } ! code.invokevirtual(mrefs.getderef); ! return null; ! } ! if ((syminf.flags&ScopeInfo.GLOBAL)==0 && (syminf.flags&ScopeInfo.BOUND)!=0) { ! code.iconst(syminf.locals_index); ! if (mrefs.getlocal2 == 0) { ! mrefs.getlocal2 = code.pool.Methodref( "org/python/core/PyFrame", "getlocal", "(I)Lorg/python/core/PyObject;"); + } + code.invokevirtual(mrefs.getlocal2); + return null; } ! } ! if (my_scope.nested_scopes && (syminf.flags&ScopeInfo.FREE) != 0) { ! code.iconst(syminf.env_index); ! if (mrefs.getderef == 0) { ! mrefs.getderef = code.pool.Methodref( ! "org/python/core/PyFrame", "getderef", ! "(I)Lorg/python/core/PyObject;"); ! } ! code.invokevirtual(mrefs.getderef); return null; } *************** *** 2212,2216 **** case SET: loadFrame(); ! if (globals.get(name) != null) { code.ldc(name); code.aload(temporary); --- 2321,2325 ---- case SET: loadFrame(); ! if (syminf != null && (syminf.flags&ScopeInfo.GLOBAL) != 0) { code.ldc(name); code.aload(temporary); *************** *** 2232,2253 **** code.invokevirtual(mrefs.setlocal1); } else { ! Integer i = (Integer)locals.get(name); ! if (i == null) { System.err.println("internal compiler error: "+node); } ! code.iconst(i.intValue()); ! code.aload(temporary); ! if (mrefs.setlocal2 == 0) { ! mrefs.setlocal2 = code.pool.Methodref( "org/python/core/PyFrame", "setlocal", "(ILorg/python/core/PyObject;)V"); } - code.invokevirtual(mrefs.setlocal2); } } return null; ! case DEL: loadFrame(); ! if (globals.get(name) != null) { code.ldc(name); if (mrefs.delglobal == 0) { --- 2341,2372 ---- code.invokevirtual(mrefs.setlocal1); } else { ! if (syminf == null) { System.err.println("internal compiler error: "+node); } ! if ((syminf.flags&ScopeInfo.CELL) != 0) { ! code.iconst(syminf.env_index); ! code.aload(temporary); ! if (mrefs.setderef == 0) { ! mrefs.setderef = code.pool.Methodref( ! "org/python/core/PyFrame", "setderef", ! "(ILorg/python/core/PyObject;)V"); ! } ! code.invokevirtual(mrefs.setderef); ! } else { ! code.iconst(syminf.locals_index); ! code.aload(temporary); ! if (mrefs.setlocal2 == 0) { ! mrefs.setlocal2 = code.pool.Methodref( "org/python/core/PyFrame", "setlocal", "(ILorg/python/core/PyObject;)V"); + } + code.invokevirtual(mrefs.setlocal2); } } } return null; ! case DEL: { loadFrame(); ! if (syminf != null && (syminf.flags&ScopeInfo.GLOBAL) != 0) { code.ldc(name); if (mrefs.delglobal == 0) { *************** *** 2267,2272 **** code.invokevirtual(mrefs.dellocal1); } else { ! Integer i = (Integer)locals.get(name); ! code.iconst(i.intValue()); if (mrefs.dellocal2 == 0) { mrefs.dellocal2 = code.pool.Methodref( --- 2386,2396 ---- code.invokevirtual(mrefs.dellocal1); } else { ! if (syminf == null) { ! System.err.println("internal compiler error: "+node); ! } ! if ((syminf.flags&ScopeInfo.CELL) != 0) { ! error("can not delete variable '"+name+"' referenced in nested scope",true,node); ! } ! code.iconst(syminf.locals_index); if (mrefs.dellocal2 == 0) { mrefs.dellocal2 = code.pool.Methodref( *************** *** 2277,2281 **** } } ! return null; } return null; --- 2401,2405 ---- } } ! return null; } } return null; Index: Module.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/compiler/Module.java,v retrieving revision 2.3 retrieving revision 2.4 diff -C2 -r2.3 -r2.4 *** Module.java 2000/01/11 20:38:48 2.3 --- Module.java 2001/03/08 23:43:51 2.4 *************** *** 193,196 **** --- 193,201 ---- public boolean arglist, keywordlist; String fname; + + // for nested scopes + public String[] cellvars; + public String[] freevars; + public int xxx_npurecell; public PyCodeConstant() { ; *************** *** 222,230 **** c.iconst(id); int mref_newCode = c.pool.Methodref( "org/python/core/Py", "newCode", ! "(I[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZLorg/python/core/PyFunctionTable;I)Lorg/python/core/PyCode;"); c.invokestatic(mref_newCode); --- 227,240 ---- c.iconst(id); + + if (cellvars != null) CodeCompiler.makeStrings(c, cellvars, cellvars.length); else c.aconst_null(); + if (freevars != null) CodeCompiler.makeStrings(c, freevars, freevars.length); else c.aconst_null(); + c.iconst(xxx_npurecell); + int mref_newCode = c.pool.Methodref( "org/python/core/Py", "newCode", ! "(I[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZLorg/python/core/PyFunctionTable;I[Ljava/lang/String;[Ljava/lang/String;I)Lorg/python/core/PyCode;"); c.invokestatic(mref_newCode); *************** *** 329,346 **** return true; } ! public PyCodeConstant PyCode(SimpleNode tree, String name, - ArgListCompiler ac, boolean fast_locals, String className, boolean classBody, boolean printResults, ! int firstlineno) throws Exception { PyCodeConstant code = new PyCodeConstant(); ! int i; ! code.arglist = ac.arglist; ! code.keywordlist = ac.keywordlist; ! code.argcount = ac.names.size(); ! code.co_name = name; code.co_firstlineno = firstlineno; --- 339,369 ---- return true; } ! ! private static final String[] emptyStringAr = new String[0]; ! ! private String[] toNameAr(Vector names,boolean nullok) { ! int sz = names.size(); ! if (sz ==0 && nullok) return null; ! return (String[])names.toArray(emptyStringAr); ! } ! ! ! private int to_cell; ! public PyCodeConstant PyCode(SimpleNode tree, String name, boolean fast_locals, String className, boolean classBody, boolean printResults, ! int firstlineno, ScopeInfo scope) throws Exception { PyCodeConstant code = new PyCodeConstant(); ! ArgListCompiler ac = (scope != null)?scope.ac:null; ! ! if (ac != null) { ! code.arglist = ac.arglist; ! code.keywordlist = ac.keywordlist; ! code.argcount = ac.names.size(); ! } ! code.co_name = name; code.co_firstlineno = firstlineno; *************** *** 363,378 **** CodeCompiler compiler = new CodeCompiler(this, printResults); ! if (ac.init_code.getNumChildren() > 0) { ac.init_code.jjtAddChild(tree, ac.init_code.getNumChildren()); tree = ac.init_code; } ! compiler.parse(tree, c, fast_locals, className, classBody, ac); ! code.names = new String[compiler.names.size()]; ! for(i=0; i<compiler.names.size(); i++) { ! code.names[i] = (String)compiler.names.elementAt(i); } ! code.module = this; code.name = code.fname; --- 386,422 ---- CodeCompiler compiler = new CodeCompiler(this, printResults); ! if (ac != null && ac.init_code.getNumChildren() > 0) { ac.init_code.jjtAddChild(tree, ac.init_code.getNumChildren()); tree = ac.init_code; } + + if (scope != null) { + int nparamcell = scope.xxx_paramcells.size(); + if (nparamcell > 0) { + if (to_cell == 0) { + to_cell = classfile.pool.Methodref("org/python/core/PyFrame","to_cell","(II)V"); + } + Hashtable tbl = scope.tbl; + Vector paramcells = scope.xxx_paramcells; + for (int i = 0; i < nparamcell; i++) { + c.aload(1); + SymInfo syminf = (SymInfo)tbl.get(paramcells.elementAt(i)); + c.iconst(syminf.locals_index); + c.iconst(syminf.env_index); + c.invokevirtual(to_cell); + } + } + } ! compiler.parse(tree, c, fast_locals, className, classBody, scope); ! code.names = toNameAr(compiler.names,false); ! ! if (scope != null) { ! code.cellvars = toNameAr(scope.cellvars,true); ! code.freevars = toNameAr(scope.freevars,true); ! code.xxx_npurecell = scope.xxx_npurecell; } ! code.module = this; code.name = code.fname; *************** *** 504,510 **** //Add __file__ for filename (if it exists?) ! Constant main = module.PyCode(node, "?", ! new ArgListCompiler(), ! false, null, false, printResults, 0); module.mainCode = main; module.write(ostream); --- 548,552 ---- //Add __file__ for filename (if it exists?) ! Constant main = module.PyCode(node, "?",false, null, false, printResults, 0,null); module.mainCode = main; module.write(ostream); |