// Only have if, switch, cil, continuation, try - no other type of statement
        // Blocks will only start with cil or try
        // Will end with null, if, switch or continuation
        // If ending in 'if', 'then' and 'else' will both have continuations only
        // 'try' statements will have only 0 or 1 catch clauses

        public static ICode V(ICode ast) {
            var v = new VisitorConvertCilToSsa(ast);
            ast = v.Visit(ast);
            foreach (var instResult in v.instResults.Values) {
                var var = new ExprVarLocal(ast.Ctx, instResult.Type);
                ast = VisitorReplace.V(ast, instResult, var);
            }
            return ast;
        }
 private Expr ConvertToBoolean(Expr e) {
     if (e.ExprType == Expr.NodeType.Literal) {
         var eLiteral = (ExprLiteral)e;
         if (eLiteral.Type.IsInt32()) {
             return new ExprLiteral(e.Ctx, ((int)eLiteral.Value) != 0 ? true : false, e.Ctx.Boolean);
         }
     }
     if (e.ExprType == Expr.NodeType.VarLocal) {
         var var = new ExprVarLocal(e.Ctx, e.Ctx.Boolean);
         this.toReplace.Add((ExprVarLocal)e, var);
         return var;
     }
     throw new InvalidOperationException();
 }
        public void Test() {
            var exprGen = Ctx.ExprGen;
            Expr e;
            IEnumerable<Expr> perms;
            var a = new ExprVarLocal(Ctx, null, "a");
            var b = new ExprVarLocal(Ctx, null, "b");
            var c = new ExprVarLocal(Ctx, null, "c");
            var d = new ExprVarLocal(Ctx, null, "d");

            e = exprGen.And(a, b);
            perms = VisitorCreatePerms.V(e);
            Assert.That(perms, Is.Unique);
            Assert.That(perms, Is.EquivalentTo(
                new[] { exprGen.And(a, b), exprGen.And(b, a) }
                ).Using(Expr.EqComparerExact));

            e = exprGen.And(a, exprGen.Or(a, b));
            perms = VisitorCreatePerms.V(e);
            Assert.That(perms, Is.Unique);
            Assert.That(perms, Is.EquivalentTo(
                new[] {
                    exprGen.And(a, exprGen.Or(a, b)), exprGen.And(a, exprGen.Or(b, a)),
                    exprGen.And(exprGen.Or(a, b), a), exprGen.And(exprGen.Or(b, a), a)
                }
                ).Using(Expr.EqComparerExact));

            e = exprGen.And(exprGen.Or(a, b), exprGen.Or(c, d));
            perms = VisitorCreatePerms.V(e);
            Assert.That(perms, Is.Unique);
            Assert.That(perms, Is.EquivalentTo(
                new[]{
                    exprGen.And(exprGen.Or(a, b), exprGen.Or(c, d)), exprGen.And(exprGen.Or(c, d), exprGen.Or(a, b)),
                    exprGen.And(exprGen.Or(b, a), exprGen.Or(c, d)), exprGen.And(exprGen.Or(c, d), exprGen.Or(b, a)),
                    exprGen.And(exprGen.Or(a, b), exprGen.Or(d, c)), exprGen.And(exprGen.Or(d, c), exprGen.Or(a, b)),
                    exprGen.And(exprGen.Or(b, a), exprGen.Or(d, c)), exprGen.And(exprGen.Or(d, c), exprGen.Or(b, a)),
                }
                ).Using(Expr.EqComparerExact));
        }
 protected override ICode VisitVarLocal(ExprVarLocal e) {
     this.code.Append(e.ToString());
     return e;
 }
 public ExprJsByRefWrapper(Ctx ctx, Expr expr, ExprVarLocal resultTemp, IEnumerable<Tuple<Expr, Expr>> byRefs)
     : base(ctx) {
     this.Expr = expr;
     this.ResultTemp = resultTemp;
     this.ByRefs = byRefs;
 }
 private Stmt SsaLocalAssignment(Expr expr) {
     if (expr.Type == null) {
         Debugger.Break();
     }
     var target = new ExprVarLocal(this.ctx, expr.Type);
     var assignment = new StmtAssignment(this.ctx, target, expr);
     this.stack.Push(target);
     return assignment;
 }
 private Stmt StLoc(int idx) {
     var expr = this.InsertConvIfRequired(this.stack.Pop(), this.localTypes[idx]);
     var target = new ExprVarLocal(this.ctx, expr.Type);
     var assignment = new StmtAssignment(this.ctx, target, expr);
     this.locals[idx] = target;
     return assignment;
 }
 private Stmt StArg(int idx) {
     var expr = this.stack.Pop();
     var target = new ExprVarLocal(this.ctx, expr.Type);
     var assignment = new StmtAssignment(this.ctx, target, expr);
     this.args[idx] = target;
     return assignment;
 }