pascalabcnet/SyntaxVisitors/YieldVisitors/JustTestVisitor.cs
Mikhalkovich Stanislav e603b1fd6d Mikhalkovich в Copyright
Заготовка для школьного плагина образцов кода
2019-07-28 23:53:15 +03:00

151 lines
6.4 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 System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class JustTestVisitor : BaseChangeVisitor
{
private void CollectFormalParams(procedure_definition pd, ISet<var_def_statement> collectedFormalParams)
{
if ((object)pd.proc_header.parameters != null)
collectedFormalParams.UnionWith(pd.proc_header.parameters.params_list.Select(tp => new var_def_statement(tp.idents, tp.vars_type)));
}
private void CollectFormalParamsNames(procedure_definition pd, ISet<string> collectedFormalParamsNames)
{
if ((object)pd.proc_header.parameters != null)
collectedFormalParamsNames.UnionWith(pd.proc_header.parameters.params_list.SelectMany(tp => tp.idents.idents).Select(id => id.name));
}
private void CollectClassFieldsNames(procedure_definition pd, ISet<string> collectedFields, out bool isInClassMethod)
{
isInClassMethod = false;
ident className = null;
if ((object)pd.proc_header.name.class_name != null)
{
// Объявление вне класса его метода
className = pd.proc_header.name.class_name;
}
else
{
// Объявление функции в классе?
var classDef = UpperNode(3) as class_definition;
if ((object)(UpperNode(3) as class_definition) != null)
{
var td = UpperNode(4) as type_declaration;
if ((object)td != null)
{
className = td.type_name;
}
}
}
if ((object)className != null)
{
isInClassMethod = true;
CollectClassFieldsVisitor fieldsVis = new CollectClassFieldsVisitor(className);
var cu = UpperTo<compilation_unit>();
if ((object)cu != null)
{
cu.visit(fieldsVis);
// Collect
collectedFields.UnionWith(fieldsVis.CollectedFields.Select(id => id.name));
}
}
}
private void CollectUnitGlobalsNames(procedure_definition pd, ISet<string> collectedUnitGlobalsName)
{
var cu = UpperTo<compilation_unit>();
if ((object)cu != null)
{
var ugVis = new CollectUnitGlobalsVisitor();
cu.visit(ugVis);
// Collect
collectedUnitGlobalsName.UnionWith(ugVis.CollectedGlobals.Select(id => id.name));
}
}
private void CreateCapturedLocalsNamesMap(ISet<string> localsNames, IDictionary<string, string> capturedLocalsNamesMap)
{
foreach (var localName in localsNames)
{
capturedLocalsNamesMap.Add(localName, CapturedNamesHelper.MakeCapturedLocalName(localName));
}
}
private void CreateCapturedFormalParamsNamesMap(ISet<string> formalParamsNames, IDictionary<string, string> captueedFormalParamsNamesMap)
{
foreach (var formalParamName in formalParamsNames)
{
captueedFormalParamsNamesMap.Add(formalParamName, CapturedNamesHelper.MakeCapturedFormalParameterName(formalParamName));
}
}
public override void visit(procedure_definition pd)
{
// frninja
// Classification
ISet<string> CollectedLocalsNames = new HashSet<string>();
ISet<string> CollectedFormalParamsNames = new HashSet<string>();
ISet<string> CollectedClassFieldsNames = new HashSet<string>();
ISet<string> CollectedUnitGlobalsNames = new HashSet<string>();
ISet<var_def_statement> CollectedLocals = new HashSet<var_def_statement>();
ISet<var_def_statement> CollectedFormalParams = new HashSet<var_def_statement>();
// Map from ident idName -> captured ident idName
IDictionary<string, string> CapturedLocalsNamesMap = new Dictionary<string, string>();
IDictionary<string, string> CapturedFormalParamsNamesMap = new Dictionary<string, string>();
var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные
pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement
// frninja 08/12/15
bool isInClassMethod;
// Collect locals
CollectedLocals.UnionWith(dld.LocalDeletedDefs);
CollectedLocalsNames.UnionWith(dld.LocalDeletedDefs.SelectMany(vds => vds.vars.idents).Select(id => id.name));
// Collect formal params
CollectFormalParams(pd, CollectedFormalParams);
CollectFormalParamsNames(pd, CollectedFormalParamsNames);
// Collect class fields
CollectClassFieldsNames(pd, CollectedClassFieldsNames, out isInClassMethod);
// Collect unit globals
CollectUnitGlobalsNames(pd, CollectedUnitGlobalsNames);
// Create maps :: idName -> captureName
CreateCapturedLocalsNamesMap(CollectedLocalsNames, CapturedLocalsNamesMap);
CreateCapturedFormalParamsNamesMap(CollectedFormalParamsNames, CapturedFormalParamsNamesMap);
// AHAHA test!
ReplaceCapturedVariablesVisitor rcapVis = new ReplaceCapturedVariablesVisitor(
CollectedLocalsNames,
CollectedFormalParamsNames,
CollectedClassFieldsNames,
new HashSet<string>(),
new HashSet<string>(),
CollectedUnitGlobalsNames,
CapturedLocalsNamesMap,
CapturedFormalParamsNamesMap,
isInClassMethod
);
// Replace
(pd.proc_body as block).program_code.visit(rcapVis);
}
}
}