Assign tuple optimizer (#3142)
* branch init * add BindCollectLightSymInfo * moved lightsyminfo to syntaxVisitors * LIghtSymInfo fixes * binder 0.1 * Attributes -> SymbolAttributes * AssignTupleOptimizer -> AssignTupleDesugar * moved algorithm classes to AssignTupleDesugarAlgorithm namespace * fixes and refactoring * LightSymInfo rework * add rebuildDebug and build units * enable VarNamesInMethodsWithSameNameAsClassGenericParamsReplacer * remove CollectFullLightSymInfo call * bind now return BindResult * change BindResult path type * path testing * fix Current in BindCollectLightSymInfo * fix Current in BindCollectLightSymInfo * potential symomyms handling without assigns count minimization * assign count minimization * rename AssignTuplesDesugar * move NewAssignTupleDesugar * add optimization switch * delete AssignTupleDesugar project * remove comments
This commit is contained in:
parent
9f8f982cc2
commit
133d082e4e
|
|
@ -15,7 +15,9 @@ namespace Languages.Pascal.Frontend.Converters
|
|||
|
||||
protected override syntax_tree_node ApplyConcreteConversions(syntax_tree_node root)
|
||||
{
|
||||
root.FillParentsInAllChilds();
|
||||
|
||||
var binder = new BindCollectLightSymInfo(root as compilation_unit);
|
||||
#if DEBUG
|
||||
// var stat = new ABCStatisticsVisitor();
|
||||
// stat.ProcessNode(root);
|
||||
|
|
@ -42,9 +44,9 @@ namespace Languages.Pascal.Frontend.Converters
|
|||
#if DEBUG
|
||||
//new SimplePrettyPrinterVisitor("D:/out.txt").ProcessNode(root);
|
||||
#endif
|
||||
|
||||
bool optimize_tuple_assign = true;
|
||||
// tuple_node
|
||||
TupleVisitor.New.ProcessNode(root);
|
||||
TupleVisitor.Create(optimize_tuple_assign).ProcessNode(root);
|
||||
|
||||
// index
|
||||
IndexVisitor.New.ProcessNode(root);
|
||||
|
|
@ -55,8 +57,10 @@ namespace Languages.Pascal.Frontend.Converters
|
|||
|
||||
// теперь коллизия с (a[1:6], a[6:11]):= (a[6:11], a[1:6]);
|
||||
// assign_tuple и assign_var_tuple
|
||||
AssignTuplesDesugarVisitor.New.ProcessNode(root); // теперь это - на семантике
|
||||
|
||||
if (!optimize_tuple_assign)
|
||||
AssignTuplesDesugarVisitor.New.ProcessNode(root); // теперь это - на семантике
|
||||
else
|
||||
NewAssignTuplesDesugarVisitor.Create(binder).ProcessNode(root);
|
||||
|
||||
// question_point_desugar_visitor
|
||||
QuestionPointDesugarVisitor.New.ProcessNode(root);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34309.116
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.34301.259
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VisualPascalABCNET", "VisualPascalABCNET", "{26843C5D-9D7E-4C2C-AC14-2D227FA5592E}"
|
||||
EndProject
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PascalABCCompiler.SyntaxTree
|
||||
{
|
||||
|
|
@ -12,22 +13,23 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
Current = Root;
|
||||
visit(root);
|
||||
Current = null;
|
||||
}
|
||||
|
||||
public SymInfoSyntax bind(ident node)
|
||||
public BindResult bind(ident node)
|
||||
{
|
||||
///Console.WriteLine("searching " + node.ToString());
|
||||
|
||||
Current = null;
|
||||
syntax_tree_node cur_node = node;
|
||||
var path = new Queue<ScopeSyntax>();
|
||||
while (cur_node != null)
|
||||
{
|
||||
// Console.WriteLine("cur_node: " + cur_node.ToString());
|
||||
|
||||
if (AbstractScopeCreator.IsScopeCreator(cur_node))
|
||||
{
|
||||
|
||||
//Console.WriteLine("checking scope" + cur_node.ToString())
|
||||
var cur_scope = scopeCreator.GetScope(cur_node);
|
||||
//Console.WriteLine(cur_scope.ToString() + ": " + cur_scope.Symbols.Count);
|
||||
path.Enqueue(cur_scope);
|
||||
var prev_scope = Current;
|
||||
|
||||
if (prev_scope != null)
|
||||
|
|
@ -36,11 +38,10 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
Current = cur_scope;
|
||||
if (cur_scope.Parent == null && !(Current is GlobalScopeSyntax))
|
||||
{
|
||||
//Console.WriteLine("visiting " + cur_node.ToString());
|
||||
cur_node.visit(this);
|
||||
}
|
||||
var res = Current.bind(node);
|
||||
if (res != null) return res;
|
||||
if (res != null) return new BindResult(res, path.ToList());
|
||||
}
|
||||
cur_node = cur_node.Parent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
recordname, interfacename, template_param, type_alias, const_var, property };
|
||||
|
||||
[Flags]
|
||||
public enum SymbolAttributes { class_attr = 1, varparam_attr = 2, private_attr = 4};
|
||||
public enum SymbolAttributes { class_attr = 1, varparam_attr = 2, private_attr = 4 };
|
||||
|
||||
public class SymInfoSyntax
|
||||
{
|
||||
|
|
@ -53,6 +53,19 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
}
|
||||
|
||||
public class BindResult {
|
||||
|
||||
public SymInfoSyntax symInfo;
|
||||
public List<ScopeSyntax> path;
|
||||
|
||||
public BindResult(SymInfoSyntax s, List<ScopeSyntax> p)
|
||||
{
|
||||
symInfo = s;
|
||||
path = p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class ScopeSyntax
|
||||
{
|
||||
public syntax_tree_node node;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AssignTupleDesugarAlgorithm;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace SyntaxVisitors.SugarVisitors
|
||||
{
|
||||
public class NewAssignTuplesDesugarVisitor : AssignTuplesDesugarVisitor
|
||||
{
|
||||
|
||||
private BindCollectLightSymInfo binder;
|
||||
|
||||
|
||||
public static NewAssignTuplesDesugarVisitor Create(BindCollectLightSymInfo binder)
|
||||
{
|
||||
return new NewAssignTuplesDesugarVisitor(binder);
|
||||
}
|
||||
|
||||
public NewAssignTuplesDesugarVisitor(BindCollectLightSymInfo binder)
|
||||
{
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
|
||||
List<statement> desugar(tuple_node tn, addressed_value_list vars)
|
||||
{
|
||||
var order = Assign.getAssignOrder(tn, vars, binder);
|
||||
var assigns = new List<statement>();
|
||||
foreach (var a in order)
|
||||
{
|
||||
if (a.to is TempSymbol ts)
|
||||
{
|
||||
var cur = new var_def_statement(ts.node as ident, a.from.node, tn.Parent.source_context);
|
||||
assigns.Add(new var_statement(cur, tn.Parent.source_context));
|
||||
}
|
||||
else
|
||||
{
|
||||
var cur = new assign(a.to.node as addressed_value, a.from.node, tn.Parent.source_context);
|
||||
assigns.Add(cur);
|
||||
}
|
||||
}
|
||||
return assigns;
|
||||
}
|
||||
|
||||
|
||||
public override void visit(assign_tuple node)
|
||||
{
|
||||
if (node.expr is tuple_node tn)
|
||||
{
|
||||
var n = node.vars.variables.Count();
|
||||
if (n > tn.el.Count)
|
||||
throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", node.vars.variables[0]);
|
||||
|
||||
var assigns = desugar(tn, node.vars);
|
||||
ReplaceStatementUsingParent(node, assigns);
|
||||
}
|
||||
else
|
||||
base.visit(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
public class Assign
|
||||
{
|
||||
public Symbol from;
|
||||
public Symbol to;
|
||||
public Assign(Symbol to, Symbol from)
|
||||
{
|
||||
this.to = to;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public static List<Assign> getAssignOrder(tuple_node tn, addressed_value_list vars, BindCollectLightSymInfo binder)
|
||||
{
|
||||
var left = new List<Symbol>();
|
||||
var right = new List<Symbol>();
|
||||
|
||||
foreach (var ex in vars.variables)
|
||||
{
|
||||
var s = new Symbol(ex, binder);
|
||||
left.Add(s);
|
||||
}
|
||||
|
||||
|
||||
foreach (var ex in tn.el.expressions)
|
||||
{
|
||||
var s = new Symbol(ex, binder);
|
||||
right.Add(s);
|
||||
}
|
||||
|
||||
|
||||
var graph = GraphUtils.createAssignGraph(left, right);
|
||||
//graph.drawGraph();
|
||||
var order = graph.GetAssignOrder();
|
||||
return order.Select(elem => new Assign(to: elem.to.symbol, from: elem.from.symbol)).ToList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
internal class AssignGraph : IEnumerable<SymbolNode>
|
||||
{
|
||||
public readonly HashSet<SymbolNode> vertexes = new HashSet<SymbolNode>();
|
||||
|
||||
public readonly List<Edge> edges = new List<Edge>();
|
||||
private bool AdjStructuresNeedSync = false;
|
||||
|
||||
public List<Edge> assignOrder = new List<Edge>();
|
||||
public List<Edge> assignLast = new List<Edge>();
|
||||
public List<Edge> assignFirst = new List<Edge>();
|
||||
|
||||
private Dictionary<SymbolNode, List<SymbolNode>> outAdjStructure = null;
|
||||
|
||||
public Dictionary<SymbolNode, List<SymbolNode>> OutAdjStructure
|
||||
{
|
||||
get
|
||||
{
|
||||
if (outAdjStructure == null || AdjStructuresNeedSync)
|
||||
{
|
||||
outAdjStructure = createOutAdjStructure();
|
||||
inAdjStructure = createInAdjStructure();
|
||||
AdjStructuresNeedSync = false;
|
||||
}
|
||||
|
||||
return outAdjStructure;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<SymbolNode, List<SymbolNode>> createOutAdjStructure()
|
||||
{
|
||||
Dictionary<SymbolNode, List<SymbolNode>> res = new Dictionary<SymbolNode, List<SymbolNode>>();
|
||||
|
||||
foreach (var vert in vertexes) res.Add(vert, new List<SymbolNode>());
|
||||
|
||||
foreach (Edge edge in edges) res[edge.from].Add(edge.to);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private Dictionary<SymbolNode, List<SymbolNode>> inAdjStructure = null;
|
||||
|
||||
public Dictionary<SymbolNode, List<SymbolNode>> InAdjStructure
|
||||
{
|
||||
get
|
||||
{
|
||||
if (inAdjStructure == null || AdjStructuresNeedSync)
|
||||
{
|
||||
outAdjStructure = createOutAdjStructure();
|
||||
inAdjStructure = createInAdjStructure();
|
||||
AdjStructuresNeedSync = false;
|
||||
}
|
||||
|
||||
return inAdjStructure;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<SymbolNode, List<SymbolNode>> createInAdjStructure()
|
||||
{
|
||||
Dictionary<SymbolNode, List<SymbolNode>> res = new Dictionary<SymbolNode, List<SymbolNode>>();
|
||||
|
||||
foreach (var vert in vertexes) res.Add(vert, new List<SymbolNode>());
|
||||
|
||||
foreach (Edge edge in edges) res[edge.to].Add(edge.from);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public List<Edge> GetInEdgesForVertex(SymbolNode v) => edges.FindAll(edge => edge.to == v);
|
||||
public List<Edge> GetOutEdgesForVertex(SymbolNode v) => edges.FindAll(edge => edge.from == v);
|
||||
|
||||
public void resetVertexesColor()
|
||||
{
|
||||
foreach (SymbolNode v in vertexes) v.resetColor();
|
||||
}
|
||||
|
||||
public bool EnsureThatEveryVertexHasOneOrZeroInEdge() =>
|
||||
vertexes.All(vert => GetInEdgesForVertex(vert).Count <= 1);
|
||||
|
||||
internal List<Edge> GetAssignOrder()
|
||||
{
|
||||
List<Edge> assignOrder = new List<Edge>();
|
||||
assignOrder.AddRange(assignFirst);
|
||||
|
||||
if (vertexes.Count == 0)
|
||||
{
|
||||
assignOrder.AddRange(assignLast);
|
||||
this.assignOrder = assignOrder;
|
||||
return this.assignOrder;
|
||||
}
|
||||
|
||||
var s = vertexes.First();
|
||||
|
||||
if (!EnsureThatEveryVertexHasOneOrZeroInEdge()) throw new Exception("Invalid assign graph!");
|
||||
|
||||
var cycles = this.findAllUniqueElementaryCycles();
|
||||
|
||||
foreach (var cycle in cycles)
|
||||
{
|
||||
SymbolNode cut_place = cycle[0];
|
||||
Edge edge_to_cut = GetInEdgesForVertex(cut_place).First();
|
||||
|
||||
SymbolNode temp_assign_from = edge_to_cut.from;
|
||||
SymbolNode temp_vertex = new TempSymbolNode(new TempSymbol());
|
||||
|
||||
assignOrder.Add(new Edge(temp_assign_from, temp_vertex));
|
||||
assignLast.Add(new Edge(temp_vertex, cut_place));
|
||||
|
||||
edges.Remove(edge_to_cut);
|
||||
AdjStructuresNeedSync = true;
|
||||
}
|
||||
|
||||
List<SymbolNode> roots = vertexes.ToList().FindAll(vertex => GetInEdgesForVertex(vertex).Count == 0);
|
||||
|
||||
void treeTraversal(SymbolNode root)
|
||||
{
|
||||
foreach (SymbolNode node in OutAdjStructure[root]) treeTraversal(node);
|
||||
|
||||
var inEdges = GetInEdgesForVertex(root);
|
||||
if (inEdges.Count() > 0) assignOrder.Add(inEdges.First());
|
||||
}
|
||||
|
||||
foreach (SymbolNode root in roots) treeTraversal(root);
|
||||
|
||||
assignOrder.AddRange(assignLast);
|
||||
this.assignOrder = assignOrder;
|
||||
return this.assignOrder;
|
||||
}
|
||||
|
||||
public AssignGraph(List<Edge> edges, List<SymbolNode> vertexes) : this(edges)
|
||||
{
|
||||
foreach (SymbolNode vert in vertexes) this.vertexes.Add(vert);
|
||||
}
|
||||
|
||||
public AssignGraph()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AssignGraph(List<Edge> e)
|
||||
{
|
||||
edges = e;
|
||||
foreach (var edge in edges)
|
||||
{
|
||||
vertexes.Add(edge.from);
|
||||
vertexes.Add(edge.to);
|
||||
}
|
||||
}
|
||||
public IEnumerator<SymbolNode> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<SymbolNode>)vertexes).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)vertexes).GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
internal class Cycle
|
||||
{
|
||||
List<SymbolNode> cycle;
|
||||
|
||||
|
||||
public int Len => cycle.Count;
|
||||
|
||||
public Cycle(List<SymbolNode> c)
|
||||
{
|
||||
cycle = c;
|
||||
}
|
||||
|
||||
public SymbolNode this[int i] => cycle[i % Len];
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string res = "";
|
||||
foreach (var v in cycle)
|
||||
{
|
||||
res += v + "->";
|
||||
}
|
||||
|
||||
return res + cycle[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
internal class Edge : IEquatable<Edge>, IComparable<Edge>
|
||||
{
|
||||
public SymbolNode from;
|
||||
public SymbolNode to;
|
||||
public int weight;
|
||||
|
||||
public Edge(SymbolNode f, SymbolNode t, int w = 0)
|
||||
{
|
||||
if (weight < 0) throw new ArgumentException("weight can't be negative!");
|
||||
from = f;
|
||||
to = t;
|
||||
weight = w;
|
||||
}
|
||||
|
||||
public int CompareTo(Edge other)
|
||||
{
|
||||
return weight - other.weight;
|
||||
}
|
||||
|
||||
public bool Equals(Edge other)
|
||||
{
|
||||
if (other is null) return false;
|
||||
return from == other.from && to == other.to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,512 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
internal static class GraphUtils
|
||||
{
|
||||
static private void dfs(this AssignGraph graph,
|
||||
Action<AssignGraph> OnEnterGraph,
|
||||
Func<AssignGraph, SymbolNode, bool> OnProcessVertex,
|
||||
Action<AssignGraph, SymbolNode> OnEnterNode,
|
||||
Func<AssignGraph, SymbolNode, SymbolNode, bool> OnProcessNodeChild,
|
||||
Action<AssignGraph, SymbolNode> OnLeaveNode,
|
||||
Action<AssignGraph> OnLeaveGraph,
|
||||
Func<AssignGraph, SymbolNode, IEnumerable<SymbolNode>> vertexTraversalOrderFunc = null,
|
||||
IEnumerable<SymbolNode> graphTraversalOrder = null)
|
||||
{
|
||||
void dfs(SymbolNode start_node,
|
||||
Action<AssignGraph, SymbolNode> OnEnter,
|
||||
Func<AssignGraph, SymbolNode, SymbolNode, bool> OnProcessChild,
|
||||
Action<AssignGraph, SymbolNode> OnLeave
|
||||
)
|
||||
{
|
||||
OnEnter(graph, start_node);
|
||||
IEnumerable<SymbolNode> vertexTraversalOrder;
|
||||
if (vertexTraversalOrderFunc == null) vertexTraversalOrder = graph.OutAdjStructure[start_node];
|
||||
else vertexTraversalOrder = vertexTraversalOrderFunc(graph, start_node);
|
||||
foreach (SymbolNode current_node in vertexTraversalOrder)
|
||||
{
|
||||
if (OnProcessChild(graph, start_node, current_node))
|
||||
dfs(current_node, OnEnter, OnProcessChild, OnLeave);
|
||||
}
|
||||
|
||||
OnLeave(graph, start_node);
|
||||
}
|
||||
|
||||
|
||||
if (graphTraversalOrder == null) graphTraversalOrder = graph.vertexes;
|
||||
|
||||
OnEnterGraph(graph);
|
||||
foreach (SymbolNode v in graphTraversalOrder)
|
||||
{
|
||||
if (OnProcessVertex(graph, v))
|
||||
dfs(v, OnEnter: OnEnterNode, OnProcessChild: OnProcessNodeChild, OnLeave: OnLeaveNode);
|
||||
}
|
||||
|
||||
OnLeaveGraph(graph);
|
||||
}
|
||||
|
||||
|
||||
private class SynonymsGraph {
|
||||
|
||||
public enum Type { SAME_NAME, INDEXER}
|
||||
|
||||
public HashSet<int> left = new HashSet<int>();
|
||||
public HashSet<int> right = new HashSet<int>();
|
||||
|
||||
public Type type;
|
||||
|
||||
public SynonymsGraph(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var res = "";
|
||||
if (type == Type.INDEXER)
|
||||
res += "Indexer";
|
||||
else
|
||||
res += "Same_Name";
|
||||
res += "graph(left[";
|
||||
foreach (var i in left) res += i.ToString() + ",";
|
||||
res += "], right[";
|
||||
foreach(var i in right) res += i.ToString() + ",";
|
||||
res += "])";
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static AssignGraph createAssignGraph(List<Symbol> left, List<Symbol> right)
|
||||
{
|
||||
if (right.Count < left.Count) throw new Exception("AAAA");
|
||||
|
||||
|
||||
List<SymbolNode> v_left = new List<SymbolNode>();
|
||||
List<SymbolNode> v_right = new List<SymbolNode>();
|
||||
List<Symbol> left_visited = new List<Symbol>();
|
||||
List<Edge> assign_first = new List<Edge>();
|
||||
List<Edge> assign_last = new List<Edge>();
|
||||
|
||||
void addTemp(int i, bool toFirst)
|
||||
{
|
||||
if(toFirst)
|
||||
{
|
||||
var temp_symbol = new TempSymbol();
|
||||
assign_first.Add(new Edge(new SymbolNode(right[i]), new TempSymbolNode(temp_symbol)));
|
||||
right[i] = temp_symbol;
|
||||
}
|
||||
else
|
||||
{
|
||||
var temp_s = new TempSymbol();
|
||||
assign_last.Add(new Edge(new TempSymbolNode(temp_s), new SymbolNode(left[i])));
|
||||
left[i] = temp_s;
|
||||
}
|
||||
}
|
||||
|
||||
//handle expressions and var params
|
||||
for (int i = 0; i < left.Count(); i++)
|
||||
{
|
||||
if (right[i].type == Symbol.Type.EXPR || right[i].type == Symbol.Type.VAR_PARAM)
|
||||
{
|
||||
addTemp(i, true);
|
||||
}
|
||||
if (left[i].type == Symbol.Type.VAR_PARAM)
|
||||
{
|
||||
addTemp(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = left.Count - 1; i > -1; i--)
|
||||
{
|
||||
//delete loops
|
||||
if (left[i].StructurallyEquals(right[i]))
|
||||
{
|
||||
var f = new SymbolNode(right[i]);
|
||||
var t = new SymbolNode(left[i]);
|
||||
assign_first.Add(new Edge(f, t));
|
||||
left.RemoveAt(i);
|
||||
right.RemoveAt(i);
|
||||
}
|
||||
// if repeated assigns or pointers -> 2n
|
||||
else if (left_visited.Find(it => it.StructurallyEquals(left[i])) != null
|
||||
|| right[i].type == Symbol.Type.POINTER
|
||||
|| left[i].type == Symbol.Type.POINTER)
|
||||
{
|
||||
var res = new AssignGraph();
|
||||
res.assignFirst = make2n(left, right);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
left_visited.Add(left[i]);
|
||||
}
|
||||
|
||||
|
||||
var indexerGraph = new SynonymsGraph(SynonymsGraph.Type.INDEXER);
|
||||
var nameToGraph = new Dictionary<string, SynonymsGraph>();
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < left.Count; i++)
|
||||
{
|
||||
if (left[i].type == Symbol.Type.INDEXER)
|
||||
indexerGraph.left.Add(i);
|
||||
else if (left[i].type == Symbol.Type.FROM_OUTER_SCOPE || left[i].type == Symbol.Type.DOT_NODE)
|
||||
{
|
||||
var name = left[i].last_name;
|
||||
if (!nameToGraph.ContainsKey(name))
|
||||
nameToGraph.Add(name, new SynonymsGraph(SynonymsGraph.Type.SAME_NAME));
|
||||
nameToGraph[name].left.Add(i);
|
||||
}
|
||||
if (right[i].type == Symbol.Type.INDEXER)
|
||||
indexerGraph.right.Add(i);
|
||||
else if (right[i].type == Symbol.Type.FROM_OUTER_SCOPE || right[i].type == Symbol.Type.DOT_NODE)
|
||||
{
|
||||
var name = right[i].last_name;
|
||||
if (!nameToGraph.ContainsKey(name))
|
||||
nameToGraph.Add(name, new SynonymsGraph(SynonymsGraph.Type.SAME_NAME));
|
||||
nameToGraph[name].right.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var leftSet = new HashSet<Symbol>(left);
|
||||
var rightSet = new HashSet<Symbol>(right);
|
||||
var graphs = new List<SynonymsGraph>();
|
||||
graphs.AddRange(nameToGraph.Values);
|
||||
graphs.Add(indexerGraph);
|
||||
var moved_first = new List<Edge>();
|
||||
var moved_last = new LinkedList<Edge>();
|
||||
var movedAssigns = new HashSet<int>();
|
||||
|
||||
|
||||
void moveAssign(int i, bool toFirst )
|
||||
{
|
||||
Edge assign = new Edge(new SymbolNode(right[i]), new SymbolNode(left[i]));
|
||||
if (toFirst)
|
||||
moved_first.Add(assign);
|
||||
else
|
||||
moved_last.AddFirst(assign);
|
||||
movedAssigns.Add(i);
|
||||
}
|
||||
|
||||
void resolveGraph(SynonymsGraph sGraph)
|
||||
{
|
||||
|
||||
foreach (var i in sGraph.left)
|
||||
{
|
||||
var type = right[i].type;
|
||||
if (type == Symbol.Type.LOCAL)
|
||||
{
|
||||
if (!leftSet.Contains(right[i]))
|
||||
moveAssign(i, false);
|
||||
}
|
||||
else if (type == Symbol.Type.FROM_OUTER_SCOPE)
|
||||
{
|
||||
if (!(leftSet.Contains(right[i]) || nameToGraph[right[i].last_name].left.Count() != 0))
|
||||
moveAssign(i, false);
|
||||
}
|
||||
else if (type == Symbol.Type.DOT_NODE)
|
||||
{
|
||||
if (nameToGraph[right[i].last_name].left.Count() == 0)
|
||||
moveAssign(i, false);
|
||||
}
|
||||
else if (type == Symbol.Type.INDEXER)
|
||||
{
|
||||
if (indexerGraph.left.Count() == 0)
|
||||
moveAssign(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var i in sGraph.right)
|
||||
{
|
||||
var type = left[i].type;
|
||||
if (type == Symbol.Type.LOCAL)
|
||||
{
|
||||
if (!right.Contains(left[i]))
|
||||
moveAssign(i, true);
|
||||
}
|
||||
else if (type == Symbol.Type.FROM_OUTER_SCOPE)
|
||||
{
|
||||
if (!(rightSet.Contains(left[i]) || nameToGraph[left[i].last_name].right.Count() != 0))
|
||||
moveAssign(i, true);
|
||||
}
|
||||
else if (type == Symbol.Type.DOT_NODE)
|
||||
{
|
||||
if (nameToGraph[left[i].last_name].right.Count() == 0)
|
||||
moveAssign(i, true);
|
||||
}
|
||||
else if (type == Symbol.Type.INDEXER)
|
||||
{
|
||||
if (indexerGraph.right.Count() == 0)
|
||||
moveAssign(i, true);
|
||||
}
|
||||
}
|
||||
foreach(int i in movedAssigns)
|
||||
{
|
||||
sGraph.left.Remove(i);
|
||||
sGraph.right.Remove(i);
|
||||
}
|
||||
|
||||
var l_size = sGraph.left.Count;
|
||||
var r_size = sGraph.right.Count;
|
||||
if (r_size == 0 || l_size == 0)
|
||||
return;
|
||||
|
||||
Edge movedFromThisGraph = null;
|
||||
if (l_size < r_size)
|
||||
{
|
||||
foreach (var i in sGraph.left)
|
||||
{
|
||||
if (sGraph.right.Contains(i))
|
||||
{
|
||||
if (movedFromThisGraph == null)
|
||||
{
|
||||
movedFromThisGraph = new Edge(new SymbolNode(right[i]), new SymbolNode(left[i]));
|
||||
movedAssigns.Add(i);
|
||||
}
|
||||
else
|
||||
addTemp(i, false);
|
||||
|
||||
}
|
||||
else
|
||||
addTemp(i, false);
|
||||
}
|
||||
if (movedFromThisGraph != null)
|
||||
moved_last.AddFirst(movedFromThisGraph);
|
||||
sGraph.left.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var i in sGraph.right)
|
||||
{
|
||||
if (sGraph.left.Contains(i))
|
||||
{
|
||||
|
||||
if (movedFromThisGraph == null)
|
||||
{
|
||||
movedFromThisGraph = new Edge(new SymbolNode(right[i]), new SymbolNode(left[i]));
|
||||
movedAssigns.Add(i);
|
||||
}
|
||||
else
|
||||
addTemp(i, true);
|
||||
}
|
||||
else
|
||||
addTemp(i, true);
|
||||
|
||||
}
|
||||
if (movedFromThisGraph != null)
|
||||
moved_first.Add(movedFromThisGraph);
|
||||
sGraph.right.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
foreach (var g in graphs)
|
||||
resolveGraph(g);
|
||||
|
||||
for (int i = left.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (movedAssigns.Contains(i))
|
||||
{
|
||||
left.RemoveAt(i);
|
||||
right.RemoveAt(i);
|
||||
movedAssigns.Remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var symbols = new Dictionary<string, SymbolNode>();
|
||||
|
||||
foreach (Symbol sym in left)
|
||||
{
|
||||
if (!symbols.ContainsKey(sym.name)) symbols[sym.name] = new SymbolNode(sym);
|
||||
v_left.Add(symbols[sym.name]);
|
||||
}
|
||||
|
||||
foreach (Symbol sym in right)
|
||||
{
|
||||
if (!symbols.ContainsKey(sym.name)) symbols[sym.name] = new SymbolNode(sym);
|
||||
v_right.Add(symbols[sym.name]);
|
||||
}
|
||||
|
||||
List<Edge> assigns = new List<Edge>();
|
||||
|
||||
for (int i = 0; i < v_left.Count; i++) assigns.Add(new Edge(v_right[i], v_left[i], i));
|
||||
|
||||
|
||||
assign_first.AddRange(moved_first);
|
||||
foreach(var assign in assign_last)
|
||||
moved_last.AddLast(assign);
|
||||
|
||||
assign_last = moved_last.ToList();
|
||||
|
||||
var graph = new AssignGraph(assigns);
|
||||
graph.assignFirst = assign_first;
|
||||
graph.assignLast = assign_last;
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static List<Edge> make2n(List<Symbol> left, List<Symbol> right)
|
||||
{
|
||||
var temps = new List<SymbolNode>();
|
||||
var res = new List<Edge>();
|
||||
|
||||
for(int i = 0; i < right.Count; i++)
|
||||
{
|
||||
var to = new SymbolNode(new TempSymbol());
|
||||
var from = new SymbolNode(right[i]);
|
||||
temps.Add(to);
|
||||
res.Add(new Edge(from, to));
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < left.Count; i++)
|
||||
{
|
||||
var to = new SymbolNode(left[i]);
|
||||
res.Add(new Edge(temps[i], to));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static AssignGraph createReversedGraph(this AssignGraph g)
|
||||
{
|
||||
List<Edge> newEdges = new List<Edge>();
|
||||
foreach (var edge in g.edges)
|
||||
{
|
||||
newEdges.Add(new Edge(f: edge.to, t: edge.from));
|
||||
}
|
||||
|
||||
return new AssignGraph(newEdges, g.vertexes.ToList());
|
||||
}
|
||||
|
||||
public static List<List<SymbolNode>> findStronglyConnectedComponets(this AssignGraph g)
|
||||
{
|
||||
List<List<SymbolNode>> res = new List<List<SymbolNode>>();
|
||||
|
||||
Stack<SymbolNode> route = new Stack<SymbolNode>();
|
||||
HashSet<SymbolNode> visited = new HashSet<SymbolNode>();
|
||||
|
||||
Action<AssignGraph> onEnterGraph = (_) =>
|
||||
{
|
||||
route.Clear();
|
||||
visited.Clear();
|
||||
};
|
||||
|
||||
Action<AssignGraph, SymbolNode> onEnterNode = (graph, node) => { visited.Add(node); };
|
||||
|
||||
Action<AssignGraph, SymbolNode> onLeaveNode = (graph, node) => { route.Push(node); };
|
||||
|
||||
Func<AssignGraph, SymbolNode, SymbolNode, bool> onProcessChildNode = (graph, parent, childNode) =>
|
||||
{
|
||||
if (!visited.Contains(childNode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
};
|
||||
|
||||
Func<AssignGraph, SymbolNode, bool> onProcessVertex = (graph, vert) => { return !visited.Contains(vert); };
|
||||
|
||||
g.dfs(OnEnterGraph: onEnterGraph, OnProcessVertex: onProcessVertex,
|
||||
OnEnterNode: onEnterNode, OnProcessNodeChild: onProcessChildNode,
|
||||
OnLeaveNode: onLeaveNode,
|
||||
OnLeaveGraph: (_) => { }
|
||||
);
|
||||
|
||||
Action<AssignGraph> onEnterGraphReversed = (_) => { visited.Clear(); };
|
||||
|
||||
Action<AssignGraph, SymbolNode> onEnterNodeReversed = (graph, node) =>
|
||||
{
|
||||
visited.Add(node);
|
||||
res.Last().Add(node);
|
||||
};
|
||||
|
||||
Action<AssignGraph, SymbolNode> onLeaveNodeReversed = (graph, node) => { };
|
||||
|
||||
Func<AssignGraph, SymbolNode, SymbolNode, bool> onProcessChildNodeReversed = (graph, parent, childNode) =>
|
||||
{
|
||||
if (!visited.Contains(childNode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
};
|
||||
|
||||
Func<AssignGraph, SymbolNode, bool> onProcessVertexReversed = (graph, vert) =>
|
||||
{
|
||||
if (visited.Contains(vert)) return false;
|
||||
else
|
||||
{
|
||||
res.Add(new List<SymbolNode>());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var graphTraversalOrder = route.ToList();
|
||||
|
||||
var g_rev = g.createReversedGraph();
|
||||
|
||||
g_rev.dfs(OnEnterGraph: onEnterGraphReversed, OnProcessVertex: onProcessVertexReversed,
|
||||
OnEnterNode: onEnterNodeReversed, OnProcessNodeChild: onProcessChildNodeReversed,
|
||||
OnLeaveNode: onLeaveNodeReversed,
|
||||
OnLeaveGraph: (_) => { },
|
||||
graphTraversalOrder: graphTraversalOrder);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static List<Cycle> findAllUniqueElementaryCycles(this AssignGraph g)
|
||||
{
|
||||
var res = new List<Cycle>();
|
||||
var components = g.findStronglyConnectedComponets();
|
||||
foreach (var component in components)
|
||||
{
|
||||
if (component.Count() > 1) res.Add(new Cycle(component));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static void LogGraph(this AssignGraph graph)
|
||||
{
|
||||
foreach (var vert in graph.vertexes)
|
||||
{
|
||||
Console.Write("{0}->[", vert);
|
||||
graph.OutAdjStructure[vert].ForEach(v => Console.Write("{0}, ", v));
|
||||
Console.WriteLine("]");
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawGraph(this AssignGraph g)
|
||||
{
|
||||
var writer = File.CreateText("graph.dot");
|
||||
writer.WriteLine("digraph _graph {");
|
||||
|
||||
Action<AssignGraph> enterGraph = (graph) => { graph.resetVertexesColor(); };
|
||||
|
||||
Func<AssignGraph, SymbolNode, bool> ProcessNode = (graph, node) => node.color != SymbolNode.Color.GREY;
|
||||
|
||||
Action<AssignGraph, SymbolNode> EnterNode = (graph, vert) => { vert.color = SymbolNode.Color.GREY; };
|
||||
|
||||
Func<AssignGraph, SymbolNode, SymbolNode, bool> ProcessNodeChild = (graph, parent, child) =>
|
||||
{
|
||||
writer.WriteLine(parent.label + "->" + child.label);
|
||||
return child.color == SymbolNode.Color.WHITE;
|
||||
};
|
||||
|
||||
g.dfs(OnEnterGraph: enterGraph, OnEnterNode: EnterNode, OnProcessNodeChild: ProcessNodeChild,
|
||||
OnProcessVertex: ProcessNode, OnLeaveGraph: (graph) => { graph.resetVertexesColor(); }, OnLeaveNode: (graph, vertex) => { });
|
||||
writer.WriteLine("}");
|
||||
writer.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using PascalABCCompiler.SyntaxTree;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
public class Symbol
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
VAR_PARAM, FROM_OUTER_SCOPE, INDEXER, DOT_NODE, LOCAL, EXPR, POINTER
|
||||
}
|
||||
public string name;
|
||||
public string last_name;
|
||||
|
||||
//public bool canBeSynonym = false;
|
||||
//public bool isIndexer = false;
|
||||
//public bool isExpr = false;
|
||||
public expression node;
|
||||
public Type type;
|
||||
|
||||
public Symbol(expression ex, BindCollectLightSymInfo binder)
|
||||
{
|
||||
node = ex;
|
||||
if (node is indexer ind)
|
||||
{
|
||||
name = ind.ToString();
|
||||
last_name = name;
|
||||
type = Type.INDEXER;
|
||||
}
|
||||
else if (node is dot_node dn)
|
||||
{
|
||||
var last = dn.right;
|
||||
while (last is dot_node dn1)
|
||||
last = dn1.right;
|
||||
|
||||
name = node.ToString();
|
||||
last_name = last.ToString();
|
||||
type = Type.DOT_NODE;
|
||||
if (last is indexer)
|
||||
type = Type.INDEXER;
|
||||
}
|
||||
else if (node is ident id)
|
||||
{
|
||||
name = id.name;
|
||||
last_name = name;
|
||||
if (binder != null)
|
||||
{
|
||||
var info = binder.bind(id);
|
||||
if (isVarParam(info))
|
||||
{
|
||||
type = Type.VAR_PARAM;
|
||||
}
|
||||
else if (isFromOuterScope(info))
|
||||
{
|
||||
type = Type.FROM_OUTER_SCOPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (node is get_address || node is roof_dereference)
|
||||
{
|
||||
type = Type.POINTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.EXPR;
|
||||
name = node.ToString();
|
||||
last_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public bool StructurallyEquals(Symbol sym) => node.ToString() == sym.node.ToString();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is null) return false;
|
||||
if (obj.GetType() != GetType()) return false;
|
||||
return name == (obj as Symbol).name;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 363513814 + EqualityComparer<string>.Default.GetHashCode(name);
|
||||
}
|
||||
|
||||
|
||||
static bool isFromOuterScope(BindResult bindRes)
|
||||
{
|
||||
var symbol = bindRes.symInfo;
|
||||
|
||||
if (symbol == null)
|
||||
return true;
|
||||
|
||||
if (symbol.SK == SymKind.var && symbol.Attr.HasFlag(SymbolAttributes.varparam_attr))
|
||||
return true;
|
||||
|
||||
if (bindRes.path[bindRes.path.Count - 1] is GlobalScopeSyntax)
|
||||
return true;
|
||||
|
||||
for (var i = 0; i < bindRes.path.Count - 1; i++)
|
||||
if (bindRes.path[i] is NamedScopeSyntax)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isVarParam(BindResult res)
|
||||
{
|
||||
if (res == null)
|
||||
return true;
|
||||
return res.symInfo.Attr.HasFlag(SymbolAttributes.varparam_attr);
|
||||
}
|
||||
}
|
||||
|
||||
public class TempSymbol : Symbol
|
||||
{
|
||||
private static int counter = 0;
|
||||
private static string getTempPrefix => "<tup_opt>" + counter++;
|
||||
public TempSymbol() : base(new ident(getTempPrefix), null)
|
||||
{
|
||||
type = Type.LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
|
||||
namespace AssignTupleDesugarAlgorithm
|
||||
{
|
||||
|
||||
internal class SymbolNode : IEquatable<SymbolNode>
|
||||
{
|
||||
public readonly string label;
|
||||
public int? number = null;
|
||||
public readonly Symbol symbol;
|
||||
|
||||
public SymbolNode(Symbol s)
|
||||
{
|
||||
symbol = s;
|
||||
label = s.name;
|
||||
}
|
||||
|
||||
public enum Color
|
||||
{
|
||||
WHITE,
|
||||
GREY,
|
||||
BLACK
|
||||
}
|
||||
|
||||
public Color color = Color.WHITE;
|
||||
public void resetColor() => color = Color.WHITE;
|
||||
|
||||
public bool Equals(SymbolNode other)
|
||||
{
|
||||
if (other is null) return false;
|
||||
|
||||
return label == other.label;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return label.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
if (GetType() != other.GetType()) return false;
|
||||
return Equals((SymbolNode)other);
|
||||
}
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string n = "";
|
||||
if (number != null)
|
||||
{
|
||||
n = "(" + number.ToString() + ")";
|
||||
}
|
||||
|
||||
return label + n;
|
||||
}
|
||||
}
|
||||
|
||||
internal class TempSymbolNode : SymbolNode
|
||||
{
|
||||
public TempSymbolNode(TempSymbol s) : base(s)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,11 +14,14 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
/// </summary>
|
||||
public class TupleVisitor : BaseChangeVisitor
|
||||
{
|
||||
public static TupleVisitor New
|
||||
public bool optimize_tuple_assign;
|
||||
|
||||
public TupleVisitor(bool optimize_tup_opt)
|
||||
{
|
||||
get { return new TupleVisitor(); }
|
||||
optimize_tuple_assign = optimize_tup_opt;
|
||||
}
|
||||
|
||||
public static TupleVisitor Create(bool optimize_tup_opt) => new TupleVisitor(optimize_tup_opt);
|
||||
private int num = 0;
|
||||
public string UniqueName()
|
||||
{
|
||||
|
|
@ -85,54 +88,57 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
|
||||
public override void visit(assign_tuple asstup)
|
||||
{
|
||||
if (asstup.expr is tuple_node tn && tn.el.expressions.All(ex => ex is const_node) && !tn.el.expressions.Any(ex => ex is nil_const))
|
||||
if (!optimize_tuple_assign)
|
||||
{
|
||||
var n = asstup.vars.variables.Count();
|
||||
if (n > tn.el.Count)
|
||||
throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", asstup.vars.variables[0]);
|
||||
|
||||
// Оптимизация, т.к. все - константы
|
||||
var sl = new List<statement>();
|
||||
for (var i = 0; i < n; i++)
|
||||
if (asstup.expr is tuple_node tn && tn.el.expressions.All(ex => ex is const_node) && !tn.el.expressions.Any(ex => ex is nil_const))
|
||||
{
|
||||
var a = new assign(asstup.vars.variables[i],
|
||||
tn.el.expressions[i],
|
||||
Operators.Assignment,
|
||||
asstup.vars.variables[i].source_context);
|
||||
sl.Add(a);
|
||||
}
|
||||
ReplaceStatementUsingParent(asstup, sl);
|
||||
}
|
||||
else if (asstup.expr is tuple_node tn1 && !tn1.el.expressions.Any(ex => ex is nil_const))
|
||||
{
|
||||
var n = asstup.vars.variables.Count();
|
||||
if (n > tn1.el.Count)
|
||||
throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", asstup.vars.variables[0]);
|
||||
var n = asstup.vars.variables.Count();
|
||||
if (n > tn.el.Count)
|
||||
throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", asstup.vars.variables[0]);
|
||||
|
||||
var sl = new List<statement>();
|
||||
for (var i = 0; i < n; i++)
|
||||
// Оптимизация, т.к. все - константы
|
||||
var sl = new List<statement>();
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var a = new assign(asstup.vars.variables[i],
|
||||
tn.el.expressions[i],
|
||||
Operators.Assignment,
|
||||
asstup.vars.variables[i].source_context);
|
||||
sl.Add(a);
|
||||
}
|
||||
ReplaceStatementUsingParent(asstup, sl);
|
||||
}
|
||||
else if (asstup.expr is tuple_node tn1 && !tn1.el.expressions.Any(ex => ex is nil_const))
|
||||
{
|
||||
var temp_id = new ident(UniqueName(), tn1.el.expressions[i].source_context);
|
||||
var var_def = new var_def_statement(temp_id, tn1.el.expressions[i], tn1.el.expressions[i].source_context);
|
||||
var a = new var_statement(var_def, tn1.el.expressions[i].source_context);
|
||||
sl.Add(a);
|
||||
}
|
||||
var n = asstup.vars.variables.Count();
|
||||
if (n > tn1.el.Count)
|
||||
throw new SyntaxVisitorError("TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMENT", asstup.vars.variables[0]);
|
||||
|
||||
//for (var i = 0; i < n; i++)
|
||||
for (var i = n-1; i >= 0; i--)
|
||||
var sl = new List<statement>();
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var temp_id = new ident(UniqueName(), tn1.el.expressions[i].source_context);
|
||||
var var_def = new var_def_statement(temp_id, tn1.el.expressions[i], tn1.el.expressions[i].source_context);
|
||||
var a = new var_statement(var_def, tn1.el.expressions[i].source_context);
|
||||
sl.Add(a);
|
||||
}
|
||||
|
||||
//for (var i = 0; i < n; i++)
|
||||
for (var i = n - 1; i >= 0; i--)
|
||||
{
|
||||
var a = new assign(asstup.vars.variables[i],
|
||||
(sl[i] as var_statement).var_def.vars.idents[0],
|
||||
Operators.Assignment,
|
||||
asstup.vars.variables[i].source_context);
|
||||
sl.Add(a);
|
||||
}
|
||||
|
||||
ReplaceStatementUsingParent(asstup, sl);
|
||||
}
|
||||
else
|
||||
{
|
||||
var a = new assign(asstup.vars.variables[i],
|
||||
(sl[i] as var_statement).var_def.vars.idents[0],
|
||||
Operators.Assignment,
|
||||
asstup.vars.variables[i].source_context);
|
||||
sl.Add(a);
|
||||
DefaultVisit(asstup);
|
||||
}
|
||||
|
||||
ReplaceStatementUsingParent(asstup, sl);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultVisit(asstup);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@
|
|||
<Compile Include="LightSymInfoVisitors\CollectLightSymInfoVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeCreator.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeHelperClasses.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\Assign.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\AssignGraph.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\Cycle.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\Edge.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\GraphUtils.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\Symbol.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\SymbolNode.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\NewAssignTuplesDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\CacheFunctionVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\LetExprVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\TestAssignIsDefVisitor.cs" />
|
||||
|
|
@ -61,11 +69,12 @@
|
|||
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
|
||||
<Compile Include="ChangeWhileVisitor.cs" />
|
||||
<Compile Include="CheckingVisitors\UnnamedRecordsCheckErrorsVisitor.cs" />
|
||||
<Compile Include="LightSymInfoVisitors\LightScopeHelperClasses.cs" />
|
||||
<Compile Include="PatternsVisitors\ExtendedIsDesugaringVisitor.cs" />
|
||||
<Compile Include="PatternsVisitors\PatternsDesugaringVisitor.cs" />
|
||||
<Compile Include="PatternsVisitors\ReplaceNamesInIsVarVisitor.cs" />
|
||||
<Compile Include="PatternsVisitors\SingleDeconstructChecker.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\AssignTuplesDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\DoubleQuestionDesugarVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\IndexVisitor.cs" />
|
||||
<Compile Include="SugarVisitors\LoopDesugarVisitor.cs" />
|
||||
|
|
|
|||
BIN
bin/AssignTupleOptimizer.dll
Normal file
BIN
bin/AssignTupleOptimizer.dll
Normal file
Binary file not shown.
Loading…
Reference in a new issue