В Compile() добавлен хук для преобразования синтаксических деревьев

This commit is contained in:
miks1965 2015-08-17 21:15:22 +03:00
parent 681c2de3ba
commit ec3421340f
24 changed files with 240 additions and 246 deletions

View file

@ -653,8 +653,15 @@ namespace PascalABCCompiler
public delegate void ChangeCompilerStateEventDelegate(ICompiler sender, CompilerState State, string FileName);
public interface ISyntaxTreeChanger
{
void Change(SyntaxTree.syntax_tree_node sn);
}
public class Compiler : MarshalByRefObject, ICompiler
{
public ISyntaxTreeChanger SyntaxTreeChanger = null; // SSM 17/08/15 - для операций над синтаксическим деревом после его построения
public static string Version
{
get
@ -2208,7 +2215,7 @@ namespace PascalABCCompiler
}
}
private List<SyntaxTree.unit_or_namespace> GetSyntaxInterfaceUsesList(SyntaxTree.compilation_unit CurrentSyntaxUnit)
public List<SyntaxTree.unit_or_namespace> GetSyntaxInterfaceUsesList(SyntaxTree.compilation_unit CurrentSyntaxUnit)
{
List<SyntaxTree.unit_or_namespace> result = null;
if(CurrentSyntaxUnit is SyntaxTree.unit_module)
@ -2450,7 +2457,7 @@ namespace PascalABCCompiler
return Path.GetDirectoryName(FileName).ToLower() == CompilerOptions.SearchDirectory.ToLower();
}
private void AddStandartUnitsToUsesSection(SyntaxTree.compilation_unit cu)
public void AddStandartUnitsToUsesSection(SyntaxTree.compilation_unit cu)
{
//if (FileInSearchDirectory(cu.file_name)) return;
@ -2533,7 +2540,7 @@ namespace PascalABCCompiler
throw new AssemblyReadingError(CurrentCompilationUnit.SyntaxTree.file_name,UnitName,sc);
}
private TreeRealization.unit_node_list GetReferences(CompilationUnit Unit)
public TreeRealization.unit_node_list GetReferences(CompilationUnit Unit)
{
//TODO переделать, ConvertDirectives определена дважды и вызывается дважды!
TreeRealization.unit_node_list res = new TreeRealization.unit_node_list();
@ -2618,7 +2625,7 @@ namespace PascalABCCompiler
return false;
}
private TreeRealization.using_namespace GetNamespace(SyntaxTree.unit_or_namespace _name_space)
public TreeRealization.using_namespace GetNamespace(SyntaxTree.unit_or_namespace _name_space)
{
return new TreeRealization.using_namespace(SyntaxTree.Utils.IdentListToString(_name_space.name.idents, "."));
}
@ -2635,19 +2642,19 @@ namespace PascalABCCompiler
return new TreeRealization.using_namespace(full_namespace_name);
}
private void AddNamespaces(TreeRealization.using_namespace_list using_list, List<SyntaxTree.unit_or_namespace> namespaces, bool possible_is_units)
public void AddNamespaces(TreeRealization.using_namespace_list using_list, List<SyntaxTree.unit_or_namespace> namespaces, bool possible_is_units)
{
foreach (SyntaxTree.unit_or_namespace ns in namespaces)
using_list.AddElement(GetNamespace(using_list, SyntaxTree.Utils.IdentListToString(ns.name.idents, "."), ns, possible_is_units));
}
private void AddNamespaces(TreeRealization.using_namespace_list using_list, SyntaxTree.using_list ul)
public void AddNamespaces(TreeRealization.using_namespace_list using_list, SyntaxTree.using_list ul)
{
if (ul != null)
AddNamespaces(using_list, ul.namespaces, false);
}
private SyntaxTree.using_list GetInterfaceSyntaxUsingList(SyntaxTree.compilation_unit cu)
public SyntaxTree.using_list GetInterfaceSyntaxUsingList(SyntaxTree.compilation_unit cu)
{
if (cu is SyntaxTree.unit_module)
return (cu as SyntaxTree.unit_module).interface_part.using_namespaces;
@ -2829,8 +2836,15 @@ namespace PascalABCCompiler
throw new SourceFileNotFound(UnitName);
else
throw new UnitNotFound(CurrentCompilationUnit.SyntaxTree.file_name, UnitName, SyntaxUsesUnit.source_context);
CurrentUnit.SyntaxTree = InternalParseText(UnitName, SourceText, errorsList);
if (errorsList.Count == 0) // SSM 17/08/15 - для преобразования синтаксических деревьев извне
{
if (SyntaxTreeChanger != null)
SyntaxTreeChanger.Change(CurrentUnit.SyntaxTree);
}
if (errorsList.Count == 0 && need_gen_doc(CurrentUnit.SyntaxTree))
{
if (SourceText != null)

View file

@ -15,7 +15,7 @@ internal static class RevisionClass
public const string Major = "2";
public const string Minor = "2";
public const string Build = "0";
public const string Revision = "1012";
public const string Revision = "1013";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%MINOR%=2
%REVISION%=1012
%REVISION%=1013
%MAJOR%=2
%COREVERSION%=0

View file

@ -1 +1 @@
!define VERSION '2.2.0.1012'
!define VERSION '2.2.0.1013'

View file

@ -186,6 +186,10 @@ namespace PascalABCCompiler.SyntaxTree
public partial class un_expr
{
public static un_expr Not(expression ex)
{
return new un_expr(ex, Operators.LogicalNOT);
}
public override string ToString()
{
return string.Format("{0} {1}", OperatorServices.ToString(operation_type, LanguageId.PascalABCNET),this.subnode);
@ -906,10 +910,23 @@ namespace PascalABCCompiler.SyntaxTree
public partial class goto_statement
{
static int lbnum = 0;
static public string newLabelName()
{
lbnum++;
return "lb#" + lbnum.ToString();
}
public override string ToString()
{
return "goto " + label;
}
public static goto_statement New
{
get { return new goto_statement(newLabelName()); }
}
}
public partial class method_call
@ -1479,5 +1496,39 @@ namespace PascalABCCompiler.SyntaxTree
return "sequence of " + this.elements_type.ToString();
}
}
public partial class if_node
{
public if_node(expression _condition, statement _then_body)
{
this._condition = _condition;
this._then_body = _then_body;
this._else_body = null;
}
}
public partial class empty_statement
{
public static empty_statement New
{
get { return new empty_statement(); }
}
}
public partial class case_node
{
public case_node(expression _param, case_variants _conditions)
{
this._param = _param;
this._conditions = _conditions;
this._else_statement = null;
}
public case_node(expression _param)
{
this._param = _param;
this._conditions = new case_variants();
this._else_statement = null;
}
}
}

View file

@ -3,10 +3,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParsePABC1", "ParsePABC1\ParsePABC1.csproj", "{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxVisitors", "ParsePABC1\SyntaxVisitors.csproj", "{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "..\SyntaxTree\SyntaxTree.csproj", "{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldDesugarTest", "YieldDesugarTest\YieldDesugarTest.csproj", "{9EBC62C6-3092-4E9D-940E-476D332E0951}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -21,6 +23,10 @@ Global
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.Build.0 = Release|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class AllVarsInProcYields : CollectUpperNamespacesVisitor
public class AllVarsInProcYields : CollectUpperNamespacesVisitor
{
public FindMainIdentsVisitor mids = new FindMainIdentsVisitor();

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class BaseChangeVisitor : CollectUpperNodesVisitor
public class BaseChangeVisitor : CollectUpperNodesVisitor
{
public override void DefaultVisit(syntax_tree_node n)
{
@ -52,6 +52,16 @@ namespace ParsePABC1
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>();

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class BaseEnterExitVisitor: WalkingVisitorNew
public class BaseEnterExitVisitor : WalkingVisitorNew
{
public BaseEnterExitVisitor()
{

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class CollectUpperNamespacesVisitor : CollectUpperNodesVisitor
public class CollectUpperNamespacesVisitor : CollectUpperNodesVisitor
{
protected List<declaration> list = new List<declaration>();

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class CollectUpperNodesVisitor : BaseEnterExitVisitor
public class CollectUpperNodesVisitor : BaseEnterExitVisitor
{
protected List<syntax_tree_node> listNodes = new List<syntax_tree_node>();

View file

@ -7,7 +7,7 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
public class FindLocalDefsVisitor : WalkingVisitorNew // Запускать только для подпрограмм
{

View file

@ -8,9 +8,9 @@ using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class ChangeWhileVisitor : BaseChangeVisitor
public class ChangeWhileVisitor : BaseChangeVisitor
{
int lbnum = 0;

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class CalcConstExprs : BaseChangeVisitor // вычисление целых и вещественных константных выражений на этапе парсинга
public class CalcConstExprs : BaseChangeVisitor // вычисление целых и вещественных константных выражений на этапе парсинга
{
public override void Exit(syntax_tree_node st)
{

View file

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.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>{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ParsePABC1</RootNamespace>
<AssemblyName>ParsePABC1</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<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' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Compiler">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Compiler.dll</HintPath>
</Reference>
<Reference Include="CompilerTools">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\CompilerTools.dll</HintPath>
</Reference>
<Reference Include="Errors">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Errors.dll</HintPath>
</Reference>
<Reference Include="Localization">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Localization.dll</HintPath>
</Reference>
<Reference Include="NETGenerator">
<HintPath>..\..\bin\NETGenerator.dll</HintPath>
</Reference>
<Reference Include="ParserTools">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\ParserTools.dll</HintPath>
</Reference>
<Reference Include="PascalABCParser">
<HintPath>..\..\..\PascalABC.NET\!PABC_Git\bin\PascalABCParser.dll</HintPath>
</Reference>
<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.Xml" />
<Reference Include="TreeConverter">
<HintPath>..\..\bin\TreeConverter.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AllVarsInProcYieldsProba.cs" />
<Compile Include="BaseVisitors\BaseEnterExitVisitor.cs" />
<Compile Include="BaseVisitors\BaseChangeVisitor.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ChangeWhileVisitor.cs" />
<Compile Include="BaseVisitors\CollectNamespaces.cs" />
<Compile Include="BaseVisitors\CollectUpperNodesVisitor.cs" />
<Compile Include="CountNodesVisitor.cs" />
<Compile Include="DeleteLocalDefs.cs" />
<Compile Include="DeleteRedundantBeginEnds.cs" />
<Compile Include="Optimization\CalcConstExprs.cs" />
<Compile Include="ProcessYieldsCapturedVars.cs" />
<Compile Include="Program.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SimplePrettyPrinterVisitor.cs" />
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SyntaxTree\SyntaxTree.csproj">
<Project>{c2cac65a-b2ae-4ccc-b067-e6b8e75df73a}</Project>
<Name>SyntaxTree</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,78 +0,0 @@
using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class Program
{
static syntax_tree_node ParseFile(string fname)
{
Compiler c = new Compiler();
var err = new List<Error>();
var txt = System.IO.File.ReadAllText(fname);
var cu = c.ParseText(fname, txt, err);
if (cu == null)
{
if (err.Count > 0)
WriteLine(err[0]);
else WriteLine("Не распарсилось");
}
return cu;
}
static void Main(string[] args)
{
try
{
var cu = ParseFile(@"..\..\..\yield2.pas");
if (cu == null)
return;
/*cu.visit(new ChangeWhileVisitor());
cu.visit(new DeleteRedundantBeginEnds());*/
/*cu.visit(new CollectUpperNamespacesVisitor());
var allv = new AllVarsInProcYields();
cu.visit(allv);
allv.PrintDict();*/
/*var cnt = new CountNodesVisitor();
cu.visit(cnt);
cnt.PrintSortedByValue();*/
/*var ld = new HashSet<string>();
ld.Add("a");
ld.Add("p1");
ld.Add("s");
var dld = new DeleteLocalDefs(ld);
cu.visit(dld);*/
var p = new ProcessYieldCapturedVarsVisitor();
cu.visit(p);
/*var p = new CalcConstExprs();
cu.visit(p);*/
cu.visit(new SimplePrettyPrinterVisitor());
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class CountNodesVisitor : BaseEnterExitVisitor
public class CountNodesVisitor : BaseEnterExitVisitor
{
public Dictionary<System.Type, int> d = new Dictionary<System.Type, int>();

View file

@ -8,9 +8,9 @@ using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class DeleteRedundantBeginEnds : BaseChangeVisitor
public class DeleteRedundantBeginEnds : BaseChangeVisitor
{
public override void Exit(syntax_tree_node st)
{

View file

@ -12,14 +12,19 @@ using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class SimplePrettyPrinterVisitor: WalkingVisitorNew
public class SimplePrettyPrinterVisitor : WalkingVisitorNew
{
int off = 0;
bool printNodeType = false;
public static SimplePrettyPrinterVisitor New
{
get { return new SimplePrettyPrinterVisitor(); }
}
public SimplePrettyPrinterVisitor()
{
OnEnter = Enter;
@ -64,6 +69,14 @@ namespace ParsePABC1
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;
@ -102,7 +115,7 @@ namespace ParsePABC1
var vds = st as var_def_statement;
Println(vds.ToString());
}
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members)
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members || st is case_variants)
{
}
else if (st is if_node)
@ -130,6 +143,13 @@ namespace ParsePABC1
Println("while " + wn.expr.ToString() + " 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;
@ -174,11 +194,11 @@ namespace ParsePABC1
off -= 2;
Println("end");
}
else if (st is while_node || st is if_node || st is type_declarations || st is variable_definitions)
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)
else if (st is class_definition || st is case_node)
{
off -= 2;
Println("end;");

View file

@ -7,9 +7,9 @@ using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class DeleteLocalDefs : BaseChangeVisitor
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>();

View file

@ -8,44 +8,50 @@ using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
namespace SyntaxVisitors
{
class ChangeWhileVisitor : BaseChangeVisitor
public class LoweringVisitor : BaseChangeVisitor
{
int lbnum = 0;
public static ChangeWhileVisitor New
public static LoweringVisitor New
{
get { return new ChangeWhileVisitor(); }
get { return new LoweringVisitor(); }
}
public string newLabelName()
public static void Accept(procedure_definition pd)
{
lbnum++;
return "lb#" + lbnum.ToString();
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(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 b = HasStatementVisitor<yield_node>.Has(wn);
if (!b)
return;
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 gt1 = goto_statement.New;
var gt2 = goto_statement.New;
var stl = new statement_list(lb3, gt2, lb1, gt3, lb2);
var if0 = new if_node(un_expr.Not(wn.expr), gt1);
var lb2 = new labeled_statement(gt2.label, if0);
var lb1 = new labeled_statement(gt1.label, empty_statement.New);
ReplaceStatement(wn, SeqStatements(lb2, wn.statements, gt2, lb1));
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);
bl.defs.Add(new label_definitions(gt1.label, gt2.label));
}
}
}

View file

@ -11,9 +11,9 @@ using PascalABCCompiler.ParserTools;
using PascalABCCompiler.Errors;
namespace ParsePABC1
namespace SyntaxVisitors
{
class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor
public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor
{
int clnum = 0;
@ -29,6 +29,11 @@ namespace ParsePABC1
public bool hasYields = false;
public static ProcessYieldCapturedVarsVisitor New
{
get { return new ProcessYieldCapturedVarsVisitor(); }
}
public ProcessYieldCapturedVarsVisitor()
{
//PrintInfo = false;
@ -86,7 +91,7 @@ namespace ParsePABC1
var className = newClassName() + "Helper";
var assG = new assign("Result", new new_expr(new named_type_reference(className),expression_list.Empty));
var GetEnumerator = new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", assG);
var GetEnumerator = new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"));
var stl = new statement_list(assG);
foreach (var id in lid)
@ -104,6 +109,67 @@ namespace ParsePABC1
return td;
}
class ConstructFiniteAutomata
{
public statement_list res = new statement_list();
statement_list stl;
int curState = 0;
statement_list curStatList;
statement_list StatListAfterCase = new statement_list();
case_node cas; // формируемый case
public ConstructFiniteAutomata(statement_list stl)
{
this.stl = stl;
}
public void Process(statement st)
{
if (!(st is yield_node || st is labeled_statement))
{
curStatList.Add(st);
}
if (st is yield_node)
{
var yn = st as yield_node;
curState += 1;
curStatList.Add(new assign("current", yn.ex));
curStatList.Add(new assign("state", curState));
curStatList.Add(new assign("Result", new bool_const(true)));
curStatList.Add(new procedure_call(new ident("exit")));
curStatList = new statement_list();
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
cas.conditions.variants.Add(cv);
}
if (st is labeled_statement)
{
var ls = st as labeled_statement;
curStatList = StatListAfterCase;
curStatList.Add(new labeled_statement(ls.label_name,empty_statement.New));
Process(ls.to_statement);
}
}
public void Transform()
{
cas = new case_node(new ident("state"));
curStatList = new statement_list();
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
cas.conditions.variants.Add(cv);
foreach (var st in stl.subnodes)
Process(st);
stl.subnodes = SeqStatements(cas,StatListAfterCase).ToList();
//statement_list res = new statement_list(cas);
res = stl;
}
}
public override void visit(procedure_definition pd)
{
hasYields = false;
@ -120,7 +186,11 @@ namespace ParsePABC1
// В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать
dld.AfterProcTraverse();
ChangeWhileVisitor.New.ProcessNode(pd);
LoweringVisitor.Accept(pd);
var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code);
cfa.Transform();
(pd.proc_body as block).program_code = cfa.res;
// Конструируем определение класса
var cc = GenClassForYield(pd, dld.BlockDeletedIds.Union(dld.LocalDeletedIds));

View file

@ -6,6 +6,7 @@ function Gen(a,b: real): sequence of integer;
var j,k: real;
begin
var i := 1;
j := 2;
while i<5 do
begin
yield i*i;

Binary file not shown.