First 'is' prototype

This commit is contained in:
Alexander Zakharenko 2018-05-16 00:26:07 +03:00
parent 556b4bb3c5
commit 174613056f
5 changed files with 1220 additions and 1126 deletions

View file

@ -2,7 +2,7 @@
// This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301
// Machine: ALEXANDER-PC
// DateTime: 13.05.2018 15:19:04
// DateTime: 15.05.2018 21:41:30
// UserName: Alexander
// GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource>

View file

@ -3010,10 +3010,11 @@ relop_expr
{
$$ = new bin_expr($1, $3, $2.type, @$);
}
| is_expr pattern
| is_expr tkRoundOpen pattern_out_param_list tkRoundClose
{
var isTypeCheck = $1 as typecast_node;
$$ = new is_pattern_expr(isTypeCheck.expr, $2, @$);
var deconstructorPattern = new deconstructor_pattern($3 as List<pattern_deconstructor_parameter>, isTypeCheck.type_def, @$);
$$ = new is_pattern_expr(isTypeCheck.expr, deconstructorPattern, @$);
}
;
@ -3049,7 +3050,7 @@ pattern_out_param
}
| pattern
{
$$ = new recursive_deconstructor_parameter($1, @$);
$$ = new recursive_deconstructor_parameter($1 as pattern_node, @$);
}
;

File diff suppressed because it is too large Load diff

View file

@ -60,24 +60,24 @@ end;
// ----
begin
var <>genVar1: P1;
var <>genVar_s: ?;
var s: ?;
var <>success1 := false;
if IsTest(e, <>genVar1) then
<>genVar1.Deconstruct(s);
<>success1 := true;
<>genVar1.Deconstruct(<>genVar_s);
var <>genVar2: P2;
var <>genVar_t: ?;
var t: ?;
var <>success2 := false;
if IsTest(<>genVar_s, <>genVar2) then
<>genVar2.Deconstruct(<>genVar_t);
if IsTest(t, <>genVar2) then
<>genVar2.Deconstruct(t);
<>success2 := true;
if (<>success and <>success2)
var s := <>genVar_s;
var t := <>genVar_t;
<ACTION>
else
<ACTION_ELSE>
goto empty_statement;
end
<ACTION_ELSE>
end_if_label: empty_statement

View file

@ -28,12 +28,6 @@ namespace SyntaxVisitors.SugarVisitors
/// </summary>
public List<var_def_statement> DeconstructionVariables { get; private set; } = new List<var_def_statement>();
/// <summary>
/// Список объявлений, которые должны быть включены внутрь особых конструкций, для ограничения области видимости.
/// Например внутрь тела then, если паттерн объявлен в условии if.
/// </summary>
public List<var_statement> InternalAssignments { get; private set; } = new List<var_statement>();
/// <summary>
/// Проверка соответствия типа выражения типу паттерна
/// </summary>
@ -50,9 +44,10 @@ namespace SyntaxVisitors.SugarVisitors
public List<statement> GetDeconstructionDefinitions(SourceContext patternContext)
{
var result = DeconstructionVariables
.Select(x => new desugared_deconstruction(DeconstructionVariables, CastVariable, patternContext))
.ToList<statement>();
var result = new List<statement>();
result.Add(CastVariableDefinition);
result.AddRange(DeconstructionVariables
.Select(x => new desugared_deconstruction(DeconstructionVariables, CastVariable, patternContext)));
result.Add(SuccessVariableDefinition);
return result;
@ -78,6 +73,8 @@ namespace SyntaxVisitors.SugarVisitors
private if_node _previousIf;
private statement desugaredMatchWith;
private List<if_node> processedIfNodes = new List<if_node>();
public static PatternsDesugaringVisitor New => new PatternsDesugaringVisitor();
public override void visit(match_with matchWith)
@ -109,8 +106,10 @@ namespace SyntaxVisitors.SugarVisitors
public override void visit(is_pattern_expr isPatternExpr)
{
if (isPatternExpr.right is type_pattern)
DesugarIsExpression(isPatternExpr);
Debug.Assert(GetCurrentLocation() != PatternLocation.Unknown, "Is-pattern expression is in an unknown context");
Debug.Assert(GetAscendant<statement_list>() != null, "Couldn't find statement list in upper nodes");
DesugarIsExpression(isPatternExpr);
}
void DesugarDeconstructorPatternCase(expression matchingExpression, pattern_case patternCase)
@ -147,15 +146,11 @@ namespace SyntaxVisitors.SugarVisitors
//AddDesugaredCaseToResult(result, ifCheck);
}
private ident NewGeneralName()
{
return new ident(GeneratedPatternNamePrefix + "GenVar" + _variableCounter++);
}
private ident NewGeneralName() => new ident(GeneratedPatternNamePrefix + "GenVar" + _variableCounter++);
private ident NewSuccessName()
{
return new ident(GeneratedPatternNamePrefix + "Success" + _variableCounter++);
}
private ident NewSuccessName() => new ident(GeneratedPatternNamePrefix + "Success" + _variableCounter++);
private ident NewEndIfName() => new ident(GeneratedPatternNamePrefix + "EndIf" + _variableCounter++);
private bool IsGenerated(string name) => name.StartsWith(GeneratedPatternNamePrefix);
@ -196,17 +191,8 @@ namespace SyntaxVisitors.SugarVisitors
var parameters = pattern.parameters.Cast<var_deconstructor_parameter>();
foreach (var deconstructedVariable in parameters)
{
if (IsGenerated(deconstructedVariable.identifier.name))
desugarResult.DeconstructionVariables.Add(
new var_def_statement(deconstructedVariable.identifier, deconstructedVariable.type));
else
{
var newVariable = NewGeneralName();
desugarResult.DeconstructionVariables.Add(
new var_def_statement(newVariable, deconstructedVariable.type));
desugarResult.InternalAssignments.Add(
new var_statement(deconstructedVariable.identifier, newVariable));
}
desugarResult.DeconstructionVariables.Add(
new var_def_statement(deconstructedVariable.identifier, deconstructedVariable.type));
}
var deconstructCall = new procedure_call();
@ -220,17 +206,114 @@ namespace SyntaxVisitors.SugarVisitors
{
Debug.Assert(isPatternExpr.right is deconstructor_pattern);
var pattern = isPatternExpr.right as deconstructor_pattern;
var patternLocation = GetCurrentLocation();
var desugaringResult = DesugarPattern(pattern, isPatternExpr.left);
switch (patternLocation)
{
case PatternLocation.IfCondition: DesugarIsExpressionInIfCondition(isPatternExpr); break;
case PatternLocation.Assign: DesugarIsExpressionInAssignment(isPatternExpr); break;
}
}
private void DesugarIsExpressionInAssignment(is_pattern_expr isExpression)
{
var pattern = isExpression.right as deconstructor_pattern;
var desugaringResult = DesugarPattern(pattern, isExpression.left);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context);
statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall());
AddDefinitionsInUpperStatementList(statementsToAdd);
}
ReplaceUsingParent(isPatternExpr, desugaringResult.SuccessVariable);
private void DesugarIsExpressionInIfCondition(is_pattern_expr isExpression)
{
var pattern = isExpression.right as deconstructor_pattern;
var desugaringResult = DesugarPattern(pattern, isExpression.left);
ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable);
var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context);
statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall());
var enclosingIf = GetAscendant<if_node>();
// Если уже обрабатывался ранее (второй встретившийся в том же условии is), то не изменяем if
if (processedIfNodes.Contains(enclosingIf))
AddDefinitionsInUpperStatementList(statementsToAdd);
// Иначе помещаем определения и if-then в отдельный блок, а else после этого блока
else
ReplaceUsingParent(enclosingIf, ConvertIfNode(enclosingIf, statementsToAdd));
}
private statement_list ConvertIfNode(if_node ifNode, List<statement> statementsBeforeIf)
{
// if e then <then> else <else>
//
// переводим в
//
// begin
// statementsBeforeIf
// if e then begin <then>; goto end_if end;
// end
// <else>
// end_if: empty_statement
// if e then <then>
//
// переводим в
//
// begin
// statementsBeforeIf
// if e then <then>
// end
ifNode = ifNode.TypedClone();
// Добавляем, чтобы на конвертировать еще раз, если потребуется
processedIfNodes.Add(ifNode);
var statementsBeforeAndIf = new statement_list();
statementsBeforeAndIf.AddMany(statementsBeforeIf);
statementsBeforeAndIf.Add(ifNode);
if (ifNode.else_body == null)
return statementsBeforeAndIf;
else
{
var result = new statement_list();
result.Add(statementsBeforeAndIf);
var endIfLabel = NewEndIfName();
// добавляем метку
if (!(ifNode.then_body is statement_list))
{
ifNode.then_body = new statement_list(ifNode.then_body, ifNode.then_body.source_context);
ifNode.then_body.Parent = ifNode;
}
var thenBody = ifNode.then_body as statement_list;
thenBody.Add(new goto_statement(endIfLabel));
// добавляем else и метку за ним
result.Add(ifNode.else_body);
result.Add(new labeled_statement(endIfLabel));
// удаляем else из if
ifNode.else_body = null;
// перепрошиваем Parent
result.FillParentsInDirectChilds();
// Добавляем метку
AddLabel(endIfLabel);
return result;
}
}
private void AddLabel(ident label)
{
var block = GetAscendant<program_module>().program_block;
if (block.defs == null)
block.defs = new declarations();
block.defs.Add(new label_definitions(label));
}
private void AddDefinitionsInUpperStatementList(IEnumerable<statement> statementsToAdd)
@ -259,6 +342,13 @@ namespace SyntaxVisitors.SugarVisitors
private PatternLocation GetCurrentLocation()
{
var firstStatement = GetAscendant<statement>();
switch (firstStatement)
{
case if_node _: return PatternLocation.IfCondition;
case assign _: return PatternLocation.Assign;
default: return PatternLocation.Unknown;
}
}
private T GetAscendant<T>()