Перенёс SyntaxVisitors в папку первого уровня
This commit is contained in:
parent
e7b65c421b
commit
bd19c5e385
|
|
@ -2902,7 +2902,7 @@ namespace PascalABCCompiler
|
|||
|
||||
if (errorsList.Count == 0) // SSM 2/05/16 - для преобразования синтаксических деревьев извне
|
||||
{
|
||||
CurrentUnit.SyntaxTree = syntaxTreeConvertersController.Convert(CurrentUnit.SyntaxTree) as SyntaxTree.compilation_unit;
|
||||
CurrentUnit.SyntaxTree = syntaxTreeConvertersController.Convert(CurrentUnit.SyntaxTree,UnitName,errorsList) as SyntaxTree.compilation_unit;
|
||||
}
|
||||
|
||||
if (errorsList.Count == 0 && need_gen_doc(CurrentUnit.SyntaxTree))
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System.IO;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.SyntaxTreeConverters;
|
||||
using PascalABCCompiler.Errors;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||
{
|
||||
|
|
@ -87,12 +87,12 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
|
||||
}
|
||||
|
||||
public syntax_tree_node Convert(syntax_tree_node root)
|
||||
public syntax_tree_node Convert(syntax_tree_node root, string FileName, List<Error> errorsList)
|
||||
{
|
||||
foreach (ISyntaxTreeConverter SyntaxTreeConverter in syntaxTreeConverters)
|
||||
{
|
||||
ChangeState(State.Convert, SyntaxTreeConverter);
|
||||
root = SyntaxTreeConverter.Convert(root);
|
||||
root = SyntaxTreeConverter.Convert(root,FileName,errorsList);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ namespace PascalABCCompiler.Errors
|
|||
if (source_context != null && source_context.FileName != null)
|
||||
base.fileName = source_context.FileName;
|
||||
bad_node = _bad_node;
|
||||
//Console.WriteLine(ToString());
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
<Compile Include="ParserTools\LanguageInformation.cs" />
|
||||
<Compile Include="ParserTools\ParserTools.cs" />
|
||||
<Compile Include="ParserTools\SourceContextMap.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SyntaxTreeVisitors\ConstantExpressionToConstantConvertor.cs" />
|
||||
<Compile Include="SyntaxTreeVisitors\SyntaxTreeComparer.cs" />
|
||||
<Compile Include="Tools.cs" />
|
||||
|
|
@ -96,9 +97,7 @@
|
|||
<Name>SyntaxTree</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
|
|
|
|||
|
|
@ -522,6 +522,17 @@
|
|||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
<Node Name="foreach (ISyntaxTreeConverter SyntaxTreeConverter in syntaxTreeConverters)">
|
||||
<FileName>\Compiler\SyntaxTreeConvertersController\SyntaxTreeConvertersController.cs</FileName>
|
||||
<Text>foreach (ISyntaxTreeConverter SyntaxTreeConverter in syntaxTreeConverters)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public syntax_tree_node Convert ( syntax_tree_node root , string FileName , List < Error > errorsList )</i>
|
||||
<i Type="ClassOrNamespace">public class SyntaxTreeConvertersController</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCCompiler . SyntaxTreeConverters</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
<Node Name="PVS Studio Detected">
|
||||
|
|
@ -1035,13 +1046,13 @@
|
|||
</Node>
|
||||
</Items>
|
||||
</Node>
|
||||
<Node Name="id.name.ToLower() == "result"">
|
||||
<FileName>\Yield\SyntaxVisitors\YieldVisitors\MarkMethodHasYieldVisitor.cs</FileName>
|
||||
<Text>if (id.name.ToLower() == "result")</Text>
|
||||
<Node Name="AddErrorFromResource">
|
||||
<FileName>\Parsers\PascalABCParserNewSaushkin\ABCPascalParserTools.cs</FileName>
|
||||
<Text>public void AddErrorFromResource(string res, PascalABCCompiler.SyntaxTree.SourceContext loc, params string[] pars)</Text>
|
||||
<OCtx>
|
||||
<i Type="Method">public override void visit ( ident id )</i>
|
||||
<i Type="ClassOrNamespace">public class MarkMethodHasYieldVisitor : WalkingVisitorNew</i>
|
||||
<i Type="ClassOrNamespace">namespace SyntaxVisitors</i>
|
||||
<i Type="Method">public void AddErrorFromResource ( string res , PascalABCCompiler . SyntaxTree . SourceContext loc , params string [ ] pars )</i>
|
||||
<i Type="ClassOrNamespace">public class PT</i>
|
||||
<i Type="ClassOrNamespace">namespace PascalABCSavParser</i>
|
||||
<i Type="CS_TreeNode">
|
||||
</i>
|
||||
</OCtx>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.Errors;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||
{
|
||||
|
|
@ -14,6 +16,10 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
}
|
||||
public interface ISyntaxTreeConverter
|
||||
{
|
||||
string FileName { get; set; }
|
||||
|
||||
List<Error> ErrorsList { get; set; }
|
||||
|
||||
string Name { get; }
|
||||
|
||||
string Version { get; }
|
||||
|
|
@ -26,7 +32,7 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
|
||||
ExecutionOrder ExecutionOrder { get; }
|
||||
|
||||
syntax_tree_node Convert(syntax_tree_node root);
|
||||
syntax_tree_node Convert(syntax_tree_node root, string FileName, List<Error> errorsList);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SyntaxTreeChanger")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2005-2016 by Ivan Bondarev, Stanislav Mihalkovich")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.IO;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.Errors;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTreeConverters
|
||||
{
|
||||
|
|
@ -81,14 +82,18 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
|||
|
||||
public class SampleSyntaxTreeConverter: ISyntaxTreeConverter
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public List<Error> ErrorsList { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Copyright { get; set; }
|
||||
public ConverterType ConverterType { get; set; }
|
||||
public ExecutionOrder ExecutionOrder { get; set; }
|
||||
public syntax_tree_node Convert(syntax_tree_node root)
|
||||
public syntax_tree_node Convert(syntax_tree_node root, string FileName, List<Error> ErrorsList)
|
||||
{
|
||||
this.FileName = FileName;
|
||||
this.ErrorsList = ErrorsList;
|
||||
//var v = new SampleVisitor();
|
||||
//v.ProcessNode(root);
|
||||
return root;
|
||||
|
|
|
|||
167
Yield/SyntaxVisitors/.gitignore
vendored
167
Yield/SyntaxVisitors/.gitignore
vendored
|
|
@ -1,167 +0,0 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
.vs/
|
||||
|
||||
# Build results
|
||||
[Bb]inaries/
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
|
||||
# NuGet restore semaphore
|
||||
build/ToolsetPackages/toolsetpackages.semaphore
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
UnitTestResults.html
|
||||
|
||||
# NuGet V3 artifacts
|
||||
*-packages.config
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.wrn
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual Studio cache files
|
||||
*.sln.ide/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
|
||||
#LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
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 AllVarsInProcYields : CollectUpperNamespacesVisitor
|
||||
{
|
||||
public FindMainIdentsVisitor mids = new FindMainIdentsVisitor();
|
||||
|
||||
public Dictionary<procedure_definition, ISet<string>> d = new Dictionary<procedure_definition, ISet<string>>();
|
||||
|
||||
public int countNodesVisited;
|
||||
|
||||
public AllVarsInProcYields()
|
||||
{
|
||||
PrintInfo = false;
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
base.Enter(st);
|
||||
countNodesVisited++;
|
||||
if (st is procedure_definition)
|
||||
{
|
||||
// пока вложенные процедуры не анализируются, хотя надо
|
||||
mids.vars.Clear();
|
||||
}
|
||||
|
||||
// сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов)
|
||||
if (st is assign || st is var_def_statement || st is procedure_call || st is procedure_header || st is expression)
|
||||
{
|
||||
visitNode = false;
|
||||
}
|
||||
}
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
if (st is procedure_definition)
|
||||
{
|
||||
if (mids.vars.Count>0)
|
||||
{
|
||||
d[st as procedure_definition] = new HashSet<string>(mids.vars);
|
||||
}
|
||||
var fld = new FindLocalDefsVisitor();
|
||||
st.visit(fld);
|
||||
fld.Print();
|
||||
var t = fld.ids.Intersect(mids.vars); // идентификаторы, захваченные из локального контекста
|
||||
|
||||
}
|
||||
base.Exit(st);
|
||||
}
|
||||
public override void visit(yield_node yn)
|
||||
{
|
||||
yn.visit(mids);
|
||||
// mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные)
|
||||
// те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции
|
||||
// самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма
|
||||
// вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield
|
||||
//base.visit(yn);
|
||||
}
|
||||
|
||||
public void PrintDict()
|
||||
{
|
||||
foreach (var a in d)
|
||||
{
|
||||
Console.Write("{0}: {1} ", a.Key.proc_header.name.meth_name, a.Value.Count);
|
||||
foreach (var v in a.Value)
|
||||
Console.Write("{0}, ", v);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("countNodesVisited={0}", countNodesVisited);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
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 BaseChangeVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
private bool _rootAdded = false;
|
||||
public override void DefaultVisit(syntax_tree_node n)
|
||||
{
|
||||
// frninja 07/12/15 - // SSM - это - идиотский код, приводивший к двойному обходу визитором всех узлов
|
||||
/*if (!_rootAdded)
|
||||
{
|
||||
_rootAdded = true;
|
||||
ProcessNode(n);
|
||||
}*/
|
||||
|
||||
// Элементы списков - с конца в начало чтобы можно было эти элементы изменять по ходу (удалять/вставлять/заменять один несколькими)
|
||||
var Сount = n.subnodes_count;
|
||||
var СountWithoutListElements = n.subnodes_without_list_elements_count;
|
||||
|
||||
for (var i = 0; i < СountWithoutListElements; i++)
|
||||
ProcessNode(n[i]);
|
||||
|
||||
for (var i = Сount - 1; i >= СountWithoutListElements; i--) // в обратном порядке
|
||||
ProcessNode(n[i]);
|
||||
}
|
||||
|
||||
public void Replace(syntax_tree_node from, syntax_tree_node to)
|
||||
{
|
||||
var upper = UpperNode();
|
||||
if (upper == null)
|
||||
throw new Exception("У корневого элемента нельзя получить UpperNode");
|
||||
upper.Replace(from, to);
|
||||
}
|
||||
|
||||
public T UpperNodeAs<T>(int up = 1) where T : syntax_tree_node
|
||||
{
|
||||
var stl = UpperNode(up) as T;
|
||||
if (stl == null)
|
||||
throw new Exception("Элемент вложен не в " + typeof(T));
|
||||
return stl;
|
||||
}
|
||||
|
||||
public T UpperTo<T>() where T : syntax_tree_node
|
||||
{
|
||||
syntax_tree_node upperNode = null;
|
||||
|
||||
int up = 1;
|
||||
|
||||
do
|
||||
{
|
||||
upperNode = UpperNode(up);
|
||||
++up;
|
||||
}
|
||||
while ((object)upperNode != null && !(upperNode is T));
|
||||
|
||||
return (object)upperNode != null ? upperNode as T : null;
|
||||
}
|
||||
|
||||
public bool DeleteInIdentList(ident id)
|
||||
{
|
||||
var idl = UpperNodeAs<ident_list>();
|
||||
return idl.Remove(id);
|
||||
}
|
||||
|
||||
public bool DeleteInStatementList(statement st)
|
||||
{
|
||||
var stl = UpperNodeAs<statement_list>();
|
||||
return stl.Remove(st);
|
||||
}
|
||||
|
||||
public static IEnumerable<statement> SeqStatements(params statement[] seq)
|
||||
{
|
||||
var l = new List<statement>();
|
||||
foreach (var st in seq)
|
||||
if (st is statement_list)
|
||||
l.AddRange((st as statement_list).list);
|
||||
else l.Add(st);
|
||||
return l;
|
||||
}
|
||||
|
||||
public void ReplaceStatement(statement from, statement to)
|
||||
{
|
||||
var stl = UpperNodeAs<statement_list>();
|
||||
stl.ReplaceInList(from, to);
|
||||
}
|
||||
|
||||
public void ReplaceStatement(statement from, IEnumerable<statement> to)
|
||||
{
|
||||
var stl = UpperNodeAs<statement_list>();
|
||||
stl.ReplaceInList(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
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 BaseEnterExitVisitor : WalkingVisitorNew
|
||||
{
|
||||
public BaseEnterExitVisitor()
|
||||
{
|
||||
OnEnter = Enter;
|
||||
OnLeave = Exit;
|
||||
}
|
||||
|
||||
public virtual void Enter(syntax_tree_node st)
|
||||
{
|
||||
}
|
||||
public virtual void Exit(syntax_tree_node st)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
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 CollectUpperNamespacesVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
protected List<declaration> list = new List<declaration>();
|
||||
|
||||
public bool PrintInfo = true;
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
base.Enter(st);
|
||||
if (st is procedure_definition || st is class_definition)
|
||||
{
|
||||
list.Add(st as declaration);
|
||||
if (PrintInfo)
|
||||
Console.Write("+: "+st.GetType().Name);
|
||||
}
|
||||
}
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
if (st is procedure_definition || st is class_definition)
|
||||
{
|
||||
if (PrintInfo)
|
||||
Console.WriteLine("-: " + st.GetType().Name);
|
||||
list.RemoveAt(list.Count - 1);
|
||||
}
|
||||
base.Exit(st);
|
||||
}
|
||||
|
||||
public override void visit(procedure_definition p)
|
||||
{
|
||||
if (PrintInfo)
|
||||
Console.WriteLine(" " + p.proc_header.name.meth_name);
|
||||
|
||||
var ld = new FindLocalDefsVisitor();
|
||||
p.visit(ld);
|
||||
|
||||
base.visit(p);
|
||||
}
|
||||
public override void visit(class_definition cl)
|
||||
{
|
||||
type_declarations tds = UpperNode(2) as type_declarations;
|
||||
if (PrintInfo)
|
||||
{
|
||||
var f = tds.types_decl.Find(td => td.type_def == cl);
|
||||
Console.WriteLine(" " + f.type_name);
|
||||
}
|
||||
base.visit(cl);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
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 CollectUpperNodesVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
protected List<syntax_tree_node> listNodes = new List<syntax_tree_node>();
|
||||
|
||||
public syntax_tree_node CurrentNode
|
||||
{
|
||||
get
|
||||
{
|
||||
return listNodes[listNodes.Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public syntax_tree_node UpperNode(int up = 1)
|
||||
{
|
||||
if (listNodes.Count - 1 - up < 0)
|
||||
return null;
|
||||
return listNodes[listNodes.Count - 1 - up];
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
listNodes.Add(st);
|
||||
}
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
listNodes.RemoveAt(listNodes.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
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 HasStatementVisitor<T> : WalkingVisitorNew
|
||||
where T : statement
|
||||
{
|
||||
private bool foundT = false;
|
||||
|
||||
public static bool Has(syntax_tree_node node)
|
||||
{
|
||||
HasStatementVisitor<T> vis = new HasStatementVisitor<T>();
|
||||
|
||||
vis.ProcessNode(node);
|
||||
|
||||
return vis.foundT;
|
||||
}
|
||||
|
||||
public override void DefaultVisit(syntax_tree_node node)
|
||||
{
|
||||
if (node is T)
|
||||
foundT = true;
|
||||
else
|
||||
base.DefaultVisit(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
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 FindLocalDefsVisitor : WalkingVisitorNew // Запускать только для подпрограмм
|
||||
{
|
||||
public ISet<string> ids = new HashSet<string>();
|
||||
private bool indef = false;
|
||||
public override void visit(ident id)
|
||||
{
|
||||
if (indef)
|
||||
ids.Add(id.name);
|
||||
}
|
||||
public override void visit(var_def_statement defs)
|
||||
{
|
||||
indef = true;
|
||||
ProcessNode(defs.vars); // исключаем типы - просматриваем только имена переменных
|
||||
indef = false;
|
||||
}
|
||||
|
||||
public void Print()
|
||||
{
|
||||
foreach (var x in ids)
|
||||
Console.Write(x + ", ");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public class FindMainIdentsVisitor : WalkingVisitorNew // в выражении yield это надо будет.
|
||||
{
|
||||
public HashSet<string> vars = new HashSet<string>();
|
||||
public override void visit(ident id)
|
||||
{
|
||||
vars.Add(id.name);
|
||||
}
|
||||
public override void visit(dot_node dn)
|
||||
{
|
||||
ProcessNode(dn.left);
|
||||
if (dn.right.GetType() != typeof(ident))
|
||||
ProcessNode(dn.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class ChangeWhileVisitor : BaseChangeVisitor
|
||||
{
|
||||
int lbnum = 0;
|
||||
|
||||
public static ChangeWhileVisitor New
|
||||
{
|
||||
get { return new ChangeWhileVisitor(); }
|
||||
}
|
||||
|
||||
public string newLabelName()
|
||||
{
|
||||
lbnum++;
|
||||
return "lb#" + lbnum.ToString();
|
||||
}
|
||||
public override void visit(while_node wn)
|
||||
{
|
||||
ProcessNode(wn.statements);
|
||||
var gt1 = new goto_statement(newLabelName());
|
||||
var gt2 = new goto_statement(newLabelName());
|
||||
var gt3 = new goto_statement(newLabelName());
|
||||
|
||||
var if0 = new if_node(wn.expr, gt1, null);
|
||||
var lb3 = new labeled_statement(gt3.label, if0);
|
||||
var lb1 = new labeled_statement(gt1.label, wn.statements);
|
||||
var lb2 = new labeled_statement(gt2.label, new empty_statement());
|
||||
|
||||
var stl = new statement_list(lb3, gt2, lb1, gt3, lb2);
|
||||
|
||||
Replace(wn, stl);
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
var ld = new label_definitions(gt1.label, gt2.label, gt3.label);
|
||||
bl.defs.Add(ld);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
/// <summary>
|
||||
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
|
||||
/// Provides a method for performing a deep copy of an object.
|
||||
/// Binary Serialization is used to perform the copy.
|
||||
/// </summary>
|
||||
public static class ObjectCopier
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform a deep Copy of the object.
|
||||
/// </summary>
|
||||
/// <typeparam className="T">The type of object being copied.</typeparam>
|
||||
/// <param className="source">The object instance to copy.</param>
|
||||
/// <returns>The copied object.</returns>
|
||||
public static T Clone<T>(T source)
|
||||
{
|
||||
if (!typeof(T).IsSerializable)
|
||||
{
|
||||
throw new ArgumentException("The type must be serializable.", "source");
|
||||
}
|
||||
|
||||
// Don't serialize a null object, simply return the default for that object
|
||||
if (Object.ReferenceEquals(source, null))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
Stream stream = new MemoryStream();
|
||||
using (stream)
|
||||
{
|
||||
formatter.Serialize(stream, source);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return (T)formatter.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
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 CalcConstExprs : BaseChangeVisitor // вычисление целых и вещественных константных выражений на этапе парсинга
|
||||
{
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
bracket_expr bre = st as bracket_expr;
|
||||
if (bre != null)
|
||||
{
|
||||
if (bre.expr is int32_const)
|
||||
Replace(st, bre.expr);
|
||||
}
|
||||
|
||||
bin_expr vs = st as bin_expr;
|
||||
if (vs != null)
|
||||
{
|
||||
if (vs.left is int32_const && vs.right is int32_const)
|
||||
{
|
||||
var a = vs.left as int32_const;
|
||||
var b = vs.right as int32_const;
|
||||
var op = vs.operation_type;
|
||||
|
||||
syntax_tree_node res;
|
||||
switch (op)
|
||||
{
|
||||
case Operators.Plus:
|
||||
res = new int32_const(a.val + b.val);
|
||||
break;
|
||||
case Operators.Minus:
|
||||
res = new int32_const(a.val - b.val);
|
||||
break;
|
||||
case Operators.Multiplication:
|
||||
res = new int32_const(a.val * b.val);
|
||||
break;
|
||||
case Operators.Division:
|
||||
res = new double_const((double)a.val / b.val);
|
||||
break;
|
||||
case Operators.Greater:
|
||||
res = new bool_const(a.val > b.val);
|
||||
break;
|
||||
case Operators.Less:
|
||||
res = new bool_const(a.val < b.val);
|
||||
break;
|
||||
case Operators.GreaterEqual:
|
||||
res = new bool_const(a.val >= b.val);
|
||||
break;
|
||||
case Operators.LessEqual:
|
||||
res = new bool_const(a.val <= b.val);
|
||||
break;
|
||||
default:
|
||||
res = vs;
|
||||
break;
|
||||
}
|
||||
|
||||
Replace(vs, res);
|
||||
}
|
||||
if (vs.left is int32_const && vs.right is double_const || vs.right is int32_const && vs.left is double_const || vs.left is double_const && vs.right is double_const)
|
||||
{
|
||||
double x,y;
|
||||
if (vs.left is int32_const)
|
||||
x = (vs.left as int32_const).val;
|
||||
else
|
||||
x = (vs.left as double_const).val;
|
||||
if (vs.right is int32_const)
|
||||
y = (vs.right as int32_const).val;
|
||||
else
|
||||
y = (vs.right as double_const).val;
|
||||
|
||||
var op = vs.operation_type;
|
||||
|
||||
syntax_tree_node res;
|
||||
switch (op)
|
||||
{
|
||||
case Operators.Plus:
|
||||
res = new double_const(x + y);
|
||||
break;
|
||||
case Operators.Minus:
|
||||
res = new double_const(x - y);
|
||||
break;
|
||||
case Operators.Multiplication:
|
||||
res = new double_const(x * y);
|
||||
break;
|
||||
case Operators.Division:
|
||||
res = new double_const(x / y);
|
||||
break;
|
||||
case Operators.Greater:
|
||||
res = new bool_const(x > y);
|
||||
break;
|
||||
case Operators.Less:
|
||||
res = new bool_const(x < y);
|
||||
break;
|
||||
case Operators.GreaterEqual:
|
||||
res = new bool_const(x >= y);
|
||||
break;
|
||||
case Operators.LessEqual:
|
||||
res = new bool_const(x <= y);
|
||||
break;
|
||||
default:
|
||||
res = vs;
|
||||
break;
|
||||
}
|
||||
|
||||
Replace(vs, res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
base.Exit(st); // это обязательно!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Управление общими сведениями о сборке осуществляется с помощью
|
||||
// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
|
||||
// связанные со сборкой.
|
||||
[assembly: AssemblyTitle("SyntaxVisitors")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Hewlett-Packard")]
|
||||
[assembly: AssemblyProduct("SyntaxVisitors")]
|
||||
[assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми
|
||||
// для COM-компонентов. Если требуется обратиться к типу в этой сборке через
|
||||
// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
|
||||
[assembly: Guid("a9ab4282-83b4-41a7-86c3-e5bf6a45e7e2")]
|
||||
|
||||
// Сведения о версии сборки состоят из следующих четырех значений:
|
||||
//
|
||||
// Основной номер версии
|
||||
// Дополнительный номер версии
|
||||
// Номер сборки
|
||||
// Редакция
|
||||
//
|
||||
// Можно задать все значения или принять номера сборки и редакции по умолчанию
|
||||
// используя "*", как показано ниже:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A9AB4282-83B4-41A7-86C3-E5BF6A45E7E2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SyntaxVisitors</RootNamespace>
|
||||
<AssemblyName>SyntaxVisitors</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AllVarsInProcYieldsProba.cs" />
|
||||
<Compile Include="BaseVisitors\BaseChangeVisitor.cs" />
|
||||
<Compile Include="BaseVisitors\BaseEnterExitVisitor.cs" />
|
||||
<Compile Include="BaseVisitors\CollectNamespaces.cs" />
|
||||
<Compile Include="BaseVisitors\CollectUpperNodesVisitor.cs" />
|
||||
<Compile Include="BaseVisitors\HasStatementVisitor.cs" />
|
||||
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
|
||||
<Compile Include="ChangeWhileVisitor.cs" />
|
||||
<Compile Include="ObjectCopier.cs" />
|
||||
<Compile Include="Optimization\CalcConstExprs.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UniversalVisitors\AddBeginEndsVisitor.cs" />
|
||||
<Compile Include="UniversalVisitors\CountNodesVisitor.cs" />
|
||||
<Compile Include="UniversalVisitors\DeleteRedundantBeginEnds.cs" />
|
||||
<Compile Include="UniversalVisitors\SimplePrettyPrinterVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\CheckVariablesRedefenitionVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\CollectClassMethodsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\CollectClassPropertiesVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\CollectUnitGlobalsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\DeleteAllLocalDefs.cs" />
|
||||
<Compile Include="YieldVisitors\DeleteLocalDefs.cs" />
|
||||
<Compile Include="YieldVisitors\CollectClassFieldsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\LoweringVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\LocalVariablesTypeDetectorHelperVisior.cs" />
|
||||
<Compile Include="YieldVisitors\MarkMethodHasYieldVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ProcessYieldsCapturedVars.cs" />
|
||||
<Compile Include="YieldVisitors\RenameSameBlockLocalVarsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceBreakContinueWithGotoLabelVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceCapturedVariablesVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceFormalParametersRefsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceVariableNameVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceYieldWithLamdasVisitor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Compiler\Compiler.csproj">
|
||||
<Project>{1e42361a-eda3-4872-88af-a3aaf600d36d}</Project>
|
||||
<Name>Compiler</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Errors\Errors.csproj">
|
||||
<Project>{44a01f9e-dce7-470c-aae5-c3de0ccbee3b}</Project>
|
||||
<Name>Errors</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\ParserTools\ParserTools.csproj">
|
||||
<Project>{af2efd7b-69dd-4b43-af65-b59b29349c23}</Project>
|
||||
<Name>ParserTools</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\SyntaxTree\SyntaxTree.csproj">
|
||||
<Project>{c2cac65a-b2ae-4ccc-b067-e6b8e75df73a}</Project>
|
||||
<Name>SyntaxTree</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\TreeConverter\TreeConverter.csproj">
|
||||
<Project>{1c9c945a-586d-42a2-a06b-65d84fa7ff78}</Project>
|
||||
<Name>TreeConverter</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YieldHelpers\YieldHelpers.csproj">
|
||||
<Project>{ce5c55c2-a11c-4e94-a9fa-3fc6ca3e4c09}</Project>
|
||||
<Name>YieldHelpers</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class AddBeginEndsVisitor : BaseChangeVisitor
|
||||
{
|
||||
public static AddBeginEndsVisitor New
|
||||
{
|
||||
get { return new AddBeginEndsVisitor(); }
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
}
|
||||
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
var sts = st as statement;
|
||||
|
||||
if (sts != null && !(sts is statement_list) && !(sts is case_variant) && !(UpperNode() is statement_list))
|
||||
{
|
||||
// Одиночный оператор
|
||||
var stl = new statement_list(sts, st.source_context);
|
||||
Replace(sts, stl);
|
||||
}
|
||||
|
||||
|
||||
var lst = st as labeled_statement;
|
||||
|
||||
if (lst != null && !(lst.to_statement is statement_list) && !(lst.to_statement is case_variant))
|
||||
{
|
||||
// Одиночный оператор
|
||||
var stl = new statement_list(sts, st.source_context);
|
||||
Replace(lst.to_statement, stl);
|
||||
}
|
||||
|
||||
base.Exit(st);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
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 CountNodesVisitor : BaseEnterExitVisitor
|
||||
{
|
||||
public Dictionary<System.Type, int> d = new Dictionary<System.Type, int>();
|
||||
|
||||
public int exprcount,statcount;
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
if (d.ContainsKey(st.GetType()))
|
||||
d[st.GetType()] += 1;
|
||||
else d[st.GetType()] = 1;
|
||||
if (st is expression)
|
||||
exprcount++;
|
||||
if (st is statement)
|
||||
statcount++;
|
||||
}
|
||||
|
||||
public void PrintSortedByValue()
|
||||
{
|
||||
var q = d.Select(x => new { x.Key, x.Value }).OrderByDescending(y => y.Value);
|
||||
foreach (var a in q)
|
||||
Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Expressions Count: {0}", exprcount);
|
||||
Console.WriteLine("Statements Count: {0}", statcount);
|
||||
}
|
||||
|
||||
public void Print()
|
||||
{
|
||||
foreach (var a in d)
|
||||
Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class DeleteRedundantBeginEnds : BaseChangeVisitor
|
||||
{
|
||||
public static DeleteRedundantBeginEnds New
|
||||
{
|
||||
get { return new DeleteRedundantBeginEnds(); }
|
||||
}
|
||||
|
||||
public static DeleteRedundantBeginEnds Accept(procedure_definition pd)
|
||||
{
|
||||
var n = New;
|
||||
n.ProcessNode(pd);
|
||||
return n;
|
||||
}
|
||||
|
||||
public override void Exit(syntax_tree_node st)
|
||||
{
|
||||
var stl = st as statement_list;
|
||||
if (stl != null && UpperNode() is statement_list)
|
||||
ReplaceStatement(stl, stl.subnodes);
|
||||
|
||||
var lst = st as labeled_statement;
|
||||
if (lst != null)
|
||||
{
|
||||
var sttl = lst.to_statement as statement_list;
|
||||
if (sttl != null)
|
||||
{
|
||||
if (sttl.subnodes[0] is var_statement) // SSM - 17.07.16 - фикс - нельзя помечать меткой var_statement!
|
||||
{
|
||||
sttl.AddFirst(empty_statement.New);
|
||||
}
|
||||
sttl.subnodes[0] = new labeled_statement(lst.label_name, sttl.subnodes[0]); // [0] элемент есть обязательно - в случае пустого begin end это empty_statement
|
||||
ReplaceStatement(lst,sttl.subnodes);
|
||||
}
|
||||
}
|
||||
|
||||
base.Exit(st);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler.PCU;
|
||||
using PascalABCCompiler.SemanticTreeConverters;
|
||||
using System.CodeDom.Compiler;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class SimplePrettyPrinterVisitor : WalkingVisitorNew
|
||||
{
|
||||
int off = 0;
|
||||
|
||||
bool printNodeType = false;
|
||||
|
||||
string filename = null;
|
||||
|
||||
public static SimplePrettyPrinterVisitor New
|
||||
{
|
||||
get { return new SimplePrettyPrinterVisitor(); }
|
||||
}
|
||||
|
||||
public SimplePrettyPrinterVisitor(string filename = null)
|
||||
{
|
||||
OnEnter = Enter;
|
||||
OnLeave = Exit;
|
||||
this.filename = filename;
|
||||
if (filename != null)
|
||||
System.IO.File.Delete(filename);
|
||||
}
|
||||
|
||||
public void Println(string s)
|
||||
{
|
||||
Print(s + Environment.NewLine);
|
||||
}
|
||||
public void Print(string s)
|
||||
{
|
||||
PrintNoOffset(new string(' ', off) + s);
|
||||
}
|
||||
public void PrintNoOffset(string s)
|
||||
{
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.", "");
|
||||
if (filename == null)
|
||||
{
|
||||
Console.Write(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.IO.File.AppendAllText(filename, s);
|
||||
}
|
||||
}
|
||||
public void PrintlnNoOffset(string s)
|
||||
{
|
||||
PrintNoOffset(s + Environment.NewLine);
|
||||
}
|
||||
|
||||
public void PrintlnNode(syntax_tree_node st)
|
||||
{
|
||||
if (printNodeType)
|
||||
PrintNoOffset(st.GetType().Name + ": ");
|
||||
Println(""+st);
|
||||
}
|
||||
|
||||
public void PrintNode(syntax_tree_node st)
|
||||
{
|
||||
if (printNodeType)
|
||||
PrintNoOffset(st.GetType().Name + ": ");
|
||||
Print(""+st);
|
||||
}
|
||||
|
||||
public virtual void Enter(syntax_tree_node st)
|
||||
{
|
||||
if (st is statement_list)
|
||||
{
|
||||
Println("begin");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is type_declarations) // надо в visit и самому всё обрабатывать
|
||||
{
|
||||
var tds = st is type_declarations;
|
||||
Println("type ");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is case_variant)
|
||||
{
|
||||
var td = st as case_variant;
|
||||
Println(td.conditions.ToString()+": ");
|
||||
off += 2;
|
||||
//ProcessNode(td.type_def);
|
||||
//visitNode = false;
|
||||
}
|
||||
else if (st is type_declaration)
|
||||
{
|
||||
var td = st as type_declaration;
|
||||
Print(td.type_name + " = ");
|
||||
ProcessNode(td.type_def);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is procedure_definition)
|
||||
{
|
||||
//ProcessNode(st as procedure_definition);
|
||||
visitNode = visitNode;
|
||||
}
|
||||
else if (st is class_definition)
|
||||
{
|
||||
var cd = st as class_definition;
|
||||
PrintNoOffset("class");
|
||||
if (cd.class_parents?.types.Count > 0)
|
||||
PrintlnNoOffset("(" + cd.class_parents.ToString() + ")");
|
||||
else
|
||||
PrintlnNoOffset("");
|
||||
off += 2;
|
||||
ProcessNode(cd.body);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is access_modifer_node)
|
||||
{
|
||||
var am = st as access_modifer_node;
|
||||
Println(am.access_level.ToString().Replace("_modifier",""));
|
||||
}
|
||||
else if (st is variable_definitions)
|
||||
{
|
||||
var vds = st as variable_definitions;
|
||||
Print("var");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is var_def_statement)
|
||||
{
|
||||
var vds = st as var_def_statement;
|
||||
Println (vds.ToString());
|
||||
}
|
||||
else if (st is yield_var_def_statement_with_unknown_type)
|
||||
{
|
||||
var vds = st as yield_var_def_statement_with_unknown_type;
|
||||
Println("var "+vds.ToString());
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members
|
||||
|| st is case_variants || st is program_module || st is no_type_foreach || st is template_param_list
|
||||
|| st is yield_unknown_foreach_type || st is yield_unknown_expression_type
|
||||
)
|
||||
{
|
||||
}
|
||||
/* else if (st is array_type)
|
||||
{
|
||||
var vds = st as array_type;
|
||||
Println ("array of "+vds.elements_type.ToString());
|
||||
}*/
|
||||
else if (st is if_node)
|
||||
{
|
||||
var ifn = st as if_node;
|
||||
|
||||
Println("if " + ifn.condition.ToString() + " then");
|
||||
off += 2;
|
||||
ProcessNode(ifn.then_body);
|
||||
if (ifn.else_body == null)
|
||||
{
|
||||
visitNode = false;
|
||||
return;
|
||||
}
|
||||
off -= 2;
|
||||
Println("else ");
|
||||
off += 2;
|
||||
ProcessNode(ifn.else_body);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is while_node)
|
||||
{
|
||||
var wn = st as while_node;
|
||||
|
||||
Println("while " + wn.expr.ToString() + " do");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is for_node)
|
||||
{
|
||||
var fn = st as for_node;
|
||||
|
||||
Println("for var " + fn.loop_variable + " := "+fn.initial_value+" to "+fn.finish_value + " do ");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is foreach_stmt)
|
||||
{
|
||||
var wn = st as foreach_stmt;
|
||||
|
||||
Println("foreach " + wn.identifier.ToString() + " in "+wn.in_what + " do");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is case_node)
|
||||
{
|
||||
var cn = st as case_node;
|
||||
|
||||
Println("case " + cn.param.ToString() + " of");
|
||||
off += 2;
|
||||
}
|
||||
else if (st is labeled_statement)
|
||||
{
|
||||
var lst = st as labeled_statement;
|
||||
|
||||
Println(lst.label_name.name + ": ");
|
||||
ProcessNode(lst.to_statement);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is var_statement || st is procedure_header)
|
||||
{
|
||||
var s = st.ToString();
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.","");
|
||||
|
||||
Println(s);
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is procedure_definition)
|
||||
{
|
||||
Println("");
|
||||
}
|
||||
else if (st is statement || st is variable_definitions || st is label_definitions)
|
||||
{
|
||||
PrintNode(st);
|
||||
if (st is statement)
|
||||
PrintlnNoOffset(";");
|
||||
else PrintlnNoOffset("");
|
||||
if (st is labeled_statement)
|
||||
visitNode = false;
|
||||
}
|
||||
else if (st is token_info)
|
||||
{
|
||||
var s = st.ToString();
|
||||
if (s == "begin" || s == "end")
|
||||
return;
|
||||
PrintlnNode(st);
|
||||
}
|
||||
else if (st is function_lambda_definition)
|
||||
{
|
||||
var f = st as function_lambda_definition;
|
||||
//PrintNoOffset(f.ToString());
|
||||
visitNode = false;
|
||||
}
|
||||
/*else if (st is named_type_reference)
|
||||
{
|
||||
var s = st.ToString();
|
||||
s = s.Replace("PascalABCCompiler.SyntaxTree.", "").Replace("System.Collections.Generic.","");
|
||||
|
||||
PrintlnNoOffset(s);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
var q = st.GetType().GetMethod("ToString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
|
||||
if (q == null)
|
||||
Println(st.GetType().Name);
|
||||
}
|
||||
}
|
||||
public virtual void Exit(syntax_tree_node st)
|
||||
{
|
||||
if (st is statement_list)
|
||||
{
|
||||
off -= 2;
|
||||
Println("end");
|
||||
}
|
||||
else if (st is while_node || st is if_node || st is type_declarations || st is variable_definitions || st is case_variant)
|
||||
{
|
||||
off -= 2;
|
||||
}
|
||||
else if (st is class_definition || st is case_node)
|
||||
{
|
||||
off -= 2;
|
||||
Println("end;");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
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 CheckVariablesRedefenitionVisitor : WalkingVisitorNew
|
||||
{
|
||||
private ISet<string> UpperBlockNames { get; set; }
|
||||
|
||||
// Map :: CurrentLevel -> { BlockNames }
|
||||
private List<ISet<string>> BlockNamesStack { get; set; }
|
||||
|
||||
private int CurrentLevel = -1;
|
||||
|
||||
public CheckVariablesRedefenitionVisitor(ISet<string> upperBlockNames)
|
||||
{
|
||||
//this.UpperBlockNames = upperBlockNames;
|
||||
this.UpperBlockNames = new HashSet<string>();
|
||||
this.BlockNamesStack = new List<ISet<string>>(10);
|
||||
}
|
||||
|
||||
|
||||
public override void visit(formal_parameters fp)
|
||||
{
|
||||
foreach (var id in fp.params_list.SelectMany(tp => tp.idents.idents))
|
||||
{
|
||||
CheckVariableAlreadyDefined(id);
|
||||
UpperBlockNames.Add(id.name);
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(variable_definitions vd)
|
||||
{
|
||||
foreach (var id in vd.var_definitions.SelectMany(vds => vds.vars.idents))
|
||||
{
|
||||
CheckVariableAlreadyDefined(id);
|
||||
UpperBlockNames.Add(id.name);
|
||||
}
|
||||
|
||||
base.visit(vd);
|
||||
}
|
||||
|
||||
/*
|
||||
* // Scope Level 0
|
||||
* begin
|
||||
* var x = value; // Name in Scope Level 0
|
||||
* // Scope Level 1
|
||||
* begin
|
||||
* var x = value; // Name in Scope Level 1 <-- REDEFENITION ERROR, x defined at Level 0
|
||||
*
|
||||
* var y = value;
|
||||
* var y = value2; // Name in Scope Level 1 <-- REDEFINITION ERROR, y defined at Level 1
|
||||
*
|
||||
* // Scope Level 2
|
||||
* begin
|
||||
* var z = y; // Name in Scope Level 2
|
||||
* end
|
||||
* // Scope Level 2
|
||||
* begin
|
||||
* var z = value; // Name in Scope Level 2
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* end
|
||||
*/
|
||||
|
||||
public override void visit(statement_list stlist)
|
||||
{
|
||||
++CurrentLevel;
|
||||
|
||||
if (BlockNamesStack.Count <= CurrentLevel)
|
||||
{
|
||||
// Создаем множество имен для текущего уровня вложенности мини-пространства имен
|
||||
BlockNamesStack.Add(new HashSet<string>());
|
||||
}
|
||||
|
||||
|
||||
base.visit(stlist);
|
||||
//for (var i = 0; i < stlist.list.Count; ++i)
|
||||
// ProcessNode(stlist.list[i]);
|
||||
|
||||
BlockNamesStack.RemoveAt(BlockNamesStack.Count - 1);
|
||||
|
||||
--CurrentLevel;
|
||||
}
|
||||
|
||||
public override void visit(var_statement vs)
|
||||
{
|
||||
foreach (var id in vs.var_def.vars.idents)
|
||||
{
|
||||
// Проверяем есть ли такое имя выше?
|
||||
CheckVariableAlreadyDefined(id);
|
||||
|
||||
BlockNamesStack[CurrentLevel].Add(id.name);
|
||||
}
|
||||
|
||||
base.visit(vs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void visit(for_node fn)
|
||||
{
|
||||
if (fn.create_loop_variable)
|
||||
{
|
||||
CheckVariableAlreadyDefined(fn.loop_variable);
|
||||
}
|
||||
base.visit(fn);
|
||||
}
|
||||
|
||||
public override void visit(foreach_stmt frch)
|
||||
{
|
||||
if (frch.type_name != null)
|
||||
{
|
||||
CheckVariableAlreadyDefined(frch.identifier);
|
||||
}
|
||||
base.visit(frch);
|
||||
}
|
||||
|
||||
private bool IsVariableAlreadyDefined(string name)
|
||||
{
|
||||
if (UpperBlockNames.Contains(name))
|
||||
return true;
|
||||
for (int i = 0; i <= CurrentLevel; ++i)
|
||||
{
|
||||
if (BlockNamesStack[i].Contains(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void CheckVariableAlreadyDefined(ident id)
|
||||
{
|
||||
string name = id.name;
|
||||
|
||||
if (IsVariableAlreadyDefined(name))
|
||||
{
|
||||
throw new PascalABCCompiler.Errors.SyntaxError(string.Format("Var {0} is already defined", name), "", id.source_context, id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
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 CollectClassFieldsVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
private ident _className;
|
||||
|
||||
public ISet<ident> CollectedFields { get; private set; }
|
||||
|
||||
public CollectClassFieldsVisitor(ident className)
|
||||
{
|
||||
CollectedFields = new HashSet<ident>();
|
||||
|
||||
_className = className;
|
||||
}
|
||||
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
type_declaration td = UpperNode(1) as type_declaration;
|
||||
|
||||
if ((object)td == null)
|
||||
{
|
||||
// Something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
if (td.type_name.name != _className.name)
|
||||
{
|
||||
// Not the class we search for
|
||||
// Yoda
|
||||
return;
|
||||
}
|
||||
|
||||
var fields = cd.body.class_def_blocks.SelectMany(cm => cm.members.Where(decl => decl is var_def_statement)
|
||||
.Select(decl1 => (decl1 as var_def_statement).vars.idents)
|
||||
.SelectMany(ids => ids.Select(id => id)));
|
||||
|
||||
|
||||
CollectedFields.UnionWith(fields);
|
||||
|
||||
/*foreach (var defs in cd.body.class_def_blocks)
|
||||
{
|
||||
// Class members
|
||||
foreach (var decl in defs.members)
|
||||
{
|
||||
// Declaration: fields + procedure defs + headers + etc
|
||||
// Need vars
|
||||
if (decl is var_def_statement)
|
||||
{
|
||||
var vars = (decl as var_def_statement).vars;
|
||||
// Fields
|
||||
foreach (var field in vars.idents)
|
||||
{
|
||||
CollectedFields.Add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
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 CollectClassMethodsVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
private ident _className;
|
||||
|
||||
public ISet<ident> CollectedMethods { get; private set; }
|
||||
|
||||
public CollectClassMethodsVisitor(ident className)
|
||||
{
|
||||
CollectedMethods = new HashSet<ident>();
|
||||
_className = className;
|
||||
}
|
||||
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
type_declaration td = UpperNode(1) as type_declaration;
|
||||
|
||||
if ((object)td == null)
|
||||
{
|
||||
// Something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
if (td.type_name.name != _className.name)
|
||||
{
|
||||
// Not the class we search for
|
||||
// Yoda
|
||||
return;
|
||||
}
|
||||
|
||||
var methods = cd.body.class_def_blocks.SelectMany(cm => cm.members.Select(decl1 =>
|
||||
{
|
||||
if (decl1 is procedure_header)
|
||||
return (decl1 as procedure_header).name.meth_name;
|
||||
else if (decl1 is procedure_definition)
|
||||
return (decl1 as procedure_definition).proc_header.name.meth_name;
|
||||
return null;
|
||||
}).Where(name => (object)name != null));
|
||||
|
||||
CollectedMethods.UnionWith(methods);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
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 CollectClassPropertiesVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
private ident _className;
|
||||
|
||||
public ISet<ident> CollectedProperties { get; private set; }
|
||||
|
||||
public CollectClassPropertiesVisitor(ident className)
|
||||
{
|
||||
CollectedProperties = new HashSet<ident>();
|
||||
_className = className;
|
||||
}
|
||||
|
||||
public override void visit(class_definition cd)
|
||||
{
|
||||
type_declaration td = UpperNode(1) as type_declaration;
|
||||
|
||||
if ((object)td == null)
|
||||
{
|
||||
// Something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
if (td.type_name.name != _className.name)
|
||||
{
|
||||
// Not the class we search for
|
||||
// Yoda
|
||||
return;
|
||||
}
|
||||
|
||||
var properties = cd.body.class_def_blocks.SelectMany(cm => cm.members.Select(decl => decl as simple_property)
|
||||
.Where(name => (object)name != null)
|
||||
.Select(sp => sp.property_name));
|
||||
|
||||
CollectedProperties.UnionWith(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
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 CollectUnitGlobalsVisitor : CollectUpperNodesVisitor
|
||||
{
|
||||
public ISet<ident> CollectedGlobals { get; private set; }
|
||||
|
||||
public CollectUnitGlobalsVisitor()
|
||||
{
|
||||
CollectedGlobals = new HashSet<ident>();
|
||||
}
|
||||
|
||||
/*public override void visit(interface_node node)
|
||||
{
|
||||
var globals = node.interface_definitions.defs
|
||||
.Select(def => def as variable_definitions)
|
||||
.Where(varDefsObj => (object)varDefsObj != null)
|
||||
.SelectMany(varDefs => varDefs.var_definitions)
|
||||
.SelectMany(v => v.vars.idents);
|
||||
|
||||
CollectedGlobals.UnionWith(globals);
|
||||
}*/
|
||||
|
||||
public override void visit(declarations node)
|
||||
{
|
||||
var globals = node.defs
|
||||
.Select(def => def as variable_definitions)
|
||||
.Where(varDefsObj => (object)varDefsObj != null)
|
||||
.SelectMany(varDefs => varDefs.var_definitions)
|
||||
.SelectMany(v => v.vars.idents);
|
||||
|
||||
CollectedGlobals.UnionWith(globals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
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 MoveAllLocalDefsToLists : BaseChangeVisitor
|
||||
{
|
||||
|
||||
private List<var_def_statement> LocalDeletedVD = new List<var_def_statement>(); // все локальные описания
|
||||
|
||||
private List<var_def_statement> LocalDeletedVS = new List<var_def_statement>(); // var_statement's, потом объединим с LocalDeletedVD для верного порядка
|
||||
|
||||
public ISet<string> LocalDeletedDefsNames = new HashSet<string>(); // их имена - для быстрого поиска
|
||||
|
||||
public ISet<ident> CollectedLocals = new HashSet<ident>(); // SSM - не очень понимаю, зачем хранить строки, identы и
|
||||
|
||||
public IEnumerable<var_def_statement> LocalDeletedDefs
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<var_def_statement>(LocalDeletedVD.Union(LocalDeletedVS));
|
||||
}
|
||||
}
|
||||
|
||||
public MoveAllLocalDefsToLists() // надо запускать этот визитор начиная с корня подпрограммы
|
||||
{
|
||||
}
|
||||
|
||||
public static MoveAllLocalDefsToLists New
|
||||
{
|
||||
get { return new MoveAllLocalDefsToLists(); }
|
||||
}
|
||||
|
||||
public static MoveAllLocalDefsToLists Accept(procedure_definition pd)
|
||||
{
|
||||
var n = New;
|
||||
n.ProcessNode(pd);
|
||||
return n;
|
||||
}
|
||||
|
||||
public override void visit(var_statement vs) // локальные описания внутри процедуры
|
||||
{
|
||||
LocalDeletedVS.Insert(0, vs.var_def);
|
||||
//DeleteInStatementList(vs);
|
||||
|
||||
// frninja 02/03/16 - fix capturing unknown idents -> replace delete with assign
|
||||
if ((object)vs.var_def.inital_value == null)
|
||||
{
|
||||
DeleteInStatementList(vs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Нескольких переменных тут всё равно не будет - это ошибка
|
||||
ReplaceStatement(vs, SeqStatements(vs.var_def.vars.idents.Select(id => new assign(id, vs.var_def.inital_value)).ToArray()));
|
||||
}
|
||||
|
||||
LocalDeletedDefsNames.UnionWith(vs.var_def.vars.idents.Select(id => id.name));
|
||||
CollectedLocals.UnionWith(vs.var_def.vars.idents);
|
||||
}
|
||||
|
||||
public override void visit(variable_definitions vd) // описания до begin
|
||||
{
|
||||
foreach (var v in vd.list)
|
||||
{
|
||||
LocalDeletedVD.Insert(0, v); //.Add(v);
|
||||
LocalDeletedDefsNames.UnionWith(v.vars.idents.Select(id => id.name));
|
||||
}
|
||||
var d = UpperNodeAs<declarations>();
|
||||
d.defs.Remove(vd); // может ли остаться список declarations пустым?
|
||||
|
||||
// frninja 03/03/16 - переносим объявления переменных c initial_value в тело метода для дальнейшей обработки
|
||||
var methodBody = UpperTo<block>().program_code;
|
||||
|
||||
methodBody.list.InsertRange(0, vd.list
|
||||
.Where(vds => (object)vds.inital_value != null)
|
||||
.SelectMany(vdsInit => vdsInit.vars.list.Select(id => new assign(id, vdsInit.inital_value))));
|
||||
|
||||
// еще - не заходить в лямбды
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
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 DeleteLocalDefs : BaseChangeVisitor
|
||||
{
|
||||
public List<var_def_statement> LocalDeletedIds = new List<var_def_statement>();
|
||||
public List<var_def_statement> BlockDeletedIds = new List<var_def_statement>();
|
||||
public HashSet<string> idsToDelete;
|
||||
public HashSet<string> deletedIdsToDeleteInLocalScope = new HashSet<string>(); // одно множество и на Local и на Block
|
||||
|
||||
public DeleteLocalDefs(HashSet<string> ids) // надо запускать этот визитор начиная с корня подпрограммы
|
||||
{
|
||||
idsToDelete = ids;
|
||||
}
|
||||
public override void visit(var_statement vs)
|
||||
{
|
||||
var idents = vs.var_def.vars.idents;
|
||||
|
||||
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления
|
||||
if (IdentsToDeleteInVarDef.Count != 0)
|
||||
{
|
||||
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания
|
||||
|
||||
LocalDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vs.var_def.vars_type, vs.var_def.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
|
||||
idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления
|
||||
|
||||
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope);
|
||||
|
||||
if (idents.Count == 0) // то и весь var_statement надо убить
|
||||
this.DeleteInStatementList(vs);
|
||||
}
|
||||
// Здесь мы не обрабатываем вложенный var_def_statement, поэтому когда мы будем обрабатывать его в другом visit, то это будут переменные до beginа подпрограммы или основной программы
|
||||
}
|
||||
public override void visit(var_def_statement vd)
|
||||
{
|
||||
var idents = vd.vars.idents;
|
||||
|
||||
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления
|
||||
if (IdentsToDeleteInVarDef.Count != 0)
|
||||
{
|
||||
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания
|
||||
|
||||
BlockDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vd.vars_type, vd.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
|
||||
idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления
|
||||
|
||||
if (idents.Count == 0)
|
||||
{
|
||||
// Выше - variable_definitions, еще выше - declarations
|
||||
var uvdsl = UpperNodeAs<variable_definitions>();
|
||||
uvdsl.var_definitions.Remove(vd);
|
||||
if (uvdsl.var_definitions.Count == 0)
|
||||
{
|
||||
var d = UpperNodeAs<declarations>(2);
|
||||
d.defs.Remove(uvdsl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void AfterProcTraverse()
|
||||
{
|
||||
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
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 LocalVariablesTypeDetectorHelperVisior : BaseChangeVisitor
|
||||
{
|
||||
public List<var_def_statement> LocalDeletedDefs = new List<var_def_statement>(); // variable_definitions - описания до начала блока
|
||||
|
||||
public List<var_def_statement> LocalDeletedVS = new List<var_def_statement>(); // var_statement's - внутриблочные описания
|
||||
|
||||
public LocalVariablesTypeDetectorHelperVisior()
|
||||
{
|
||||
}
|
||||
|
||||
public override void visit(yield_variable_definitions_with_unknown_type yvds)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
public override void visit(var_statement vs) // локальные описания внутри процедуры
|
||||
{
|
||||
|
||||
LocalDeletedVS.Insert(0, vs.var_def);
|
||||
|
||||
//ReplaceStatement(vs, new yield_var_def_statement_with_unknown_type(vs.var_def));
|
||||
}
|
||||
|
||||
public override void visit(variable_definitions vd)
|
||||
{
|
||||
foreach (var v in vd.list)
|
||||
{
|
||||
LocalDeletedDefs.Insert(0, v);
|
||||
}
|
||||
|
||||
//Replace(vd, new yield_variable_definitions_with_unknown_type(vd));
|
||||
|
||||
// еще - не заходить в лямбды
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,470 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class VarNames
|
||||
{
|
||||
public string VarName { get; set; }
|
||||
public string VarEndName { get; set; }
|
||||
|
||||
public VarNames()
|
||||
{
|
||||
}
|
||||
|
||||
public VarNames(string varName, string varEndName)
|
||||
{
|
||||
VarName = varName;
|
||||
VarEndName = varEndName;
|
||||
}
|
||||
}
|
||||
|
||||
public class LoweringVisitor : BaseChangeVisitor
|
||||
{
|
||||
public static LoweringVisitor New
|
||||
{
|
||||
get { return new LoweringVisitor(); }
|
||||
}
|
||||
|
||||
private int _varnum = 0;
|
||||
private int _foreachCollectionNum = 0;
|
||||
private int _enumeratorNum = 0;
|
||||
|
||||
private VarNames NewVarNames(ident name)
|
||||
{
|
||||
_varnum++;
|
||||
return new VarNames()
|
||||
{
|
||||
VarName = "$" + name.name + _varnum,
|
||||
VarEndName = "<>varLV" + _varnum
|
||||
};
|
||||
}
|
||||
|
||||
private ident NewEnumeratorName()
|
||||
{
|
||||
++_enumeratorNum;
|
||||
return "$enumerator$" + _enumeratorNum;
|
||||
}
|
||||
|
||||
private ident NewForeachCollectionName()
|
||||
{
|
||||
++_foreachCollectionNum;
|
||||
return "$coll$" + _foreachCollectionNum;
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
base.Enter(st);
|
||||
if (!(st is procedure_definition || st is block || st is statement_list || st is case_node || st is for_node || st is foreach_stmt || st is if_node || st is repeat_node || st is while_node || st is with_statement || st is try_stmt || st is lock_stmt))
|
||||
{
|
||||
//visitNode = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void visit(yield_unknown_foreach_type _unk)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
// frninja 21/05/16
|
||||
public override void visit(foreach_stmt frch)
|
||||
{
|
||||
// Полный код Loweringа c yield_unknown_foreach_type = integer
|
||||
// var a: System.Collections.Generic.IEnumerable<integer>;
|
||||
// a := l;
|
||||
// var en := a.GetEnumerator();
|
||||
// while en.MoveNext do
|
||||
// begin
|
||||
// var curr := en.Current; // var не нужно ставить если curr была описана раньше
|
||||
// Print(curr);
|
||||
// end;
|
||||
///
|
||||
|
||||
// var a: System.Collections.Generic.IEnumerable<yield_unknown_foreach_type> := l;
|
||||
var foreachCollIdent = this.NewForeachCollectionName();
|
||||
var foreachCollType = new template_type_reference(new named_type_reference("System.Collections.Generic.IEnumerable"),
|
||||
new template_param_list(new yield_unknown_foreach_type(frch)));
|
||||
var foreachCollVarDef = new var_statement(foreachCollIdent, foreachCollType);
|
||||
|
||||
var ass = new assign(foreachCollIdent, frch.in_what);
|
||||
|
||||
// var en := a.GetEnumerator();
|
||||
var enumeratorIdent = this.NewEnumeratorName();
|
||||
var enumeratorVarDef = new var_statement(enumeratorIdent, new method_call(new dot_node(foreachCollIdent, new ident("GetEnumerator")), new expression_list()));
|
||||
|
||||
//var curr := en.Current;
|
||||
// Переменная цикла foreach. Есть три варианта:
|
||||
// 1. foreach x in l do -> curr := en.Current;
|
||||
// 2. foreach var x in l do -> var curr := en.Current;
|
||||
// 3. foreach var x: T in l do -> var curr: T := en.Current;
|
||||
var currentIdent = frch.identifier;
|
||||
statement st = null;
|
||||
|
||||
var curExpr = new dot_node(enumeratorIdent, "Current");
|
||||
|
||||
// С типом
|
||||
if (frch.type_name == null) // 1. foreach x in l do -> curr := en.Current;
|
||||
{
|
||||
st = new assign(currentIdent, curExpr);
|
||||
}
|
||||
else if (frch.type_name is no_type_foreach) // 2. foreach var x in l do -> var curr := en.Current;
|
||||
{
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
frch.visit(replacerVis);
|
||||
|
||||
st = new var_statement(currentIdent, curExpr);
|
||||
}
|
||||
else // 3. foreach var x: T in l do -> var curr: T := en.Current;
|
||||
{
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
frch.visit(replacerVis);
|
||||
|
||||
st = new var_statement(currentIdent, frch.type_name, curExpr);
|
||||
}
|
||||
|
||||
// Добавляем тело цикла в stl
|
||||
var stl = new statement_list(st);
|
||||
ProcessNode(frch.stmt); // для обработки вложенных конструкций
|
||||
stl.Add(frch.stmt);
|
||||
|
||||
var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
|
||||
stl,
|
||||
WhileCycleType.While);
|
||||
|
||||
var sq = SeqStatements(foreachCollVarDef, ass, enumeratorVarDef, whileNode);
|
||||
|
||||
ReplaceStatement(frch,sq);
|
||||
|
||||
visit(whileNode); // Lowering оставшегося whileNode
|
||||
|
||||
//var sl = UpperNodeAs<statement_list>();
|
||||
//ProcessNode(sl); // необходимо еще lowerить while - как это сделать лучше - пока не знаю
|
||||
}
|
||||
|
||||
private expression CreateConditionFromCaseVariant(expression param, expression_list list)
|
||||
{
|
||||
var res = list.expressions.Aggregate(new bool_const(false) as expression, (acc, expr) =>
|
||||
{
|
||||
bin_expr currentExpr = null;
|
||||
diapason_expr diap = expr as diapason_expr;
|
||||
if (diap != null)
|
||||
{
|
||||
currentExpr = new bin_expr(new bin_expr(param, diap.left, Operators.GreaterEqual),
|
||||
new bin_expr(param, diap.right, Operators.LessEqual),
|
||||
Operators.LogicalAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentExpr = new bin_expr(param, expr, Operators.Equal);
|
||||
}
|
||||
|
||||
return new bin_expr(acc, currentExpr, Operators.LogicalOR);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// frninja 30/05/16
|
||||
public override void visit(case_node csn)
|
||||
{
|
||||
var b = HasStatementVisitor<yield_node>.Has(csn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
/*
|
||||
*
|
||||
* case i of
|
||||
* cv1: bla1;
|
||||
* cv2: bla2;
|
||||
* ..
|
||||
* cvN: blaN;
|
||||
* else: bla_else;
|
||||
*
|
||||
* --->
|
||||
*
|
||||
* if i satisfy cv1
|
||||
* then bla1
|
||||
* else if i satisfy cv2
|
||||
* then bla2
|
||||
* ..
|
||||
* else if i satisfy cvN
|
||||
* then blaN
|
||||
* else bla_else
|
||||
*
|
||||
*/
|
||||
|
||||
if_node currentIfNode = null;
|
||||
statement currentIfElseClause = (csn.else_statement != null) ? csn.else_statement :new statement_list(new empty_statement()); ;
|
||||
|
||||
for (int i = csn.conditions.variants.Count - 1; i >= 0; --i)
|
||||
{
|
||||
case_variant cv = csn.conditions.variants[i];
|
||||
|
||||
ProcessNode(cv.exec_if_true);
|
||||
|
||||
var ifCondition = this.CreateConditionFromCaseVariant(csn.param, cv.conditions);
|
||||
currentIfNode = new if_node(ifCondition, new statement_list(cv.exec_if_true), new statement_list(currentIfElseClause));
|
||||
currentIfElseClause = currentIfNode;
|
||||
}
|
||||
|
||||
if_node finalIfNode = currentIfNode;
|
||||
|
||||
if (finalIfNode==null) // SSM - значит, в цикл мы не заходили и у case отсутствуют все ветви кроме else - поскольку yieldы в case есть
|
||||
{
|
||||
ReplaceStatement(csn, csn.else_statement);
|
||||
}
|
||||
else
|
||||
ReplaceStatement(csn, finalIfNode);
|
||||
|
||||
if (finalIfNode!=null)
|
||||
visit(finalIfNode);
|
||||
}
|
||||
|
||||
public override void visit(if_node ifn)
|
||||
{
|
||||
ProcessNode(ifn.then_body);
|
||||
ProcessNode(ifn.else_body);
|
||||
|
||||
var b = HasStatementVisitor<yield_node>.Has(ifn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
var gtAfter = goto_statement.New;
|
||||
var lbAfter = new labeled_statement(gtAfter.label);
|
||||
|
||||
if ((object)ifn.else_body == null)
|
||||
{
|
||||
var if0 = new if_node(un_expr.Not(ifn.condition), gtAfter);
|
||||
//Replace(ifn, SeqStatements(gotoStartIfCondition, ifn.then_body, lbAfter));
|
||||
ReplaceStatement(ifn, SeqStatements(if0, ifn.then_body, lbAfter));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gtAfter.label));
|
||||
}
|
||||
else
|
||||
{
|
||||
var gtAlt = goto_statement.New;
|
||||
var lbAlt = new labeled_statement(gtAlt.label, ifn.else_body);
|
||||
|
||||
var if0 = new if_node(un_expr.Not(ifn.condition), gtAlt);
|
||||
|
||||
ReplaceStatement(ifn, SeqStatements(if0, ifn.then_body, gtAfter, lbAlt, lbAfter));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gtAfter.label, gtAlt.label));
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(repeat_node rn)
|
||||
{
|
||||
var b = HasStatementVisitor<yield_node>.Has(rn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
var gotoContinue = goto_statement.New;
|
||||
var gotoBreak = goto_statement.New;
|
||||
|
||||
ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);
|
||||
rn.statements.visit(replaceBreakContinueVis);
|
||||
|
||||
ProcessNode(rn.statements);
|
||||
|
||||
var gotoContinueIfNotCondition = new if_node(un_expr.Not(rn.expr), gotoContinue);
|
||||
var continueLabeledStatement = new labeled_statement(gotoContinue.label, new statement_list(rn.statements, gotoContinueIfNotCondition));
|
||||
|
||||
var breakLabeledStatement = new labeled_statement(gotoBreak.label);
|
||||
|
||||
|
||||
ReplaceStatement(rn, SeqStatements(gotoContinue, continueLabeledStatement, breakLabeledStatement));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gotoContinue.label, gotoBreak.label));
|
||||
|
||||
}
|
||||
|
||||
public override void visit(while_node wn)
|
||||
{
|
||||
var b = HasStatementVisitor<yield_node>.Has(wn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
var gotoBreak = goto_statement.New;
|
||||
var gotoContinue = goto_statement.New;
|
||||
|
||||
ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);
|
||||
wn.statements.visit(replaceBreakContinueVis);
|
||||
|
||||
ProcessNode(wn.statements);
|
||||
|
||||
var if0 = new if_node(un_expr.Not(wn.expr), gotoBreak);
|
||||
var lb2 = new labeled_statement(gotoContinue.label, if0); // continue
|
||||
var lb1 = new labeled_statement(gotoBreak.label); // break
|
||||
|
||||
ReplaceStatement(wn, SeqStatements(lb2, wn.statements, gotoContinue, lb1));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gotoBreak.label, gotoContinue.label));
|
||||
}
|
||||
|
||||
|
||||
public override void visit(for_node fn)
|
||||
{
|
||||
var b = HasStatementVisitor<yield_node>.Has(fn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
var gotoContinue = goto_statement.New;
|
||||
var gotoBreak = goto_statement.New;
|
||||
var gotoStart = goto_statement.New;
|
||||
|
||||
ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoContinue, gotoBreak);
|
||||
fn.statements.visit(replaceBreakContinueVis);
|
||||
|
||||
ProcessNode(fn.statements);
|
||||
|
||||
var newNames = this.NewVarNames(fn.loop_variable);
|
||||
|
||||
var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;
|
||||
|
||||
// Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
|
||||
var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);
|
||||
fn.visit(replacerVis);
|
||||
|
||||
fn.loop_variable = newLoopVar;
|
||||
|
||||
var endtemp = new ident(newNames.VarEndName); //new ident(newVarName());
|
||||
|
||||
//var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
|
||||
//var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
|
||||
//var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);
|
||||
|
||||
// frninja 05/06/16 - фиксим для !fn.create_variable
|
||||
var ass1 = fn.create_loop_variable
|
||||
? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement
|
||||
: new assign(fn.loop_variable, fn.initial_value) as statement;
|
||||
|
||||
|
||||
var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ?
|
||||
bin_expr.Greater(fn.loop_variable, fn.finish_value) :
|
||||
bin_expr.Less(fn.loop_variable, fn.finish_value), gotoBreak);
|
||||
|
||||
var lb2 = new labeled_statement(gotoStart.label, if0);
|
||||
var lb1 = new labeled_statement(gotoBreak.label);
|
||||
var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
|
||||
new ident("Inc") :
|
||||
new ident("Dec"), new expression_list(fn.loop_variable)));
|
||||
|
||||
var lbInc = new labeled_statement(gotoContinue.label, Inc);
|
||||
|
||||
ReplaceStatement(fn, SeqStatements(ass1, lb2, fn.statements, lbInc, gotoStart, lb1));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gotoContinue.label, gotoBreak.label, gotoStart.label));
|
||||
}
|
||||
|
||||
/*
|
||||
public override void visit(for_node fn)
|
||||
{
|
||||
|
||||
* initializer;
|
||||
* goto end;
|
||||
* start:
|
||||
* body;
|
||||
* continue:
|
||||
* increment;
|
||||
* end:
|
||||
* GotoIfTrue condition start;
|
||||
* break:
|
||||
|
||||
|
||||
|
||||
var b = HasStatementVisitor<yield_node>.Has(fn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
var gotoStart = goto_statement.New;
|
||||
var gotoEnd = goto_statement.New;
|
||||
var gotoStart = goto_statement.New;
|
||||
var gotoBreak = goto_statement.New;
|
||||
|
||||
ReplaceBreakContinueWithGotoLabelVisitor replaceBreakContinueVis = new ReplaceBreakContinueWithGotoLabelVisitor(gotoStart, gotoBreak);
|
||||
fn.statements.visit(replaceBreakContinueVis);
|
||||
|
||||
ProcessNode(fn.statements);
|
||||
|
||||
|
||||
var newNames = this.NewVarNames(fn.loop_variable);
|
||||
|
||||
var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;
|
||||
|
||||
// Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
|
||||
var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);
|
||||
fn.visit(replacerVis);
|
||||
|
||||
fn.loop_variable = newLoopVar;
|
||||
|
||||
var endtemp = new ident(newNames.VarEndName); //new ident(newVarName());
|
||||
|
||||
//var initializer = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
|
||||
//var initializer = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
|
||||
//var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);
|
||||
|
||||
// frninja 05/06/16 - фиксим для !fn.create_variable
|
||||
var initializer = fn.create_loop_variable
|
||||
? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement
|
||||
: new assign(fn.loop_variable, fn.initial_value) as statement;
|
||||
|
||||
|
||||
var gotoStartIfCondition = new if_node((fn.cycle_type == for_cycle_type.to) ?
|
||||
new bin_expr(fn.loop_variable, fn.finish_value, Operators.LessEqual) :
|
||||
new bin_expr(fn.loop_variable, fn.finish_value, Operators.GreaterEqual), gotoStart);
|
||||
|
||||
var endLabeledStatement = new labeled_statement(gotoEnd.label, gotoStartIfCondition);
|
||||
var startLabeledStatement = new labeled_statement(gotoStart.label, fn.statements);
|
||||
var Inc = new procedure_call(new method_call((fn.cycle_type == for_cycle_type.to) ?
|
||||
new ident("Inc") :
|
||||
new ident("Dec"), new expression_list(fn.loop_variable)));
|
||||
|
||||
var continueLabeledStatement = new labeled_statement(gotoStart.label, Inc);
|
||||
var breakLabeledStatement = new labeled_statement(gotoBreak.label);
|
||||
|
||||
ReplaceStatement(fn, SeqStatements(initializer, gotoEnd, startLabeledStatement, continueLabeledStatement, endLabeledStatement, breakLabeledStatement));
|
||||
|
||||
// в declarations ближайшего блока добавить описание labels
|
||||
block bl = listNodes.FindLast(x => x is block) as block;
|
||||
|
||||
bl.defs.Add(new label_definitions(gotoStart.label, gotoEnd.label, gotoStart.label, gotoBreak.label));
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class MarkMethodHasYieldAndCheckSomeErrorsVisitor : WalkingVisitorNew
|
||||
{
|
||||
private bool HasYields = false;
|
||||
private procedure_definition CurrentMethod = null;
|
||||
|
||||
private Stack<procedure_definition> MethodsStack = new Stack<procedure_definition>();
|
||||
|
||||
public override void visit(function_lambda_definition ld)
|
||||
{
|
||||
if (ld.DescendantNodes().OfType<yield_node>().Count() > 0)
|
||||
{
|
||||
throw new SyntaxError("Лямбда-выражения не могут содержать yield", "", ld.source_context, ld);
|
||||
}
|
||||
|
||||
//base.visit(ld); // SSM 15/07/16 - незачем обходить внутренности лямбды - мы и так ищем внутри них yield - этого в этом визиторе достаточно
|
||||
}
|
||||
|
||||
public override void visit(with_statement ws)
|
||||
{
|
||||
if (ws.DescendantNodes().OfType<yield_node>().Count() > 0)
|
||||
{
|
||||
throw new SyntaxError("Yield запрещен внутри with", "", ws.source_context, ws);
|
||||
}
|
||||
base.visit(ws);
|
||||
}
|
||||
|
||||
|
||||
public override void visit(procedure_definition pd)
|
||||
{
|
||||
//this.CurrentMethod = pd;
|
||||
|
||||
MethodsStack.Push(pd);
|
||||
|
||||
HasYields = false;
|
||||
|
||||
base.visit(pd);
|
||||
pd.has_yield = HasYields;
|
||||
|
||||
if (pd.has_yield) // SSM bug fix #219
|
||||
{
|
||||
var ee = pd.proc_body as block;
|
||||
if (ee != null)
|
||||
{
|
||||
var FirstTypeDeclaration = ee.defs.DescendantNodes().OfType<type_declarations>().First();
|
||||
if (FirstTypeDeclaration != null)
|
||||
{
|
||||
throw new SyntaxError("Функции с yield не могут содержать локальные определения типов", "", FirstTypeDeclaration.source_context, FirstTypeDeclaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var innerPds = pd.DescendantNodes().OfType<procedure_definition>();
|
||||
|
||||
if (pd.has_yield && innerPds.Count() > 0
|
||||
|| innerPds.Where(npd => npd.has_yield).Count() > 0)
|
||||
{
|
||||
// Есть yield и вложенные - плохо
|
||||
// Или нет yield но есть вложенные с yield
|
||||
throw new SyntaxError("Функции с yield не могут содержать вложенных подпрограмм result", "", pd.source_context, pd);
|
||||
}
|
||||
|
||||
if (pd.has_yield && pd.DescendantNodes().OfType<try_stmt>().Count() > 0)
|
||||
{
|
||||
throw new SyntaxError("Функции с yield не могут содержать блоков try..except..finally", "", pd.source_context, pd);
|
||||
}
|
||||
|
||||
if (pd.has_yield && pd.DescendantNodes().OfType<lock_stmt>().Count() > 0)
|
||||
{
|
||||
throw new SyntaxError("Функции с yield не могут содержать lock", "", pd.source_context, pd);
|
||||
}
|
||||
|
||||
HasYields = false;
|
||||
|
||||
MethodsStack.Pop();
|
||||
|
||||
//this.CurrentMethod = null;
|
||||
}
|
||||
|
||||
public override void visit(ident id)
|
||||
{
|
||||
//if (CurrentMethod == null || !HasYields)
|
||||
if (MethodsStack.Count == 0 || !HasYields)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (id.name.ToLower() == "result")
|
||||
{
|
||||
throw new SyntaxError("Функции с yield не могут использовать result", "", id.source_context, id);
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(dot_node dn)
|
||||
{
|
||||
ProcessNode(dn.left);
|
||||
if (dn.right.GetType() != typeof(ident))
|
||||
ProcessNode(dn.right);
|
||||
}
|
||||
|
||||
public override void visit(yield_node yn)
|
||||
{
|
||||
//var pd = CurrentMethod;
|
||||
var pd = MethodsStack.Peek();
|
||||
|
||||
if (pd == null)
|
||||
throw new SyntaxError("Только функции могут содержать yield", "", yn.source_context, yn);
|
||||
|
||||
var fh = (pd.proc_header as function_header);
|
||||
if (fh == null)
|
||||
throw new SyntaxError("Только функции могут содержать yield", "", pd.proc_header.source_context, pd.proc_header);
|
||||
var seqt = fh.return_type as sequence_type;
|
||||
if (seqt == null)
|
||||
throw new SyntaxError("Функции с yield должны возвращать последовательность", "", fh.source_context, fh);
|
||||
|
||||
var pars = fh.parameters;
|
||||
if (pars != null)
|
||||
foreach (var ps in pars.params_list)
|
||||
{
|
||||
if (ps.param_kind != parametr_kind.none)
|
||||
throw new SyntaxError("В параметрах функции с yield не должно быть модификаторов 'var', 'const' или 'params'", "", pars.source_context, pars);
|
||||
if (ps.inital_value != null)
|
||||
throw new SyntaxError("Параметры функции с yield не должны иметь начальных значений", "", pars.source_context, pars);
|
||||
}
|
||||
|
||||
HasYields = true;
|
||||
|
||||
base.visit(yn);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,181 +0,0 @@
|
|||
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 RenameSameBlockLocalVarsVisitor : BaseChangeVisitor
|
||||
{
|
||||
// Надо хранить принадлежность имени конкретному ПИ на определенном уровне вложенности
|
||||
// И отображение этого имени в новое
|
||||
|
||||
// Map :: CurrentLevel -> { BlockName -> NewBlockName }
|
||||
private List<Dictionary<string, string>> BlockNamesStack { get; set; }
|
||||
|
||||
private Dictionary<string, int> BlockNamesCounter { get; set; }
|
||||
|
||||
|
||||
private int CurrentLevel = -1;
|
||||
|
||||
public RenameSameBlockLocalVarsVisitor()
|
||||
{
|
||||
this.BlockNamesStack = new List<Dictionary<string, string>>();
|
||||
this.BlockNamesCounter = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
public static RenameSameBlockLocalVarsVisitor New
|
||||
{
|
||||
get { return new RenameSameBlockLocalVarsVisitor(); }
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
}
|
||||
|
||||
public override void visit(declarations decls)
|
||||
{
|
||||
// Для обхода в правильном порядке сверху вниз
|
||||
var vd_s = decls.defs.OfType<variable_definitions>().ToArray();
|
||||
for (int i = 0; i < vd_s.Count(); ++i)
|
||||
{
|
||||
ProcessNode(vd_s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(procedure_header pd)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
public override void visit(function_header fh)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
public override void visit(formal_parameters fp)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
public override void visit(statement_list stlist)
|
||||
{
|
||||
++CurrentLevel;
|
||||
|
||||
if (BlockNamesStack.Count <= CurrentLevel)
|
||||
{
|
||||
// Создаем отображение для имен текущего уровня вложенности мини-пространства имен
|
||||
BlockNamesStack.Add(new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
//base.visit(stlist);
|
||||
for (var i = 0; i < stlist.list.Count; ++i)
|
||||
ProcessNode(stlist.list[i]);
|
||||
|
||||
BlockNamesStack.RemoveAt(BlockNamesStack.Count - 1);
|
||||
|
||||
--CurrentLevel;
|
||||
}
|
||||
|
||||
public override void visit(var_statement vs)
|
||||
{
|
||||
if (vs.var_def.vars.idents.Any(id => id.name.StartsWith("$")))
|
||||
{
|
||||
base.visit(vs); // SSM 17/07/16 исправление ошибки - не обходилось выражение-инициализатор
|
||||
return;
|
||||
}
|
||||
|
||||
var newLocalNames = vs.var_def.vars.idents.Select(id =>
|
||||
{
|
||||
var newName = this.CreateNewVariableName(id.name);
|
||||
BlockNamesStack[CurrentLevel].Add(id.name, newName);
|
||||
return new ident(newName, id.source_context);
|
||||
});
|
||||
|
||||
var newVS = new var_statement(new var_def_statement(new ident_list(newLocalNames.ToArray()),
|
||||
vs.var_def.vars_type,
|
||||
vs.var_def.inital_value));
|
||||
|
||||
Replace(vs, newVS);
|
||||
|
||||
base.visit(newVS);
|
||||
}
|
||||
|
||||
public override void visit(variable_definitions vd)
|
||||
{
|
||||
if (vd.var_definitions.Any(vds => vds.vars.idents.Any(id => id.name.StartsWith("$"))))
|
||||
return;
|
||||
|
||||
++CurrentLevel;
|
||||
|
||||
if (BlockNamesStack.Count <= CurrentLevel)
|
||||
{
|
||||
// Создаем отображение для имен текущего уровня вложенности мини-пространства имен
|
||||
BlockNamesStack.Add(new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
var newVD = new variable_definitions(
|
||||
vd.var_definitions.Select(vds =>
|
||||
{
|
||||
var newLocalNames = vds.vars.idents.Select(id =>
|
||||
{
|
||||
var newName = this.CreateNewVariableName(id.name);
|
||||
BlockNamesStack[CurrentLevel].Add(id.name, newName);
|
||||
return new ident(newName, id.source_context);
|
||||
});
|
||||
|
||||
return new var_def_statement(new ident_list(newLocalNames.ToArray()), vds.vars_type, vds.inital_value);
|
||||
}).ToList(),
|
||||
vd.source_context);
|
||||
|
||||
Replace(vd, newVD);
|
||||
base.visit(newVD);
|
||||
}
|
||||
|
||||
public override void visit(ident id)
|
||||
{
|
||||
var newName = this.GetNewVariableName(id.name);
|
||||
if ((object)newName != null)
|
||||
{
|
||||
Replace(id, new ident(newName, id.source_context));
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(dot_node dn)
|
||||
{
|
||||
ProcessNode(dn.left);
|
||||
if (dn.right.GetType() != typeof(ident))
|
||||
ProcessNode(dn.right);
|
||||
}
|
||||
|
||||
private string CreateNewVariableName(string name)
|
||||
{
|
||||
if (BlockNamesCounter.ContainsKey(name))
|
||||
{
|
||||
++BlockNamesCounter[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockNamesCounter.Add(name, 0);
|
||||
}
|
||||
return "$" + name + "__" + BlockNamesCounter[name];
|
||||
}
|
||||
|
||||
private string GetNewVariableName(string name)
|
||||
{
|
||||
for (int i = CurrentLevel; i >= 0; --i)
|
||||
{
|
||||
if (BlockNamesStack[i].ContainsKey(name))
|
||||
{
|
||||
return BlockNamesStack[i][name];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class ReplaceBreakContinueWithGotoLabelVisitor : BaseChangeVisitor
|
||||
{
|
||||
public goto_statement GotoContinue { get; private set; }
|
||||
public goto_statement GotoBreak { get; private set; }
|
||||
|
||||
public ReplaceBreakContinueWithGotoLabelVisitor(goto_statement gotoContinue, goto_statement gotoBreak)
|
||||
{
|
||||
this.GotoContinue = gotoContinue;
|
||||
this.GotoBreak = gotoBreak;
|
||||
}
|
||||
|
||||
public override void Enter(syntax_tree_node st)
|
||||
{
|
||||
base.Enter(st);
|
||||
// Не заходим во вложенные циклы, там свои break-continue
|
||||
if ((st is for_node || st is foreach_stmt || st is while_node || st is repeat_node))
|
||||
{
|
||||
visitNode = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void visit(procedure_call pc)
|
||||
{
|
||||
var pcIdent = pc.func_name as ident;
|
||||
if (pcIdent != null)
|
||||
{
|
||||
var pcName = pcIdent.name.ToLower();
|
||||
if (pcName == "break")
|
||||
{
|
||||
Replace(pc, this.GotoBreak);
|
||||
}
|
||||
else if (pcName == "continue")
|
||||
{
|
||||
Replace(pc, this.GotoContinue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
using PascalABCCompiler.YieldHelpers;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class ReplaceCapturedVariablesVisitor : BaseChangeVisitor
|
||||
{
|
||||
private ISet<string> CollectedLocals = new HashSet<string>();
|
||||
private ISet<string> CollectedFormalParams = new HashSet<string>();
|
||||
private ISet<string> CollectedClassFields = new HashSet<string>();
|
||||
private ISet<string> CollectedUnitGlobals = new HashSet<string>();
|
||||
|
||||
// Maps :: idName -> capturedName
|
||||
private IDictionary<string, string> CapturedLocalsMap = new Dictionary<string, string>();
|
||||
private IDictionary<string, string> CapturedFormalParamsMap = new Dictionary<string, string>();
|
||||
|
||||
private bool IsInClassMethod = true;
|
||||
private bool IsStaticMethod = false;
|
||||
|
||||
private ident ClassName;
|
||||
|
||||
|
||||
public ReplaceCapturedVariablesVisitor(IEnumerable<string> locals,
|
||||
IEnumerable<string> formalParams,
|
||||
IEnumerable<string> classFields,
|
||||
IEnumerable<string> classMethods,
|
||||
IEnumerable<string> classProperties,
|
||||
IEnumerable<string> unitGlobals,
|
||||
IDictionary<string, string> localsMap,
|
||||
IDictionary<string, string> formalParamsMap,
|
||||
bool isInClassMethod, bool isStaticMethod, ident className)
|
||||
{
|
||||
CollectedLocals = new HashSet<string>(locals);
|
||||
CollectedFormalParams = new HashSet<string>(formalParams);
|
||||
CollectedClassFields = new HashSet<string>(classFields);
|
||||
CollectedUnitGlobals = new HashSet<string>(unitGlobals);
|
||||
|
||||
CapturedLocalsMap = new Dictionary<string, string>(localsMap);
|
||||
CapturedFormalParamsMap = new Dictionary<string, string>(formalParamsMap);
|
||||
|
||||
IsInClassMethod = isInClassMethod;
|
||||
ClassName = className;
|
||||
|
||||
// Methods hack
|
||||
CollectedClassFields.UnionWith(classMethods);
|
||||
// Properties hack
|
||||
CollectedClassFields.UnionWith(classProperties);
|
||||
|
||||
}
|
||||
|
||||
public override void visit(labeled_statement ls)
|
||||
{
|
||||
ProcessNode(ls.to_statement);
|
||||
}
|
||||
|
||||
public override void visit(goto_statement gt)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
// frninja 12/05/16 - фикс для yield_unknown_ident
|
||||
public override void visit(yield_unknown_ident unk)
|
||||
{
|
||||
//yield_var_def_statement_with_unknown_type x;
|
||||
// Empty
|
||||
}
|
||||
|
||||
public override void visit(ident id)
|
||||
{
|
||||
// Check dot node
|
||||
var upper = UpperNode(1);
|
||||
//if (upper is dot_node)
|
||||
// return;
|
||||
|
||||
var idName = id.name;
|
||||
var idSourceContext = id.source_context;
|
||||
|
||||
// frninja 31/03/16 - фикс селфа для extensionmethod
|
||||
if (idName.ToLower() == "self" && !CollectedFormalParams.Contains(idName))
|
||||
{
|
||||
var newSelf = new dot_node(new ident("self"), new ident(YieldConsts.Self));
|
||||
Replace(id, newSelf);
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect where is id from
|
||||
if (CollectedLocals.Contains(idName))
|
||||
{
|
||||
Replace(id, new ident(CapturedLocalsMap[idName], idSourceContext));
|
||||
}
|
||||
else if (CollectedFormalParams.Contains(idName))
|
||||
{
|
||||
Replace(id, new ident(CapturedFormalParamsMap[idName], idSourceContext));
|
||||
}
|
||||
else if (IsInClassMethod)
|
||||
{
|
||||
// In class -> check fields
|
||||
//if (CollectedClassFields.Contains(idName))
|
||||
{
|
||||
// Good
|
||||
// Name in class fields -> capture as class field
|
||||
|
||||
|
||||
//var capturedId = new dot_node(new dot_node(new ident("self"), new ident(YieldConsts.Self)), id);
|
||||
//Replace(id, capturedId);
|
||||
}
|
||||
//else
|
||||
{
|
||||
// Bad
|
||||
// At syntax we don't know if the className is class field or not coz of e.g. base .NET classes
|
||||
// HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic
|
||||
// Check for globals will be processed at semantic, too
|
||||
|
||||
if (!id.name.StartsWith("<")) // Check for already captured
|
||||
{
|
||||
Replace(id, new yield_unknown_ident(id, ClassName, this.IsStaticMethod));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not in class -> check globals
|
||||
if (CollectedUnitGlobals.Contains(idName))
|
||||
{
|
||||
// Global -> just do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
// What about static classes - search at semantic
|
||||
// HERE WE SHOULD REPLACE TO yield_unknown_reference -> so decision is passed to semantic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*public override void visit(procedure_call pc)
|
||||
{
|
||||
ProcessNode(pc.func_name);
|
||||
var methCall = pc.func_name as method_call;
|
||||
if ((object)methCall != null)
|
||||
{
|
||||
foreach (var param in methCall.parameters.expressions)
|
||||
{
|
||||
param.visit(this);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
public override void visit(dot_node dn)
|
||||
{
|
||||
var rid = dn.right as ident;
|
||||
if ((object)rid != null && rid.name != YieldConsts.Self)
|
||||
ProcessNode(dn.left);
|
||||
|
||||
// Most nested
|
||||
// DotNode (DLeft, DRight) -> DotNode(DotNode("self", "<>__self"), DRight)
|
||||
|
||||
|
||||
// LEFT self -> captured self (self.captured_self)
|
||||
/*var id = dn.left as ident;
|
||||
if ((object)id != null && (id.className == "self" || CollectedClassFields.Contains(id.className)))
|
||||
{
|
||||
// Some magic for blocking back-traverse from BaseChangeVisitor redoin' work
|
||||
//var rid = dn.right as ident;
|
||||
//if ((object)rid != null && rid.className != Consts.Self)
|
||||
{
|
||||
var newDotNode = new dot_node(new dot_node(new ident("self"), new ident(Consts.Self)), dn.right);
|
||||
// Change right?
|
||||
//var capturedRight = new dot_node(new ident(Consts.Self), dn.right);
|
||||
//var newDotNode = new dot_node(dn.left, capturedRight);
|
||||
Replace(dn, newDotNode);
|
||||
}
|
||||
|
||||
|
||||
// Some magic for blocking back-traverse from BaseChangeVisitor redoin' work
|
||||
//var rid = dn.right as ident;
|
||||
//if ((object)rid != null && rid.className != Consts.Self)
|
||||
// {
|
||||
// var capturedSelf = new dot_node(new ident("self"), new ident(Consts.Self));
|
||||
// Replace(dn.left, capturedSelf);
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessNode(dn.left);
|
||||
}*/
|
||||
|
||||
//if (dn.right.GetType() != typeof(ident))
|
||||
// ProcessNode(dn.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
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 ReplaceFormalParametersRefsVisitor : BaseChangeVisitor
|
||||
{
|
||||
public Dictionary<string, type_definition> CollectedFormalParameters = new Dictionary<string, type_definition>();
|
||||
|
||||
// Типа-стек соответствий paramName -> <>num__paramName для разных уровней вложенности методов
|
||||
private List<Dictionary<string, string>> formalParametersStack = new List<Dictionary<string, string>>();
|
||||
|
||||
private bool _isClassMethod = false;
|
||||
|
||||
|
||||
public ReplaceFormalParametersRefsVisitor()
|
||||
{
|
||||
}
|
||||
|
||||
// Лучше запретить yield в вложенных функциях и в функциях со вложенными!
|
||||
// Запретить-запретить-запретить
|
||||
|
||||
public override void visit(procedure_definition pd)
|
||||
{
|
||||
// var u = UpperNode(3);
|
||||
// В случае отсутствия формальных параметров
|
||||
if ((object)pd.proc_header.parameters == null)
|
||||
{
|
||||
base.visit(pd.proc_body);
|
||||
return;
|
||||
}
|
||||
|
||||
formalParametersStack.Add(new Dictionary<string, string>());
|
||||
int currentLevel = formalParametersStack.Count - 1;
|
||||
|
||||
foreach (var plist in pd.proc_header.parameters.params_list)
|
||||
{
|
||||
foreach (var id in plist.idents.idents)
|
||||
{
|
||||
var paramName = id.name;
|
||||
var hoistedParamName = CapturedNamesHelper.MakeCapturedFormalParameterName(id.name);
|
||||
|
||||
formalParametersStack[currentLevel].Add(paramName, hoistedParamName);
|
||||
|
||||
// Захват
|
||||
CollectedFormalParameters.Add(hoistedParamName, plist.vars_type);
|
||||
}
|
||||
}
|
||||
|
||||
base.visit(pd.proc_body);
|
||||
|
||||
formalParametersStack.RemoveAt(currentLevel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override void visit(ident id)
|
||||
{
|
||||
int? paramNameLevel = null;
|
||||
|
||||
var paramName = id.name;
|
||||
|
||||
// Ищем с какого уровня имя
|
||||
for (int level = formalParametersStack.Count - 1; level >= 0; --level)
|
||||
{
|
||||
if (formalParametersStack[level].ContainsKey(paramName))
|
||||
{
|
||||
// Нашли!
|
||||
paramNameLevel = level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isField = false;
|
||||
|
||||
// Локальные параметры обрабатываются в другом визиторе
|
||||
|
||||
// Параметр функции
|
||||
if ((object)paramNameLevel != null)
|
||||
{
|
||||
var upper = UpperNode();
|
||||
// Подозреваем обращение к параметру метода
|
||||
if ((object)upper == null || (object)upper != null && (upper as dot_node) == null)
|
||||
{
|
||||
// Это не self.paramName - поле класса и не что-то другое?
|
||||
// Нашли обращение к параметру?
|
||||
|
||||
var self = new ident("self", id.source_context);
|
||||
|
||||
// Заменяем paramName -> self.hoistedParamName: <>num__paramName
|
||||
|
||||
var hoistedParamName = new ident(formalParametersStack[(int)paramNameLevel][paramName], id.source_context);
|
||||
|
||||
var selfId = new dot_node(self, hoistedParamName);
|
||||
|
||||
Replace(id, selfId);
|
||||
}
|
||||
// Иначе проверить что это поле класса! self.paramName или какой-то другой очень извращенный вариант вроде (someMethod: self).paramName
|
||||
}
|
||||
|
||||
// Поле класса
|
||||
|
||||
// Параметр внешней функции (если наша - вложенная)
|
||||
|
||||
// Глобальная переменная
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
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 ReplaceVariableNameVisitor : BaseChangeVisitor
|
||||
{
|
||||
private ident _oldName;
|
||||
private ident _newName;
|
||||
|
||||
public ReplaceVariableNameVisitor(ident oldName, ident newName)
|
||||
{
|
||||
_oldName = oldName;
|
||||
_newName = newName;
|
||||
}
|
||||
|
||||
public override void visit(ident id)
|
||||
{
|
||||
if (id.name != _oldName.name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var upperNode = UpperNode();
|
||||
if (
|
||||
(object)upperNode != null && (object)(upperNode as dot_node) == null)
|
||||
{
|
||||
Replace(id, _newName);
|
||||
}
|
||||
}
|
||||
|
||||
// frninja 11/03/16 - оно тут вообще надо???
|
||||
public override void visit(dot_node dn)
|
||||
{
|
||||
ProcessNode(dn.left);
|
||||
if (dn.right.GetType() != typeof(ident))
|
||||
ProcessNode(dn.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler.Errors;
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class ReplaceYieldWithLamdasVisitor : BaseChangeVisitor
|
||||
{
|
||||
private int _lambdaNum = 0;
|
||||
|
||||
private ident NewLamdaVarName()
|
||||
{
|
||||
++_lambdaNum;
|
||||
return new ident("$lambdaVar$" + _lambdaNum);
|
||||
}
|
||||
|
||||
public static ReplaceYieldWithLamdasVisitor New
|
||||
{
|
||||
get { return new ReplaceYieldWithLamdasVisitor(); }
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
}
|
||||
|
||||
public override void visit(procedure_definition pd)
|
||||
{
|
||||
DefaultVisit(pd);
|
||||
}
|
||||
|
||||
public override void visit(statement_list st)
|
||||
{
|
||||
DefaultVisit(st);
|
||||
}
|
||||
|
||||
public override void visit(for_node fn)
|
||||
{
|
||||
DefaultVisit(fn);
|
||||
}
|
||||
|
||||
public override void visit(yield_node yn)
|
||||
{
|
||||
//var lambdaSearcher = new TreeConverter.LambdaExpressions.LambdaSearcher(yn);
|
||||
//if (lambdaSearcher.CheckIfContainsLambdas())
|
||||
{
|
||||
var lambdaVarIdent = this.NewLamdaVarName();
|
||||
var_statement lambdaVS = new var_statement(lambdaVarIdent, yn.ex) { source_context = yn.ex.source_context };
|
||||
ReplaceStatement(yn, SeqStatements(lambdaVS, new yield_node(lambdaVarIdent, yn.ex.source_context)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +48,10 @@
|
|||
<Project>{1e42361a-eda3-4872-88af-a3aaf600d36d}</Project>
|
||||
<Name>Compiler</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Errors\Errors.csproj">
|
||||
<Project>{44a01f9e-dce7-470c-aae5-c3de0ccbee3b}</Project>
|
||||
<Name>Errors</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\SyntaxTreeConverters\SyntaxTreeConverters.csproj">
|
||||
<Project>{f10a5330-dcf4-4533-877c-7b1b1be23884}</Project>
|
||||
<Name>SyntaxTreeConverters</Name>
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PascalABCCompiler;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
using PascalABCCompiler.Errors;
|
||||
|
||||
using SyntaxVisitors;
|
||||
|
||||
|
|
@ -15,6 +15,9 @@ namespace YieldDesugarSyntaxTreeConverter
|
|||
{
|
||||
public class YieldDesugarSyntaxTreeConverter : ISyntaxTreeConverter
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public List<Error> ErrorsList { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
|
@ -22,8 +25,11 @@ namespace YieldDesugarSyntaxTreeConverter
|
|||
|
||||
public ConverterType ConverterType { get; set; }
|
||||
public ExecutionOrder ExecutionOrder { get; set; }
|
||||
public syntax_tree_node Convert(syntax_tree_node root)
|
||||
public syntax_tree_node Convert(syntax_tree_node root, string FileName, List<Error> ErrorsList)
|
||||
{
|
||||
this.FileName = FileName;
|
||||
this.ErrorsList = ErrorsList;
|
||||
|
||||
root.visit(new MarkMethodHasYieldAndCheckSomeErrorsVisitor());
|
||||
root.visit(new ProcessYieldCapturedVarsVisitor());
|
||||
|
||||
|
|
|
|||
4
bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat
Normal file
4
bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Syntax tree conversion errors
|
||||
%PREFIX%=SYNTAXTREEVISITORSERROR_
|
||||
|
||||
YIELD_FUNC_MUST_RETURN_SEQUENCE=Functions with yield must return sequences
|
||||
4
bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat
Normal file
4
bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// Syntax tree conversion errors
|
||||
%PREFIX%=SYNTAXTREEVISITORSERROR_
|
||||
|
||||
YIELD_FUNC_MUST_RETURN_SEQUENCE=Функции с yield должны возвращать последовательность
|
||||
Loading…
Reference in a new issue