80 lines
3.1 KiB
C#
80 lines
3.1 KiB
C#
// 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 ExitParamVisitor : BaseChangeVisitor
|
|
{
|
|
public static ExitParamVisitor New
|
|
{
|
|
get { return new ExitParamVisitor(); }
|
|
}
|
|
|
|
public override void visit(procedure_call pc)
|
|
{
|
|
var fname = pc.func_name as method_call;
|
|
var id = fname?.dereferencing_value as ident;
|
|
if (id != null && id.name.ToLower() == "exit")
|
|
{
|
|
if (fname.parameters == null || fname.parameters.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
if (fname.parameters.Count > 1)
|
|
{
|
|
throw new SyntaxVisitorError("EXIT_PROC_CAN_HAVE_ONLY_ONE_OR_ZERO_PARAMS", pc.source_context);
|
|
}
|
|
// Поднимаемся по Parent до procedure_definition или nil
|
|
var parent = pc.Parent;
|
|
while (parent != null && !(parent is procedure_definition)
|
|
&& !(parent is function_lambda_definition))
|
|
parent = parent.Parent;
|
|
if (parent == null)
|
|
{
|
|
throw new SyntaxVisitorError("EXIT_WITH_PARAM_MUST_BE_ONLY_IN_FUNC", pc.source_context);
|
|
}
|
|
if (parent is procedure_definition pd && !(pd.proc_header is function_header))
|
|
{
|
|
throw new SyntaxVisitorError("EXIT_WITH_PARAM_MUST_BE_ONLY_IN_FUNC", pc.source_context);
|
|
}
|
|
if (parent is function_lambda_definition fld /*&& fld.return_type == null*/)
|
|
{
|
|
fld.usedkeyword = 1;
|
|
fld.return_type = new lambda_inferred_type();
|
|
//throw new SyntaxVisitorError("EXIT_WITH_PARAM_CANNOT_BE_IN_LAMBDA_PROCEDURE", pc.source_context);
|
|
}
|
|
|
|
var arg = fname.parameters[0] as expression;
|
|
// Теперь сформировать 2 узла как statement_list: Result := arg; exit
|
|
|
|
var sl = new List<statement>();
|
|
var exitproc = new procedure_call(new ident("exit", pc.source_context));
|
|
var ass_Res = new assign(new ident("Result", pc.source_context), arg,
|
|
Operators.Assignment, pc.source_context);
|
|
sl.Add(ass_Res);
|
|
sl.Add(exitproc);
|
|
|
|
ReplaceStatementUsingParent(pc, sl);
|
|
|
|
}
|
|
|
|
//mc = new method_call(
|
|
// new dot_node(indexCreation, new ident("Reverse", ind.source_context)),
|
|
// reverseIndexMethodParams,
|
|
// ind.source_context);
|
|
|
|
//ReplaceUsingParent(ind, mc);
|
|
//visit(mc);
|
|
}
|
|
|
|
}
|
|
|
|
}
|