2021-03-08 00:00:59 +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.Collections.Generic;
|
|
|
|
|
|
|
2026-03-08 18:30:33 +03:00
|
|
|
|
using PascalABCCompiler.CoreUtils;
|
2021-03-08 00:00:59 +03:00
|
|
|
|
using PascalABCCompiler.SyntaxTree;
|
|
|
|
|
|
|
|
|
|
|
|
namespace SyntaxVisitors.SugarVisitors
|
|
|
|
|
|
{
|
|
|
|
|
|
public class UnpackLambdaParametersVisitor : BaseChangeVisitor
|
|
|
|
|
|
{
|
2026-03-08 18:30:33 +03:00
|
|
|
|
private readonly GeneratedNamesManager generatedNamesManager;
|
2021-03-08 00:00:59 +03:00
|
|
|
|
|
2026-03-08 18:30:33 +03:00
|
|
|
|
private UnpackLambdaParametersVisitor(GeneratedNamesManager generatedNamesManager)
|
2021-03-08 00:00:59 +03:00
|
|
|
|
{
|
2026-03-08 18:30:33 +03:00
|
|
|
|
this.generatedNamesManager = generatedNamesManager;
|
2021-03-08 00:00:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-08 18:30:33 +03:00
|
|
|
|
public static UnpackLambdaParametersVisitor Create(GeneratedNamesManager generatedNamesManager) => new UnpackLambdaParametersVisitor(generatedNamesManager);
|
|
|
|
|
|
|
2021-03-08 00:00:59 +03:00
|
|
|
|
public ident CreateIdent(SourceContext sc)
|
|
|
|
|
|
{
|
2026-03-08 18:30:33 +03:00
|
|
|
|
return new ident(generatedNamesManager.GenerateName("#fpl"), sc);
|
2021-03-08 00:00:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-26 00:12:48 +03:00
|
|
|
|
public void CreateUnpackedListOfAssignments(unpacked_list_of_ident_or_list ll, List<statement> res, ident prevname, SourceContext sc)
|
2021-03-08 00:00:59 +03:00
|
|
|
|
{
|
|
|
|
|
|
var idlist = new ident_list();
|
2021-03-26 00:12:48 +03:00
|
|
|
|
foreach (var llelem in ll.lst)
|
2021-03-08 00:00:59 +03:00
|
|
|
|
{
|
|
|
|
|
|
if (llelem.lst != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var id = CreateIdent(sc);
|
|
|
|
|
|
// надо у этого id установить souce_context
|
|
|
|
|
|
idlist.Add(id);
|
|
|
|
|
|
CreateUnpackedListOfAssignments(llelem.lst, res, id, sc);
|
|
|
|
|
|
}
|
|
|
|
|
|
else idlist.Add(llelem.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
idlist.source_context = sc;
|
|
|
|
|
|
var ass = new assign_var_tuple(idlist, prevname, sc);
|
|
|
|
|
|
res.Insert(0, ass);
|
|
|
|
|
|
}
|
|
|
|
|
|
public override void visit(function_lambda_definition fld)
|
|
|
|
|
|
{
|
|
|
|
|
|
ProcessNode(fld.proc_body);
|
|
|
|
|
|
if (fld.unpacked_params == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
2021-03-26 00:12:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fld.formal_parameters = new formal_parameters();
|
|
|
|
|
|
fld.formal_parameters.source_context = fld.source_context;
|
2021-03-08 00:00:59 +03:00
|
|
|
|
|
|
|
|
|
|
// Пусть параметр имеет вид \(x,y)
|
|
|
|
|
|
// Тогда в начало тела лямбды надо добавить var (x,y) = #fpl1;
|
|
|
|
|
|
//var idl = new ident_list(fld.unpacked_params.Select(p => p.id).ToList(),fld.source_context); //
|
|
|
|
|
|
|
|
|
|
|
|
//var ass = new assign_var_tuple(idl, main_param_id, fld.source_context);
|
2021-03-26 00:12:48 +03:00
|
|
|
|
|
2021-03-08 00:00:59 +03:00
|
|
|
|
List<statement> res = new List<statement>();
|
2021-03-26 00:12:48 +03:00
|
|
|
|
|
|
|
|
|
|
foreach (var param in fld.unpacked_params)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param is unpacked_list_of_ident_or_list unpacked_param)
|
|
|
|
|
|
{
|
2023-05-31 14:04:04 +03:00
|
|
|
|
var lam_inft = new lambda_inferred_type(new lambda_any_type_node_syntax());
|
2021-03-26 00:12:48 +03:00
|
|
|
|
var param_id = CreateIdent(fld.source_context);
|
|
|
|
|
|
var idlist = new ident_list(param_id, unpacked_param.source_context);
|
|
|
|
|
|
var typed_pars = new typed_parameters(idlist, lam_inft, parametr_kind.none, null, unpacked_param.source_context);
|
|
|
|
|
|
fld.formal_parameters.Add(typed_pars, unpacked_param.source_context);
|
|
|
|
|
|
fld.ident_list.Add(param_id);
|
|
|
|
|
|
fld.parameters.Add(param_id);
|
|
|
|
|
|
|
|
|
|
|
|
CreateUnpackedListOfAssignments(unpacked_param, res, param_id, unpacked_param.source_context);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (param is ident id)
|
|
|
|
|
|
{
|
2023-05-31 14:04:04 +03:00
|
|
|
|
var lam_inft = new lambda_inferred_type(new lambda_any_type_node_syntax());
|
2021-03-26 00:12:48 +03:00
|
|
|
|
var idlist = new ident_list(id,id.source_context);
|
|
|
|
|
|
var typed_pars = new typed_parameters(idlist, lam_inft);
|
|
|
|
|
|
fld.formal_parameters.Add(typed_pars, fld.source_context);
|
|
|
|
|
|
fld.ident_list.Add(id);
|
|
|
|
|
|
fld.parameters.Add(id);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-08 00:00:59 +03:00
|
|
|
|
|
|
|
|
|
|
var stl = fld.proc_body as statement_list;
|
|
|
|
|
|
res.Reverse();
|
|
|
|
|
|
foreach (var st in res)
|
|
|
|
|
|
{
|
|
|
|
|
|
var ass = st as assign_var_tuple;
|
|
|
|
|
|
ass.idents.source_context = new SourceContext(ass.idents[0].source_context, ass.idents[ass.idents.Count - 1].source_context);
|
|
|
|
|
|
ass.expr.source_context = ass.idents.source_context;
|
|
|
|
|
|
stl.Insert(0, st); // возможно, в обратном порядке
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//stl.Insert(0, ass);
|
|
|
|
|
|
fld.unpacked_params = null; // на рассахаренном уровне это поле нулевое!
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|