1 package polyglot.visit; 2 3 import java.util.HashMap ; 4 import java.util.Map ; 5 6 import polyglot.ast.ConstructorCall; 7 import polyglot.ast.Node; 8 import polyglot.ast.NodeFactory; 9 import polyglot.frontend.Job; 10 import polyglot.types.ConstructorInstance; 11 import polyglot.types.Context; 12 import polyglot.types.SemanticException; 13 import polyglot.types.TypeSystem; 14 import polyglot.util.InternalCompilerError; 15 16 17 public class ConstructorCallChecker extends ContextVisitor 18 { 19 public ConstructorCallChecker(Job job, TypeSystem ts, NodeFactory nf) { 20 super(job, ts, nf); 21 } 22 23 protected Map constructorInvocations = new HashMap (); 24 25 protected NodeVisitor enterCall(Node n) throws SemanticException { 26 if (n instanceof ConstructorCall) { 27 ConstructorCall cc = (ConstructorCall)n; 28 if (cc.kind() == ConstructorCall.THIS) { 29 Context ctxt = context(); 31 32 if (!(ctxt.currentCode() instanceof ConstructorInstance)) { 33 throw new InternalCompilerError("Constructor call " + 34 "occurring in a non-constructor.", cc.position()); 35 } 36 ConstructorInstance srcCI = (ConstructorInstance)ctxt.currentCode(); 37 ConstructorInstance destCI = cc.constructorInstance(); 38 39 constructorInvocations.put(srcCI, destCI); 40 while (destCI != null) { 41 destCI = (ConstructorInstance)constructorInvocations.get(destCI); 42 if (destCI != null && srcCI.equals(destCI)) { 43 throw new SemanticException("Recursive constructor " + 45 "invocation.", cc.position()); 46 } 47 } 48 } 49 } 50 return this; 51 } 52 } 53 54 | Popular Tags |