/** @{inheritDoc} */ @Override public void visit(final Factor n) { if (n.getOperand() instanceof Identifier) { final Identifier id = (Identifier) n.getOperand(); if (id.getToken().equals("visit")) { final Call c = (Call) n.getOp(0); if (c.getArgsSize() == 1) { c.addArg(ASTFactory.createFactorExpr(original.clone())); return; } } } super.visit(n); }
/** @{inheritDoc} */ @SuppressWarnings("unchecked") @Override public void visit(VisitorExpression n) { int wildcardStop = 0; final Map<BoaProtoTuple, Integer> beforeStopTypes = new HashMap<BoaProtoTuple, Integer>(); final Map<VisitStatement, Integer> bodyMap = new HashMap<VisitStatement, Integer>(); original = n.clone(); // // 1) convert all self-visit() calls to pass in copy of the original visitor // transformSelfVisits.start(n.getBody()); // // 2) add a long var declaration to the enclosing scope // n.insertStatementBefore( new VarDeclStatement( new Identifier(varCounterName), new Identifier("int"), ASTFactory.createFactorExpr(new IntegerLiteral("0")))); // // 3) find all visit statements containing stop statements, for each one: // stopFinder.start(n.getBody()); for (final VisitStatement v : stopFinder.getVisits()) { // // a) lift the body into a new function in the surrounding scope // final FunctionType funcType = new FunctionType(); final String funcName; if (v.hasComponent()) { funcType.addArg(v.getComponent().clone()); funcName = funcWithVisitorId + ++counter; } else { funcName = funcId + ++counter; } final Block funcBody = v.getBody().clone(); final VarDeclStatement var = new VarDeclStatement( new Identifier(funcName), ASTFactory.createFactorExpr(new FunctionExpression(funcType, funcBody))); n.insertStatementBefore(var); // // i) replace all stop statements with incrementing long var and a return statement // transformStops.start(funcBody); // // b) replace the body with a call to the function // final Call c2 = new Call(); if (funcType.getArgsSize() > 0) c2.addArg(ASTFactory.createFactorExpr(funcType.getArg(0).getIdentifier().clone())); final Factor f2 = new Factor(new Identifier(funcName)); f2.addOp(c2); v.setBody( new Block() .addStatement( new ExprStatement( new Expression( new Conjunction(new Comparison(new SimpleExpr(new Term(f2)))))))); bodyMap.put(v, counter); if (v.hasWildcard()) wildcardStop = counter; else if (v.hasComponent()) beforeStopTypes.put((BoaProtoTuple) v.getComponent().type, counter); else for (final Identifier id : v.getIdList()) beforeStopTypes.put((BoaProtoTuple) id.type, counter); } final Set<BoaProtoTuple> keys = new HashSet<BoaProtoTuple>(beforeStopTypes.keySet()); final Set<BoaProtoTuple> remainingAfters = new HashSet<BoaProtoTuple>(keys); // // 4) find all after visits matching the visited node types in step 1, for each one: // visitClassifier.start(n.getBody()); for (final VisitStatement v : visitClassifier.getAfters()) { final Set<BoaProtoTuple> types = new HashSet<BoaProtoTuple>(); if (v.hasComponent()) types.add((BoaProtoTuple) v.getComponent().getType().type); else for (final Identifier id : v.getIdList()) types.add((BoaProtoTuple) id.type); final Set<Integer> intersection = new HashSet<Integer>(); for (final BoaProtoTuple t : keys) if (types.contains(t)) intersection.add(beforeStopTypes.get(t)); if (wildcardStop > 0 && v.hasWildcard()) intersection.add(wildcardStop); if (intersection.isEmpty()) continue; remainingAfters.removeAll(types); // // a) wrap body in an "if (stop == 0)" guard // addGuard(v); // // b) add code "if (stop > 0) stop--;", after ALL if() blocks // createReset(v.getBody()); } // // 5) for any node type matching the visited node types in step 1 not found in step 2: // for (final BoaProtoTuple t : remainingAfters) { // // a) add an after visit for that type // final Block body = new Block(); n.getBody() .addStatement( new VisitStatement( false, new Component(new Identifier("n"), new Identifier(t.toString())), body)); // // b) add code "if (stop > 0) stop--;" // createReset(body); } if (wildcardStop > 0 && !visitClassifier.hasDefaultAfter()) { final Block body = new Block(); n.getBody().addStatement(new VisitStatement(false, true, body)); createReset(body); } // // 6) wrap default before visit body in an "if (stop == 0)" guard // if (visitClassifier.hasDefaultBefore()) addGuard(visitClassifier.getDefaultBefore()); // // 7) find all before/after visits with a node type below a node type found in step 1, for each // one: // for (final BoaProtoTuple t : beforeStopTypes.keySet()) { final List<VisitStatement> statements = new ArrayList<VisitStatement>(visitClassifier.getBefores()); statements.addAll(visitClassifier.getAfters()); for (final VisitStatement v : statements) { final Set<Class<? extends BoaProtoTuple>> types = new HashSet<Class<? extends BoaProtoTuple>>(); if (v.hasComponent()) types.add((Class<? extends BoaProtoTuple>) v.getComponent().getType().type.getClass()); else for (final Identifier id : v.getIdList()) types.add((Class<? extends BoaProtoTuple>) id.type.getClass()); types.retainAll(t.reachableTypes()); if (types.isEmpty()) continue; // // a) add code "if (stop > 0) stop--;", after ALL if() blocks // // FIXME the nesting makes for more than 1 guard addGuard(v); } } // c) add code "if (stop > 0) stop++;" to the START of the new body for (final VisitStatement v : bodyMap.keySet()) v.getBody() .getStatements() .add( 0, new IfStatement( ASTFactory.createComparison( new Identifier(varCounterName), ">", new IntegerLiteral("0")), new Block() .addStatement( new PostfixStatement( ASTFactory.createFactorExpr(new Identifier(varCounterName)), "++")))); }
public AssignmentStatement clone() { final AssignmentStatement s = new AssignmentStatement(lhs.clone(), rhs.clone()); copyFieldsTo(s); return s; }
public AssignmentStatement(final Factor lhs, final Expression rhs) { if (lhs != null) lhs.setParent(this); if (rhs != null) rhs.setParent(this); this.lhs = lhs; this.rhs = rhs; }