Перенёс SyntaxVisitors в папку первого уровня

This commit is contained in:
miks1965 2016-07-18 13:04:50 +03:00
parent e7b65c421b
commit bd19c5e385
47 changed files with 57 additions and 4511 deletions

View file

@ -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))

View file

@ -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;
}

View file

@ -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()
{

View file

@ -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>

View file

@ -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 &lt; Error &gt; 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() == &quot;result&quot;">
<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>

View file

@ -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);
}
}

View file

@ -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("")]

View file

@ -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;

View file

@ -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

View file

@ -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);
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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)
{
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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); // это обязательно!
}
}
}

View file

@ -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")]

View file

@ -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>

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;");
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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);
}
}
}
}*/
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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))));
// еще - не заходить в лямбды
}
}
}

View file

@ -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
}
}
}

View file

@ -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);
}
}
}

View file

@ -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));
// еще - не заходить в лямбды
}
}
}

View file

@ -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));
}*/
}
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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);
}
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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
}
// Поле класса
// Параметр внешней функции (если наша - вложенная)
// Глобальная переменная
}
}
}

View file

@ -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);
}
}
}

View file

@ -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)));
}
}
}
}

View file

@ -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>

View file

@ -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());

View file

@ -0,0 +1,4 @@
// Syntax tree conversion errors
%PREFIX%=SYNTAXTREEVISITORSERROR_
YIELD_FUNC_MUST_RETURN_SEQUENCE=Functions with yield must return sequences

View file

@ -0,0 +1,4 @@
// Syntax tree conversion errors
%PREFIX%=SYNTAXTREEVISITORSERROR_
YIELD_FUNC_MUST_RETURN_SEQUENCE=Функции с yield должны возвращать последовательность