添加对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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user