2019-07-28 23:53:15 +03:00
|
|
|
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
2017-02-19 16:29:24 +03:00
|
|
|
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
|
|
|
|
|
using System;
|
2017-01-20 19:56:43 +03:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
|
|
using PascalABCCompiler.SyntaxTree;
|
|
|
|
|
|
|
|
|
|
|
|
namespace SyntaxVisitors.SugarVisitors
|
|
|
|
|
|
{
|
2017-01-26 15:47:13 +03:00
|
|
|
|
public class SliceDesugarVisitor : BaseChangeVisitor
|
2017-01-20 19:56:43 +03:00
|
|
|
|
{
|
2017-01-26 15:47:13 +03:00
|
|
|
|
public static SliceDesugarVisitor New
|
2017-01-20 19:56:43 +03:00
|
|
|
|
{
|
2017-01-26 15:47:13 +03:00
|
|
|
|
get { return new SliceDesugarVisitor(); }
|
2017-01-20 19:56:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
expression_list construct_expression_list_for_slice_expr(slice_expr sl)
|
|
|
|
|
|
{
|
|
|
|
|
|
// situation = 0 - ничего не пропущено
|
|
|
|
|
|
// situation = 1 - пропущен from
|
|
|
|
|
|
// situation = 2 - пропущен to
|
|
|
|
|
|
// situation = 3 - пропущены from и to
|
|
|
|
|
|
// Пропущенность кодируется тем, что в соответствующем поле - int.MaxValue
|
|
|
|
|
|
// step может просто отсутствовать - это параметр по умолчанию в SystemSlice
|
|
|
|
|
|
|
|
|
|
|
|
int situation = 0;
|
2020-05-02 11:44:20 +03:00
|
|
|
|
var fromInverted = false;
|
|
|
|
|
|
var fromExpr = sl.from;
|
2017-01-20 19:56:43 +03:00
|
|
|
|
|
2020-05-02 11:44:20 +03:00
|
|
|
|
if (sl.from is index fromInd)
|
|
|
|
|
|
{
|
|
|
|
|
|
fromInverted = fromInd.inverted;
|
|
|
|
|
|
fromExpr = fromInd.index_expr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var toInverted = false;
|
|
|
|
|
|
var toExpr = sl.to;
|
|
|
|
|
|
if (sl.to is index toInd)
|
|
|
|
|
|
{
|
|
|
|
|
|
toInverted = toInd.inverted;
|
|
|
|
|
|
toExpr = toInd.index_expr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((fromExpr is int32_const) && (fromExpr as int32_const).val == int.MaxValue)
|
2017-01-20 19:56:43 +03:00
|
|
|
|
situation += 1;
|
2020-05-02 11:44:20 +03:00
|
|
|
|
if ((toExpr is int32_const) && (toExpr as int32_const).val == int.MaxValue)
|
2017-01-20 19:56:43 +03:00
|
|
|
|
situation += 2;
|
|
|
|
|
|
|
|
|
|
|
|
var el = new expression_list();
|
|
|
|
|
|
el.Add(new int32_const(situation));
|
2020-05-02 11:44:20 +03:00
|
|
|
|
el.Add(sl.from);
|
|
|
|
|
|
// Это плохо - считается 2 раза. Надо делать semantic_expr_node !!!? Нет!!!
|
|
|
|
|
|
// Если там будет лямбда, то не будет работать - известно, что semantic_expr_node не работает с лямбдами
|
|
|
|
|
|
// т.к. они несколько раз обходят код.
|
2017-01-20 19:56:43 +03:00
|
|
|
|
el.Add(sl.to);
|
|
|
|
|
|
if (sl.step != null)
|
|
|
|
|
|
el.Add(sl.step);
|
|
|
|
|
|
return el;
|
|
|
|
|
|
}
|
2020-05-05 18:58:06 +03:00
|
|
|
|
|
|
|
|
|
|
/*
|
2020-05-02 11:44:20 +03:00
|
|
|
|
public override void Exit(syntax_tree_node st)
|
2020-04-03 11:48:15 +03:00
|
|
|
|
{
|
2020-05-02 11:44:20 +03:00
|
|
|
|
if (st is slice_expr_question)
|
|
|
|
|
|
{
|
|
|
|
|
|
ProceedSliceQuestionExpr(st as slice_expr_question);
|
|
|
|
|
|
} else if (st is slice_expr)
|
2020-04-03 11:48:15 +03:00
|
|
|
|
{
|
2020-05-02 11:44:20 +03:00
|
|
|
|
ProceedSliceExpr(st as slice_expr);
|
2020-04-03 11:48:15 +03:00
|
|
|
|
}
|
2020-05-05 18:58:06 +03:00
|
|
|
|
}*/
|
|
|
|
|
|
|
2020-05-02 11:44:20 +03:00
|
|
|
|
public override void visit(assign _assign)
|
|
|
|
|
|
{
|
2020-05-05 18:58:06 +03:00
|
|
|
|
_assign.from.visit(this);
|
|
|
|
|
|
_assign.to.visit(this);
|
2020-05-02 11:44:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-05 18:58:06 +03:00
|
|
|
|
public override void visit(slice_expr sl)
|
2017-01-21 00:33:12 +03:00
|
|
|
|
{
|
|
|
|
|
|
var el = construct_expression_list_for_slice_expr(sl);
|
2019-12-27 10:23:08 +03:00
|
|
|
|
if (sl.Parent is assign parent_assign && parent_assign.to == sl)
|
|
|
|
|
|
{
|
|
|
|
|
|
el.Insert(0, parent_assign.from);
|
2020-03-19 12:43:07 +03:00
|
|
|
|
var mc = method_call.NewP(
|
2019-12-27 10:23:08 +03:00
|
|
|
|
dot_node.NewP(
|
|
|
|
|
|
sl.v,
|
|
|
|
|
|
new ident("SystemSliceAssignment", sl.v.source_context),
|
|
|
|
|
|
sl.v.source_context),
|
2020-03-19 12:43:07 +03:00
|
|
|
|
el, sl.source_context);
|
|
|
|
|
|
var systemSliceAssignmentCall = new procedure_call(mc, sl.source_context);
|
|
|
|
|
|
var typeCompatibilityCheck = GetAssignmentTypeCompatibilityCheck(sl, parent_assign.from, mc);
|
2019-12-27 10:23:08 +03:00
|
|
|
|
var checkAndDesugaredSliceBlock = new statement_list(typeCompatibilityCheck, systemSliceAssignmentCall);
|
|
|
|
|
|
checkAndDesugaredSliceBlock.source_context = sl.source_context;
|
|
|
|
|
|
ReplaceUsingParent(parent_assign, checkAndDesugaredSliceBlock);
|
2020-03-19 12:43:07 +03:00
|
|
|
|
visit(systemSliceAssignmentCall); // обойти заменённое на предмет наличия такого же синтаксического сахара
|
2019-12-27 10:23:08 +03:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var mc = method_call.NewP(dot_node.NewP(sl.v, new ident("SystemSlice", sl.v.source_context), sl.v.source_context), el, sl.source_context);
|
|
|
|
|
|
var sug = sugared_addressed_value.NewP(sl, mc, sl.source_context);
|
|
|
|
|
|
ReplaceUsingParent(sl, sug);
|
|
|
|
|
|
visit(mc); // обойти заменённое на предмет наличия такого же синтаксического сахара
|
|
|
|
|
|
}
|
2017-01-21 00:33:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-05 18:58:06 +03:00
|
|
|
|
public override void visit(slice_expr_question sl)
|
2017-01-20 19:56:43 +03:00
|
|
|
|
{
|
2020-03-19 12:43:07 +03:00
|
|
|
|
if (sl.Parent is assign parent_assign && parent_assign.to == sl)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new SyntaxVisitorError("CAN_NOT_ASSIGN_TO_LEFT_PART", sl.source_context);
|
|
|
|
|
|
}
|
2017-01-20 19:56:43 +03:00
|
|
|
|
var el = construct_expression_list_for_slice_expr(sl);
|
2017-02-06 11:02:42 +03:00
|
|
|
|
var mc = method_call.NewP(dot_node.NewP(sl.v, new ident("SystemSliceQuestion", sl.v.source_context), sl.v.source_context), el, sl.source_context);
|
|
|
|
|
|
var sug = sugared_addressed_value.NewP(sl, mc, sl.source_context);
|
2017-01-21 00:33:12 +03:00
|
|
|
|
ReplaceUsingParent(sl, sug);
|
2017-01-20 19:56:43 +03:00
|
|
|
|
visit(mc); // обойти заменённое на предмет наличия такого же синтаксического сахара
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-19 12:43:07 +03:00
|
|
|
|
private semantic_check_sugared_statement_node GetAssignmentTypeCompatibilityCheck(expression expression1, expression expression2, expression expression3) =>
|
|
|
|
|
|
new semantic_check_sugared_statement_node(SemanticCheckType.SliceAssignmentTypeCompatibility, new List<syntax_tree_node>() { expression1, expression2, expression3 });
|
2017-01-20 19:56:43 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|