// 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 }
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)); }
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)); }
// 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 }
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)); }