예제 #1
0
        // frninja 21/05/16
        public override void visit(foreach_stmt frch)
        {
            // Полный код Loweringа c yield_unknown_foreach_type = integer
            //  var a: System.Collections.Generic.IEnumerable<integer>;
            //  a := l;
            //  var en := a.GetEnumerator();
            //  while en.MoveNext do
            //  begin
            //    var curr := en.Current; // var не нужно ставить если curr была описана раньше
            //    Print(curr);
            //  end;
            ///

            // var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l;
            var foreachCollIdent = this.NewForeachCollectionName();
            var foreachCollType  = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"),
                                                               new template_param_list(new yield_unknown_foreach_type(frch)));
            var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType);

            var ass = new assign(foreachCollIdent, frch.in_what);

            //  var en := a.GetEnumerator();
            var enumeratorIdent  = this.NewEnumeratorName();
            var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list()));

            //var curr := en.Current;
            // Переменная цикла foreach. Есть три варианта:
            // 1. foreach x in l do           ->    curr := en.Current;
            // 2. foreach var x in l do       ->    var curr := en.Current;
            // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            var       currentIdent = frch.identifier;
            statement st           = null;

            var curExpr = new dot_node(enumeratorIdent, "Current");

            // С типом
            if (frch.type_name == null) // 1. foreach x in l do   ->   curr := en.Current;
            {
                st = new assign(currentIdent, curExpr);
            }
            else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do    ->    var curr := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, curExpr);
            }
            else // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, frch.type_name, curExpr);
            }

            // Добавляем тело цикла в stl
            var stl = new statement_list(st);

            ProcessNode(frch.stmt); // для обработки вложенных конструкций
            stl.Add(frch.stmt);

            var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
                                           stl,
                                           WhileCycleType.While);

            var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode);

            ReplaceStatement(frch, sq);

            visit(whileNode); // Lowering оставшегося whileNode
        }
예제 #2
0
        public override void visit(for_node fn)
        {
            var b = HasStatementVisitor <yield_node> .Has(fn);

            if (!b)
            {
                return;
            }

            var gotoContinue = goto_statement.New;
            var gotoBreak    = goto_statement.New;
            var gotoStart    = goto_statement.New;

            ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);

            fn.statements.visit(replaceBreakContinueVis);

            ProcessNode(fn.statements);

            var newNames = this.NewVarNames(fn.loop_variable);

            var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;

            // Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
            var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);

            fn.visit(replacerVis);

            fn.loop_variable = newLoopVar;

            var endtemp = new ident(newNames.VarEndName); //new ident(newVarName());

            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);

            // frninja 05/06/16 - фиксим для !fn.create_variable
            var ass1 = fn.create_loop_variable
                ? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement
                : new assign(fn.loop_variable, fn.initial_value) as statement;


            var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ?
                                  bin_expr.Greater(fn.loop_variable, fn.finish_value) :
                                  bin_expr.Less(fn.loop_variable, fn.finish_value), gotoBreak);

            var lb2 = new labeled_statement(gotoStart.label, if0);
            var lb1 = new labeled_statement(gotoBreak.label);
            var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
                                                         new ident("Inc") :
                                                         new ident("Dec"), new expression_list(fn.loop_variable)));

            var lbInc = new labeled_statement(gotoContinue.label, Inc);

            ReplaceStatement(fn, SeqStatements(ass1, lb2, fn.statements, lbInc, gotoStart, lb1));

            // в declarations ближайшего блока добавить описание labels
            block bl = listNodes.FindLast(x => x is block) as block;

            bl.defs.Add(new label_definitions(gotoContinue.label, gotoBreak.label, gotoStart.label));
        }
예제 #3
0
        public override void visit(for_node fn)
        {
            var b = HasStatementVisitor<yield_node>.Has(fn);
            if (!b)
                return;

            var gotoContinue = goto_statement.New;
            var gotoBreak = goto_statement.New;
            var gotoStart = goto_statement.New;

            ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);
            fn.statements.visit(replaceBreakContinueVis);

            ProcessNode(fn.statements);

            var newNames = this.NewVarNames(fn.loop_variable);

            var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;

            // Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
            var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);
            fn.visit(replacerVis);

            fn.loop_variable = newLoopVar;

            var endtemp = new ident(newNames.VarEndName); //new ident(newVarName());

            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);

            // frninja 05/06/16 - фиксим для !fn.create_variable
            var ass1 = fn.create_loop_variable
                ? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement
                : new assign(fn.loop_variable, fn.initial_value) as statement;


            var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ?
                bin_expr.Greater(fn.loop_variable, fn.finish_value) :
                bin_expr.Less(fn.loop_variable, fn.finish_value), gotoBreak);

            var lb2 = new labeled_statement(gotoStart.label, if0);
            var lb1 = new labeled_statement(gotoBreak.label);
            var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
                new ident("Inc") :
                new ident("Dec"), new expression_list(fn.loop_variable)));

            var lbInc = new labeled_statement(gotoContinue.label, Inc);

            ReplaceStatement(fn, SeqStatements(ass1, lb2, fn.statements, lbInc, gotoStart, lb1));

            // в declarations ближайшего блока добавить описание labels
            block bl = listNodes.FindLast(x => x is block) as block;

            bl.defs.Add(new label_definitions(gotoContinue.label, gotoBreak.label, gotoStart.label));
        }
예제 #4
0
        // frninja 21/05/16
        public override void visit(foreach_stmt frch)
        {
            // Полный код Loweringа c yield_unknown_foreach_type = integer
            //  var a: System.Collections.Generic.IEnumerable<integer>;
            //  a := l;
            //  var en := a.GetEnumerator();
            //  while en.MoveNext do
            //  begin
            //    var curr := en.Current; // var не нужно ставить если curr была описана раньше
            //    Print(curr);
            //  end;
            ///

            // var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l;
            var foreachCollIdent = this.NewForeachCollectionName();
            var foreachCollType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"), 
                new template_param_list(new yield_unknown_foreach_type(frch)));
            var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType);
            
            var ass = new assign(foreachCollIdent, frch.in_what);

            //  var en := a.GetEnumerator();
            var enumeratorIdent = this.NewEnumeratorName();
            var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list()));

            //var curr := en.Current;
            // Переменная цикла foreach. Есть три варианта:
            // 1. foreach x in l do           ->    curr := en.Current;
            // 2. foreach var x in l do       ->    var curr := en.Current;
            // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            var currentIdent = frch.identifier;
            statement st = null;

            var curExpr = new dot_node(enumeratorIdent, "Current");

            // С типом
            if (frch.type_name == null) // 1. foreach x in l do   ->   curr := en.Current;
            {
                st = new assign(currentIdent, curExpr);
            }
            else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do    ->    var curr := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, curExpr);
            }
            else // 3. foreach var x: T in l do    ->    var curr: T := en.Current;
            {
                // Получаем служебное имя с $ и заменяем его в теле цикла
                currentIdent = this.NewVarNames(frch.identifier).VarName;
                var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
                frch.visit(replacerVis);

                st = new var_statement(currentIdent, frch.type_name, curExpr);
            }

            // Добавляем тело цикла в stl
            var stl = new statement_list(st);
            ProcessNode(frch.stmt); // для обработки вложенных конструкций
            stl.Add(frch.stmt);

            var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
                stl,
                WhileCycleType.While);

            var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode);

            ReplaceStatement(frch,sq);

            visit(whileNode); // Lowering оставшегося whileNode
        }
예제 #5
0
        public override void visit(for_node fn)
        {
            var b = HasStatementVisitor <yield_node> .Has(fn);

            if (!b)
            {
                return;
            }

            var gotoContinue = goto_statement.New;
            var gotoBreak    = goto_statement.New;
            var gotoStart    = goto_statement.New;

            ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);

            fn.statements.visit(replaceBreakContinueVis);

            ProcessNode(fn.statements);

            var newNames = this.NewVarNames(fn.loop_variable);

            var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;

            // Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
            var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);

            fn.visit(replacerVis);

            fn.loop_variable = newLoopVar;

            var endtemp = new ident(newNames.VarEndName); //new ident(newVarName());

            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
            //var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);

            // Исправления в связи с #1254 (новый алгоритм)
            // цикл for i:=a to b do
            //          i := a
            //          if i > b then goto break
            //Start:    stmts
            //          if i >= b then goto break
            //Continue: Inc(i)
            //          goto Start
            //Break:

            // цикл for i:=a downto b do
            //          i := a
            //          if i < b then goto break
            //Start:    stmts
            //          if i <= b then goto break
            //Continue: Dec(i)
            //          goto Start
            //Break:

            // frninja 05/06/16 - фиксим для !fn.create_variable
            var ass1 = fn.create_loop_variable
                ? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement
                : new assign(fn.loop_variable, fn.initial_value) as statement;

            var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ?
                                  bin_expr.Greater(fn.loop_variable, fn.finish_value) :
                                  bin_expr.Less(fn.loop_variable, fn.finish_value), gotoBreak);

            var if1 = new if_node((fn.cycle_type == for_cycle_type.to) ?
                                  bin_expr.GreaterEqual(fn.loop_variable, fn.finish_value) :
                                  bin_expr.LessEqual(fn.loop_variable, fn.finish_value), gotoBreak);

            var lb1 = new labeled_statement(gotoStart.label);
            var lb2 = new labeled_statement(gotoBreak.label); // пустой оператор
            var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
                                                         new ident("Inc") :
                                                         new ident("Dec"), new expression_list(fn.loop_variable)));

            var lbInc = new labeled_statement(gotoContinue.label, Inc);

            ReplaceStatement(fn, SeqStatements(ass1, if0, lb1, fn.statements, if1, lbInc, gotoStart, lb2));

            /*var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ?
             *  bin_expr.Greater(fn.loop_variable, fn.finish_value) :
             *  bin_expr.Less(fn.loop_variable, fn.finish_value), gotoBreak);
             *
             * var lb2 = new labeled_statement(gotoStart.label, if0);
             * var lb1 = new labeled_statement(gotoBreak.label); // пустой оператор
             * var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
             *  new ident("Inc") :
             *  new ident("Dec"), new expression_list(fn.loop_variable)));
             *
             * var lbInc = new labeled_statement(gotoContinue.label, Inc);
             *
             * ReplaceStatement(fn, SeqStatements(ass1, lb2, fn.statements, lbInc, gotoStart, lb1));*/

            // в declarations ближайшего блока добавить описание labels
            block bl = listNodes.FindLast(x => x is block) as block;

            bl.defs.Add(new label_definitions(gotoContinue.label, gotoBreak.label, gotoStart.label));
        }