2020-01-05 22:46:12 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using PascalABCCompiler.SyntaxTree ;
namespace SyntaxVisitors.SugarVisitors
{
2020-01-06 11:23:55 +03:00
2020-07-11 17:11:27 +03:00
public class NewRangeDesugarAndFindHasYieldVisitor : BaseChangeVisitor
2020-01-05 22:46:12 +03:00
{
2020-07-11 17:11:27 +03:00
public static NewRangeDesugarAndFindHasYieldVisitor New
2020-01-05 22:46:12 +03:00
{
2020-07-11 17:11:27 +03:00
get { return new NewRangeDesugarAndFindHasYieldVisitor ( ) ; }
2020-01-05 22:46:12 +03:00
}
public override void visit ( diapason_expr_new diap )
{
if ( diap . Parent . Parent is pascal_set_constant )
{
// вернуть назад к diapason_expr
var d = new diapason_expr ( diap . left , diap . right , diap . source_context ) ;
ReplaceUsingParent ( diap , d ) ;
visit ( d ) ;
return ;
}
var el = new expression_list ( ) ;
el . Add ( diap . left , diap . left . source_context ) ;
el . Add ( diap . right , diap . right . source_context ) ;
// Проблема в том, что тут тоже надо перепрошивать Parent!
2020-02-14 19:47:41 +03:00
var mc = method_call . NewP ( dot_node . NewP ( new ident ( "PABCSystem" , diap . source_context ) , new ident ( "InternalRange" , diap . source_context ) , diap . source_context ) , el , diap . source_context ) ;
2020-01-05 22:46:12 +03:00
var sug = sugared_addressed_value . NewP ( diap , mc , diap . source_context ) ;
ReplaceUsingParent ( diap , sug ) ;
visit ( mc ) ; // обойти заменённое на предмет наличия такого же синтаксического с а х а р а
}
public override void visit ( bin_expr ex )
{
if ( ex . operation_type = = Operators . In & & ex . right is diapason_expr_new diap & & ex . left is addressed_value exl )
{
var el = new expression_list ( ) ;
el . Add ( exl , exl . source_context ) ;
el . Add ( diap . left , diap . left . source_context ) ;
el . Add ( diap . right , diap . right . source_context ) ;
var mc = method_call . NewP ( new ident ( "InRangeInternal" , exl . source_context ) , el , exl . source_context ) ;
var sug = sugared_addressed_value . NewP ( ex , mc , ex . source_context ) ;
ReplaceUsingParent ( ex , sug ) ;
visit ( mc ) ; // обойти заменённое на предмет наличия такого же синтаксического с а х а р а
}
else base . visit ( ex ) ;
}
public override void visit ( foreach_stmt fe )
{
2022-03-08 21:41:46 +03:00
if ( fe . in_what is diapason_expr_new diap & & fe . index = = null )
2020-01-05 22:46:12 +03:00
{
var from = diap . left ;
var typ = fe . type_name ;
if ( typ ! = null & & typ is no_type_foreach )
typ = null ;
var cr = fe . type_name is no_type_foreach ;
var fn = new for_node ( fe . identifier , diap . left , diap . right , fe . stmt , for_cycle_type . to , null , typ , cr ) ;
var sl = new List < statement > ( ) ;
// надо проверить типы в диапазоне. Проверять соответствие типа переменной foreach возможно не надо - сообщение о б ошибке и так будет хорошим. Посмотрим
sl . Add ( new semantic_check_sugared_statement_node ( typeof ( foreach_stmt ) , new List < syntax_tree_node > { diap , fe . type_name , fe . identifier } , fe . source_context ) ) ;
sl . Add ( fn ) ;
ReplaceStatementUsingParent ( fe , sl ) ;
2020-01-06 12:14:53 +03:00
visit ( fn ) ;
2020-01-05 22:46:12 +03:00
}
2020-06-12 23:31:38 +03:00
/ * else if ( fe . in_what is dot_node dn & & dn . right is ident id & & id . name . ToLower ( ) = = "indices" )
2020-01-06 00:55:40 +03:00
{
var typ = fe . type_name ;
if ( typ ! = null & & typ is no_type_foreach )
typ = null ;
var cr = fe . type_name is no_type_foreach ;
var left = new int32_const ( 0 , fe . identifier . source_context ) ;
2020-01-06 11:23:55 +03:00
var right = dn . left . dot_node ( "Count" ) . Minus ( 1 ) ; // Строки таким образом сделать не получится. Разве что в семантическом контроле чуть довернуть этот узел ))
2020-01-06 00:55:40 +03:00
var fn = new for_node ( fe . identifier , left , right , fe . stmt , for_cycle_type . to , null , typ , cr ) ;
var sl = new List < statement > ( ) ;
2020-01-06 12:14:53 +03:00
sl . Add ( new semantic_check_sugared_statement_node ( typeof ( foreach_stmt ) , new List < syntax_tree_node > { dn . left } , fe . source_context ) ) ;
2020-01-06 00:55:40 +03:00
sl . Add ( fn ) ;
ReplaceStatementUsingParent ( fe , sl ) ;
2020-01-06 12:14:53 +03:00
visit ( fn ) ;
2020-06-12 23:31:38 +03:00
} * /
2020-01-05 22:46:12 +03:00
else base . visit ( fe ) ;
}
2020-07-11 17:11:27 +03:00
List < procedure_definition > lpd = new List < procedure_definition > ( ) ;
public override void visit ( procedure_definition pd )
{
lpd . Add ( pd ) ;
base . visit ( pd ) ;
lpd . RemoveAt ( lpd . Count - 1 ) ;
}
public override void visit ( yield_node yn )
{
if ( lpd . Count > 0 )
lpd [ lpd . Count - 1 ] . has_yield = true ;
base . visit ( yn ) ;
}
public override void visit ( yield_sequence_node yn )
{
if ( lpd . Count > 0 )
lpd [ lpd . Count - 1 ] . has_yield = true ;
base . visit ( yn ) ;
}
2020-01-05 22:46:12 +03:00
}
}