Compare commits
1 commit
master
...
features/r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88c129a3e5 |
|
|
@ -45,8 +45,8 @@ namespace PascalABCCompiler.SyntaxTreeConverters
|
||||||
// Patterns
|
// Patterns
|
||||||
PatternsDesugaringVisitor.New.ProcessNode(root);
|
PatternsDesugaringVisitor.New.ProcessNode(root);
|
||||||
|
|
||||||
|
// Auto classes
|
||||||
|
AutoClassDesugaringVisitor.New.ProcessNode(root);
|
||||||
|
|
||||||
// Всё, связанное с yield
|
// Всё, связанное с yield
|
||||||
MarkMethodHasYieldAndCheckSomeErrorsVisitor.New.ProcessNode(root);
|
MarkMethodHasYieldAndCheckSomeErrorsVisitor.New.ProcessNode(root);
|
||||||
|
|
|
||||||
107
SyntaxVisitors/SugarVisitors/AutoClassDesugaringVisitor.cs
Normal file
107
SyntaxVisitors/SugarVisitors/AutoClassDesugaringVisitor.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
using PascalABCCompiler.SyntaxTree;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SyntaxVisitors.SugarVisitors
|
||||||
|
{
|
||||||
|
public class AutoClassDesugaringVisitor : BaseChangeVisitor
|
||||||
|
{
|
||||||
|
private Dictionary<string, class_definition> autoClassDefinitions = new Dictionary<string, class_definition>();
|
||||||
|
|
||||||
|
public static AutoClassDesugaringVisitor New => new AutoClassDesugaringVisitor();
|
||||||
|
|
||||||
|
public override void visit(type_declaration typeDeclaration)
|
||||||
|
{
|
||||||
|
var isAutoClass = typeDeclaration.type_def is class_definition classDefinition && IsAutoClass(classDefinition);
|
||||||
|
if (!isAutoClass)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Добавляем автокласс в словарь
|
||||||
|
classDefinition = typeDeclaration.type_def as class_definition;
|
||||||
|
autoClassDefinitions[typeDeclaration.type_name.name] = classDefinition;
|
||||||
|
|
||||||
|
CheckAutoClassInheritance(classDefinition);
|
||||||
|
CheckAutoClassBody(classDefinition);
|
||||||
|
|
||||||
|
var fieldNames = new List<ident>();
|
||||||
|
var fieldTypes = new List<type_definition>();
|
||||||
|
CollectAutoClassRegularFields(classDefinition, ref fieldNames, ref fieldTypes);
|
||||||
|
var constructor = SyntaxTreeBuilder.BuildSimpleConstructorSection(fieldNames, fieldNames.Select(x => new ident('_' + x.name)).ToList(), fieldTypes);
|
||||||
|
classDefinition.body.Add(constructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsAutoClass(class_definition classDefinition) => (classDefinition.attribute & class_attribute.Auto) == class_attribute.Auto;
|
||||||
|
|
||||||
|
private bool AutoClassExists(string className) => className != null && autoClassDefinitions.ContainsKey(className);
|
||||||
|
|
||||||
|
private void CheckAutoClassInheritance(class_definition classDefinition)
|
||||||
|
{
|
||||||
|
if (classDefinition?.class_parents?.Count > 1)
|
||||||
|
throw new SyntaxVisitorError("AUTO_CLASS_CAN_ONLY_HAVE_ONE_PARENT_CLASS", classDefinition.source_context);
|
||||||
|
|
||||||
|
if (classDefinition?.class_parents?.Count > 0 && !AutoClassExists(GetAutoClassParentName(classDefinition)))
|
||||||
|
throw new SyntaxVisitorError("AUTO_CLASS_CAN_BE_INHERITED_ONLY_FROM_ANOTHER_AUTO_CLASS", classDefinition.source_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckAutoClassBody(class_definition classDefinition)
|
||||||
|
{
|
||||||
|
// Запрещаем все кроме полей
|
||||||
|
if (classDefinition.body.class_def_blocks.Any(block => block.members.Any(member => !(member is var_def_statement))))
|
||||||
|
throw new SyntaxVisitorError("AUTO_CLASS_CAN_ONLY_CONTAIN_FIELD_DECLARATIONS", classDefinition.source_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CollectAutoClassRegularFields(class_definition classDefinition, ref List<ident> names, ref List<type_definition> types)
|
||||||
|
{
|
||||||
|
if (classDefinition?.class_parents?.Count > 0)
|
||||||
|
{
|
||||||
|
var hasParent = GetAutoClassParent(classDefinition, out var definition, out _);
|
||||||
|
CollectAutoClassRegularFields(classDefinition, ref names, ref types);
|
||||||
|
}
|
||||||
|
|
||||||
|
var varDefs = CollectAutoClassVarDefs(classDefinition);
|
||||||
|
names.AddRange(varDefs.Select(x => x.vars).SelectMany(x => x.list));
|
||||||
|
types.AddRange(varDefs.SelectMany(x => Enumerable.Repeat(x.vars_type, x.vars.Count)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<var_def_statement> CollectAutoClassVarDefs(class_definition classDefinition) =>
|
||||||
|
classDefinition.body.class_def_blocks.SelectMany(block => block.members.OfType<var_def_statement>());
|
||||||
|
|
||||||
|
private string GetAutoClassParentName(class_definition classDefinition)
|
||||||
|
{
|
||||||
|
GetAutoClassParent(classDefinition, out _, out string parentName);
|
||||||
|
return parentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает предка класса, только если он тоже автокласс
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="classDefinition"></param>
|
||||||
|
/// <param name="definition"></param>
|
||||||
|
/// <param name="parentName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool GetAutoClassParent(class_definition classDefinition, out class_definition definition, out string parentName)
|
||||||
|
{
|
||||||
|
parentName = null;
|
||||||
|
definition = null;
|
||||||
|
|
||||||
|
if (classDefinition?.class_parents?.Count > 0)
|
||||||
|
{
|
||||||
|
parentName = classDefinition.class_parents.types
|
||||||
|
.Where(x => autoClassDefinitions.ContainsKey(x.names[0].name))
|
||||||
|
.Select(x => x.names[0].name)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (parentName != null)
|
||||||
|
{
|
||||||
|
definition = autoClassDefinitions[parentName];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1.cs" />
|
<Compile Include="LightSymInfoVisitors\SymInfoCollect1.cs" />
|
||||||
<Compile Include="LightSymInfoVisitors\SymInfoCollect1Helper.cs" />
|
<Compile Include="LightSymInfoVisitors\SymInfoCollect1Helper.cs" />
|
||||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor.cs" />
|
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor.cs" />
|
||||||
|
<Compile Include="SugarVisitors\AutoClassDesugaringVisitor.cs" />
|
||||||
<Compile Include="SugarVisitors\DoubleQuestionDesugarVisitor.cs" />
|
<Compile Include="SugarVisitors\DoubleQuestionDesugarVisitor.cs" />
|
||||||
<Compile Include="SugarVisitors\LoopDesugarVisitor.cs" />
|
<Compile Include="SugarVisitors\LoopDesugarVisitor.cs" />
|
||||||
<Compile Include="SugarVisitors\QuestionPointDesugarVisitor.cs" />
|
<Compile Include="SugarVisitors\QuestionPointDesugarVisitor.cs" />
|
||||||
|
|
|
||||||
|
|
@ -3592,6 +3592,9 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
/*if (_class_definition.class_parents!=null)
|
/*if (_class_definition.class_parents!=null)
|
||||||
AddError(new AutoClassMustNotHaveParents(get_location(_class_definition)));*/
|
AddError(new AutoClassMustNotHaveParents(get_location(_class_definition)));*/
|
||||||
// добавление членов автоклассов. Не забыть сделать, что от автоклассов нельзя наследовать
|
// добавление членов автоклассов. Не забыть сделать, что от автоклассов нельзя наследовать
|
||||||
|
|
||||||
|
// Закоментировал для реализации record-classes
|
||||||
|
/*
|
||||||
SyntaxTreeBuilder.AddMembersForAutoClass(_class_definition,ref names,ref types);
|
SyntaxTreeBuilder.AddMembersForAutoClass(_class_definition,ref names,ref types);
|
||||||
for (var i = 0; i < types.Count; i++)
|
for (var i = 0; i < types.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -3615,6 +3618,8 @@ namespace PascalABCCompiler.TreeConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
//if (!SemanticRules.OrderIndependedNames)
|
//if (!SemanticRules.OrderIndependedNames)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,9 @@
|
||||||
<Reference Include="System.Design" />
|
<Reference Include="System.Design" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Messaging" />
|
<Reference Include="System.Messaging" />
|
||||||
|
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Windows.Forms.DataVisualization" />
|
<Reference Include="System.Windows.Forms.DataVisualization" />
|
||||||
<Reference Include="System.Xaml" />
|
<Reference Include="System.Xaml" />
|
||||||
|
|
@ -532,6 +535,7 @@
|
||||||
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\ConfigureSidebarDialog.xfrm" />
|
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\ConfigureSidebarDialog.xfrm" />
|
||||||
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\RenameSidebarCategoryDialog.xfrm" />
|
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\RenameSidebarCategoryDialog.xfrm" />
|
||||||
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\WindowsFormsGeneralOptions.xfrm" />
|
<EmbeddedResource Include="FormsDesignerBinding\FormsDesigner\Resources\WindowsFormsGeneralOptions.xfrm" />
|
||||||
|
<None Include="packages.config" />
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue