/** Perform the appropriate flow operations for declaration of a local variable */ protected Map flowLocalDecl( DataFlowItem inItem, FlowGraph graph, LocalDecl ld, Set succEdgeKeys) { Map m = new HashMap(inItem.initStatus); MinMaxInitCount initCount = (MinMaxInitCount) m.get(ld.localInstance()); // if (initCount == null) { if (ld.init() != null) { // declaration of local var with initialization. initCount = new MinMaxInitCount(InitCount.ONE, InitCount.ONE); } else { // declaration of local var with no initialization. initCount = new MinMaxInitCount(InitCount.ZERO, InitCount.ZERO); } m.put(ld.localInstance(), initCount); // } // else { // the initCount is not null. We now have a problem. Why is the // initCount not null? Has this variable been assigned in its own // initialization, or is this a declaration inside a loop body? // XXX@@@ THIS IS A BUG THAT NEEDS TO BE FIXED. // Currently, the declaration "final int i = (i=5);" will // not be rejected, as we cannot distinguish between that and // "while (true) {final int i = 4;}" // } // record the fact that we have seen a local declaration currCBI.localDeclarations.add(ld.localInstance()); return itemToMap(new DataFlowItem(m), succEdgeKeys); }
@Override public Node typeCheck(ContextVisitor tc) throws SemanticException { RuleDef sym = null; MethodInstance mi = call.methodInstance(); IbexClassType ct = (IbexClassType) mi.container(); for (RuleInstance rule : ct.rules()) { if (rule.name() == mi.name()) sym = rule.def(); } if (sym == null) throw new SemanticException("Cannot find rule for " + mi); RhsInvoke n = (RhsInvoke) symbol(sym.asNonterminal()).type(call.type()); if (assocTag) { Context c = tc.context(); CodeDef code = c.currentCode(); if (code instanceof RuleDef) { RuleDef rd = (RuleDef) code; if (rd != sym) throw new SemanticException( "Associativity annotation must be self-recursive.", position()); } } if (!call.type().isVoid()) { TypeSystem ts = tc.typeSystem(); LocalDef li = ts.localDef(position(), Flags.FINAL, Types.ref(call.type()), call.name().id()); // Formal parameters are never compile-time constants. li.setNotConstant(); IbexNodeFactory nf = (IbexNodeFactory) tc.nodeFactory(); LocalDecl ld = nf.LocalDecl( position(), nf.FlagsNode(position(), li.flags()), nf.CanonicalTypeNode(position(), li.type()), nf.Id(position(), li.name())); ld = ld.localDef(li); ld = ld.init(n); return nf.RhsSyntheticBind(position(), ld).type(n.type()); } return n; }
/** Flatten complex expressions within the AST */ public Node leave(Node old, Node n, NodeVisitor v) { if (n == noFlatten) { noFlatten = null; return n; } if (n instanceof Block) { List l = (List) stack.removeFirst(); return ((Block) n).statements(l); } else if (n instanceof Stmt && !(n instanceof LocalDecl)) { List l = (List) stack.getFirst(); l.add(n); return n; } else if (n instanceof Expr && !(n instanceof Lit) && !(n instanceof Special) && !(n instanceof Local)) { Expr e = (Expr) n; if (e instanceof Assign) { return n; } // create a local temp, initialized to the value of the complex // expression String name = newID(); LocalDecl def = nf.LocalDecl( e.position(), Flags.FINAL, nf.CanonicalTypeNode(e.position(), e.type()), name, e); def = def.localInstance(ts.localInstance(e.position(), Flags.FINAL, e.type(), name)); List l = (List) stack.getFirst(); l.add(def); // return the local temp instead of the complex expression Local use = nf.Local(e.position(), name); use = (Local) use.type(e.type()); use = use.localInstance(ts.localInstance(e.position(), Flags.FINAL, e.type(), name)); return use; } return n; }
private Node buildLocalDecl(LocalDecl ld) throws SemanticException { Type t = ld.declType(); SJLocalInstance li = (SJLocalInstance) ld.localInstance(); // SJNamedInstance ni = null; if (t.isSubtype(SJ_PROTOCOL_TYPE)) // Mostly the same as for LocalDecl. { if (!(ld instanceof SJLocalProtocolDecl)) { throw new SemanticException( "[SJProtocolDeclTypeBuilder] Protocols may only be declared using the protocol keyword: " + ld); } SJTypeNode tn = disambiguateSJTypeNode(this, ((SJProtocolDecl) ld).sessionType()); SJSessionType st = tn.type(); String sjname = ld.name(); // Should match that given by SJVariable.sjname. ld = ld.localInstance(sjts.SJLocalProtocolInstance(li, st, sjname)); ld = (LocalDecl) setSJProtocolDeclExt((SJProtocolDecl) ld, tn, sjname); } return ld; }
/** Type check the statement. */ public Node typeCheck(TypeChecker tc) throws SemanticException { TypeSystem ts = tc.typeSystem(); // Check that all initializers have the same type. // This should be enforced by the parser, but check again here, // just to be sure. Type t = null; for (Iterator i = inits.iterator(); i.hasNext(); ) { ForInit s = (ForInit) i.next(); if (s instanceof LocalDecl) { LocalDecl d = (LocalDecl) s; Type dt = d.type().type(); if (t == null) { t = dt; } else if (!t.equals(dt)) { throw new InternalCompilerError( "Local variable " + "declarations in a for loop initializer must all " + "be the same type, in this case " + t + ", not " + dt + ".", d.position()); } } } if (cond != null && !ts.isImplicitCastValid(cond.type(), ts.Boolean())) { throw new SemanticException( "The condition of a for statement must have boolean type.", cond.position()); } return this; }
private Node translateExtendedFor(ExtendedFor n, List<String> labels) throws SemanticException { if (n.expr().type().isArray()) { return translateExtForArray(n, labels); } Position pos = Position.compilerGenerated(); Type iterType = ts.typeForName("java.util.Iterator"); Type iteratedType = n.decl().type().type(); // translate "L1,...,Ln: for (C x: e) b" to // "{ Iterator iter = e.iterator(); L1,...,Ln: while (iter.hasNext();) { C x = (C)iter.next(); // b }" // Create the iter declaration "Iterator iter = e.iterator()" Id iterName = freshName("iter"); LocalDecl iterDecl; LocalInstance iterLI = ts.localInstance(pos, Flags.NONE, iterType, iterName.id()); { Id id = nodeFactory().Id(pos, "iterator"); Call iterator = nodeFactory().Call(pos, n.expr(), id); iterator = (Call) iterator.type(iterType); iterator = iterator.methodInstance( ts.findMethod( n.expr().type().toClass(), "iterator", Collections.<Type>emptyList(), this.context().currentClass())); iterDecl = nodeFactory() .LocalDecl( pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, iterType), iterName, iterator); iterDecl = iterDecl.localInstance(iterLI); } // create the loop body List<Stmt> loopBody = new ArrayList<Stmt>(); { Id id = nodeFactory().Id(pos, "next"); Call call = nodeFactory() .Call( pos, ((Local) nodeFactory().Local(pos, iterName).type(iterType)) .localInstance(iterDecl.localInstance()), id); call = (Call) call.type(ts.Object()); call = call.methodInstance( ts.findMethod( iterType.toClass(), "next", Collections.<Type>emptyList(), this.context().currentClass())); Cast cast = nodeFactory().Cast(pos, nodeFactory().CanonicalTypeNode(pos, iteratedType), call); cast = (Cast) cast.type(iteratedType); loopBody.add(n.decl().init(cast)); loopBody.add(n.body()); } // create the while loop While loop; { Id id = nodeFactory().Id(pos, "hasNext"); Call cond = nodeFactory() .Call( pos, ((Local) nodeFactory().Local(pos, iterName).type(iterType)) .localInstance(iterDecl.localInstance()), id); cond = (Call) cond.type(ts.Boolean()); cond = cond.methodInstance( ts.findMethod( iterType.toClass(), "hasNext", Collections.<Type>emptyList(), this.context().currentClass())); loop = nodeFactory().While(pos, cond, nodeFactory().Block(pos, loopBody)); } return nodeFactory().Block(pos, iterDecl, labelStmt(loop, labels)); }
private Node translateExtForArray(ExtendedFor n, List<String> labels) throws SemanticException { Position pos = Position.compilerGenerated(); Type iteratedType = n.decl().type().type(); // translate "L1,...,Ln: for (C x: e) b" to // "{ C[] arr = e; int iter = 0; L1,...,Ln: while (iter < arr.length) { C x = arr[iter]; b ; // iter = iter + 1; }" List<Stmt> stmts = new ArrayList<Stmt>(); // add the declaration of arr: "C[] arr = e" Id arrID = freshName("arr"); LocalInstance arrLI = ts.localInstance(pos, Flags.NONE, n.expr().type(), arrID.id()); { LocalDecl ld = nodeFactory() .LocalDecl( pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, arrLI.type()), arrID); ld = ld.localInstance(arrLI); ld = ld.init(n.expr()); stmts.add(ld); } // add the declaration of iterator: "int iter = 0" Id iterID = freshName("iter"); LocalInstance iterLI = ts.localInstance(pos, Flags.NONE, ts.Int(), iterID.id()); { LocalDecl ld = nodeFactory() .LocalDecl( pos, Flags.NONE, nodeFactory().CanonicalTypeNode(pos, iterLI.type()), iterID); ld = ld.localInstance(iterLI); ld = ld.init(nodeFactory().IntLit(pos, IntLit.INT, 0).type(ts.Int())); stmts.add(ld); } // build the conditional "iter < arr.length" Expr cond; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Local arrLocal = (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type()); Id id = nodeFactory().Id(pos, "length"); Field field = (Field) nodeFactory().Field(pos, arrLocal, id).type(ts.Int()); field = field.fieldInstance(ts.findField(arrLI.type().toReference(), "length")); cond = nodeFactory().Binary(pos, iterLocal, Binary.LT, field).type(ts.Boolean()); } // build the initlizer for the local decl: arr[iter] Expr init; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Local arrLocal = (Local) nodeFactory().Local(pos, arrID).localInstance(arrLI).type(arrLI.type()); init = nodeFactory().ArrayAccess(pos, arrLocal, iterLocal); init = init.type(iteratedType); } // build the increment for iter (iter = iter + 1;) Stmt inc; { Local iterLocal = (Local) nodeFactory().Local(pos, iterID).localInstance(iterLI).type(ts.Int()); Expr incExpr = nodeFactory() .Binary( pos, iterLocal.type(ts.Int()), Binary.ADD, nodeFactory().IntLit(pos, IntLit.INT, 1).type(ts.Int())) .type(ts.Int()); Assign incStore = (Assign) nodeFactory().Assign(pos, iterLocal, Assign.ASSIGN, incExpr).type(ts.Int()); inc = nodeFactory().Eval(pos, incStore); } // build the while loop { // Create a new loop body from the old body followed by the increment Block loopBody = nodeFactory().Block(pos, n.decl().init(init), n.body(), inc); While loop = nodeFactory().While(pos, cond, loopBody); stmts.add(labelStmt(loop, labels)); } return nodeFactory().Block(pos, stmts); }
private boolean expectsBoxed(LocalDecl decl) { return isBoxedType(decl.declType()); }