添加对while-do语句的支持 (#77)

Co-authored-by: jackfiled <xcrenchangjun@outlook.com>
Reviewed-on: PostGuard/Canon#77
Co-authored-by: ichirinko <1621543655@qq.com>
Co-committed-by: ichirinko <1621543655@qq.com>
This commit is contained in:
ichirinko
2024-05-10 13:52:11 +08:00
committed by jackfiled
parent 4a712fc462
commit f993d49856
11 changed files with 867 additions and 704 deletions

View File

@@ -294,6 +294,18 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
};
}
public override void PreVisit(Expression expression)
{
base.PreVisit(expression);
if (expression.IsWhileCondition)
{
GenerateWhileLabel();
Builder.AddLine($"""
{_whileBeginLabels.Peek()}:;
""");
}
}
public override void PostVisit(Expression expression)
{
base.PostVisit(expression);
@@ -333,6 +345,11 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
{
_forEndConditions.Push(expression.VariableName);
}
if (expression.IsWhileCondition)
{
_whileConditionNames.Push(expression.VariableName);
}
}
@@ -386,6 +403,21 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
/// </summary>
private readonly Stack<string> _forEndLabels = new();
/// <summary>
/// WHILE语句条件变量的标签
/// </summary>
private readonly Stack<string> _whileConditionNames = new();
/// <summary>
/// WHILE语句开始的标签
/// </summary>
private readonly Stack<string> _whileBeginLabels = new();
/// <summary>
/// WHILE语句结束的标签
/// </summary>
private readonly Stack<string> _whileEndLabels = new();
public override void PreVisit(Statement statement)
{
base.PreVisit(statement);
@@ -396,8 +428,15 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
{
e.Begin.IsForConditionBegin = true;
e.End.IsForConditionEnd = true;
e.Do.IsForNode = true;
_forVariables.Push(e.Iterator.IdentifierName);
};
statement.OnWhileGenerator += (_, e) =>
{
e.Do.IsWhileNode = true;
e.Condition.IsWhileCondition = true;
};
}
public override void PostVisit(Statement statement)
@@ -434,6 +473,17 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
_forBeginConditions.Pop();
_forEndConditions.Pop();
};
statement.OnWhileGenerator += (_, _) =>
{
Builder.AddLine($"""
goto {_whileBeginLabels.Peek()};
{_whileEndLabels.Peek()}:;
""");
_whileBeginLabels.Pop();
_whileEndLabels.Pop();
_whileConditionNames.Pop();
};
}
public override void PreVisit(ElsePart elsePart)
@@ -605,13 +655,26 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
""");
break;
case KeywordType.Do:
Builder.AddLine($"""
if ({_forVariables.Peek()} <= {_forEndConditions.Peek()})
goto {_forLabels.Peek()};
else
goto {_forEndLabels.Peek()};
{_forLabels.Peek()}:;
""");
if (terminatedSyntaxNode.IsForNode)
{
Builder.AddLine($"""
if ({_forVariables.Peek()} <= {_forEndConditions.Peek()})
goto {_forLabels.Peek()};
else
goto {_forEndLabels.Peek()};
{_forLabels.Peek()}:;
""");
}
if (terminatedSyntaxNode.IsWhileNode)
{
// GenerateWhileLabel();
Builder.AddLine($"""
if (!{_whileConditionNames.Peek()})
goto {_whileEndLabels.Peek()};
""");
}
break;
}
}
@@ -881,4 +944,16 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
_labelCount += 1;
}
/// <summary>
/// 产生WHILE语句中的标签
/// </summary>
private void GenerateWhileLabel()
{
_whileBeginLabels.Push($"while_{_labelCount}");
_whileConditionNames.Push($"while_condition_{_labelCount}");
_whileEndLabels.Push($"while_end_{_labelCount}");
_labelCount += 1;
}
}

View File

@@ -478,6 +478,18 @@ public class TypeCheckVisitor(ICompilerLogger? logger = null) : SyntaxNodeVisito
e.Condition.VariableType.ToString());
}
};
// statement -> while Expression do Statement
statement.OnWhileGenerator += (_, e) =>
{
// 条件是否为Boolean
if (e.Condition.VariableType != PascalBasicType.Boolean)
{
IsError = true;
logger?.LogError("Expect '{}' but '{}'.", PascalBasicType.Boolean.TypeName,
e.Condition.VariableType.ToString());
}
};
}
public override void PostVisit(ProcedureCall procedureCall)