pascalabcnet/SyntaxVisitors/SugarVisitors/NewRangeDesugarVisitor.cs
Mikhalkovich Stanislav 228c9f9aac fix #2204
Изменение реализации range на InternalRange и IntRange CharRange

Правки в AutoInsertCode.cs

IntRange и CharRange в PABCSystem.pas - аналогично Котлину
2020-02-14 19:47:41 +03:00

101 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
{
public class NewRangeDesugarVisitor : BaseChangeVisitor
{
public static NewRangeDesugarVisitor New
{
get { return new NewRangeDesugarVisitor(); }
}
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!
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);
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)
{
if (fe.in_what is diapason_expr_new diap)
{
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);
visit(fn);
}
else if (fe.in_what is dot_node dn && dn.right is ident id && id.name.ToLower() == "indices")
{
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);
var right = dn.left.dot_node("Count").Minus(1); // Строки таким образом сделать не получится. Разве что в семантическом контроле чуть довернуть этот узел ))
var fn = new for_node(fe.identifier, left, right, fe.stmt, for_cycle_type.to, null, typ, cr);
var sl = new List<statement>();
sl.Add(new semantic_check_sugared_statement_node(typeof(foreach_stmt), new List<syntax_tree_node> { dn.left }, fe.source_context));
sl.Add(fn);
ReplaceStatementUsingParent(fe, sl);
visit(fn);
}
else base.visit(fe);
}
}
}