pascalabcnet/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs
Александр Земляк 17f6a9b956
Spython test suite (#3362)
* Reorganize files in TestSuite dir for multiple languages

* Add SPython samples to TestSuite

* Update TestRunner to support multiple languages

* Delete dll files accidentally pushed

* Update .gitignore

* Revert "Delete dll files accidentally pushed"

This reverts commit 62bcba2b821d58ae51ec98e9dadcf621bb0fc003.

* Update testing dir path in Testing.cs

* Improve TestRunner output

* Add random module and it's usage sample

* Reorganize gitignore files

* Move pascal tests back to TestSuite and create new TestSuiteLanguagePlugins folder for SPython

* Revert "Update testing dir path in Testing.cs"

This reverts commit 7d94eafb25292421bce8315520b4f6a0de001bbd.

* Revert crlf changes in pascal tests

* Test changes of _RebuildReleaseAndRunTestsForGitHubActions.bat

* Revert "Test changes of _RebuildReleaseAndRunTestsForGitHubActions.bat"

This reverts commit 234ceae3e3a339fbc68a6170e2bd201dab14d67d.

* Test changes in StorageLocationPicker

* Another test changes in StorageLocationPicker.cs

* Rename LanguagePlugins folder to AdditionalLanguages

* Decouple TestRunner from language names and parameters

* Revert calling TestRunner without parameters in .bat files

* Fix formatter tests nogui exception handling

* Small refactoring in Testing.cs and TestRunner fix of working directory
2025-12-21 21:11:52 +03:00

102 lines
4 KiB
C#

using PascalABCCompiler.SyntaxTree;
using System.Collections.Generic;
namespace Languages.SPython.Frontend.Converters
{
internal class CompoundComparisonDesugarVisitor : BaseChangeVisitor
{
private int curr_sl_index;
public CompoundComparisonDesugarVisitor() { }
public override void visit(statement_list sl)
{
if (sl == null) return;
for (var i = sl.subnodes_count - 1; i >= 0; i--)
{
curr_sl_index = i;
ProcessNode(sl[i]);
}
}
private static statement_list GetCurrentStatementList(syntax_tree_node curr)
{
while (!(curr is statement_list)) curr = curr.Parent;
return curr as statement_list;
}
private static bool IsComparison(bin_expr _bin_expr)
{
Operators Operator = _bin_expr.operation_type;
switch (Operator)
{
case Operators.Less:
case Operators.Greater:
case Operators.LessEqual:
case Operators.GreaterEqual:
case Operators.Equal:
case Operators.NotEqual:
return true;
}
return false;
}
private static bool IsCompoundComparison(bin_expr _bin_expr)
{
return (_bin_expr.left is bin_expr left) && IsComparison(_bin_expr) && IsComparison(left);
}
private int createdIdentsCounter = 0;
private string NewIdentName()
{
string result = '%' + createdIdentsCounter.ToString();
createdIdentsCounter++;
return result;
}
public override void visit(bin_expr _bin_expr)
{
if (IsCompoundComparison(_bin_expr))
{
// transform
//
// ((left comp1 middle) comp2 right)
//
// to
//
// var id: typeof(middle);
// ((left comp1 !assign(id, middle)) && (id comp2 right))
//
// then recursive call for left
// P.S. !assign(a, b) assigns b to a and return a
bin_expr left_comp_middle = _bin_expr.left as bin_expr;
expression left = left_comp_middle.left;
Operators comp1 = left_comp_middle.operation_type;
expression middle = left_comp_middle.right;
Operators comp2 = _bin_expr.operation_type;
expression right = _bin_expr.right;
ident id = new ident(NewIdentName(), middle.source_context);
type_definition td = new same_type_node(middle.TypedClone(), middle.source_context);
var_def_statement vds = new var_def_statement(id, td, middle.source_context);
statement_list curr_statement_list = GetCurrentStatementList(_bin_expr);
int index = curr_sl_index - curr_statement_list.subnodes_without_list_elements_count;
curr_statement_list.list.Insert(index, new var_statement(vds, middle.source_context));
curr_sl_index++;
addressed_value method_name = new ident("!assign", middle.source_context);
expression_list el = new expression_list(new List<expression> { id, middle }, middle.source_context);
method_call method_call = new method_call(method_name, el, middle.source_context);
bin_expr new_left = new bin_expr(left, method_call, comp1, new SourceContext(left.source_context, method_call.source_context));
bin_expr new_right = new bin_expr(id, right, comp2, new SourceContext(id.source_context, right.source_context));
bin_expr new_bin_expr = new bin_expr(new_left, new_right, Operators.LogicalAND, _bin_expr.source_context);
_bin_expr.Parent.ReplaceDescendant(_bin_expr, new_bin_expr);
new_bin_expr.left.visit(this);
}
else
base.visit(_bin_expr);
}
}
}