@@ -1,9 +1,11 @@
 | 
				
			|||||||
using System.Globalization;
 | 
					using System.Globalization;
 | 
				
			||||||
using Canon.Core.CodeGenerators;
 | 
					using Canon.Core.CodeGenerators;
 | 
				
			||||||
using Canon.Core.Enums;
 | 
					using Canon.Core.Enums;
 | 
				
			||||||
 | 
					using Canon.Core.GrammarParser;
 | 
				
			||||||
using Canon.Core.LexicalParser;
 | 
					using Canon.Core.LexicalParser;
 | 
				
			||||||
using Canon.Core.SyntaxNodes;
 | 
					using Canon.Core.SyntaxNodes;
 | 
				
			||||||
using BasicType = Canon.Core.Enums.BasicType;
 | 
					using BasicType = Canon.Core.Enums.BasicType;
 | 
				
			||||||
 | 
					using Expression = Canon.Core.SyntaxNodes.Expression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Canon.Core.SemanticParser;
 | 
					namespace Canon.Core.SemanticParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -278,6 +280,12 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
 | 
				
			|||||||
                : variable.Identifier.IdentifierName;
 | 
					                : variable.Identifier.IdentifierName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private record CircuitLabel(string Circuit, string End);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Stack<CircuitLabel> _andCircuitLabels = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private readonly Stack<CircuitLabel> _orCircuitLabels = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void PreVisit(Term term)
 | 
					    public override void PreVisit(Term term)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.PreVisit(term);
 | 
					        base.PreVisit(term);
 | 
				
			||||||
@@ -286,25 +294,56 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            e.Left.IsCondition = term.IsCondition;
 | 
					            e.Left.IsCondition = term.IsCondition;
 | 
				
			||||||
            e.Right.IsCondition = term.IsCondition;
 | 
					            e.Right.IsCondition = term.IsCondition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (e.Operator.OperatorToken == new Terminator(KeywordType.And))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _andCircuitLabels.Push(new CircuitLabel($"and_circult_{_labelCount}",
 | 
				
			||||||
 | 
					                    $"and_end_{_labelCount}"));
 | 
				
			||||||
 | 
					                _labelCount += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        term.OnFactorGenerator += (_, e) => { e.Factor.IsCondition = term.IsCondition; };
 | 
					        term.OnFactorGenerator += (_, e) => { e.Factor.IsCondition = term.IsCondition; };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private string? _termVariableName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void PostVisit(Term term)
 | 
					    public override void PostVisit(Term term)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.PostVisit(term);
 | 
					        base.PostVisit(term);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        term.OnFactorGenerator += (_, e) => { term.VariableName = e.Factor.VariableName; };
 | 
					        term.OnFactorGenerator += (_, e) =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            term.VariableName = e.Factor.VariableName;
 | 
				
			||||||
 | 
					            _termVariableName = term.VariableName;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        term.OnMultiplyGenerator += (_, e) =>
 | 
					        term.OnMultiplyGenerator += (_, e) =>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            string temporaryName = GenerateTemporaryVariable();
 | 
					            string temporaryName = GenerateTemporaryVariable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Builder.AddLine(
 | 
					            if (e.Operator.OperatorToken == new Terminator(KeywordType.And))
 | 
				
			||||||
                $"{GenerateBasicTypeString(term.VariableType)} {temporaryName} = " +
 | 
					            {
 | 
				
			||||||
                $"{e.Left.VariableName} {GenerateMultipleOperator(e.Operator)} {e.Right.VariableName};");
 | 
					                // 处理and的短路代码
 | 
				
			||||||
 | 
					                Builder.AddLine($"""
 | 
				
			||||||
 | 
					                                 bool {temporaryName} = {e.Left.VariableName} && {e.Right.VariableName};
 | 
				
			||||||
 | 
					                                 goto {_andCircuitLabels.Peek().End};
 | 
				
			||||||
 | 
					                                 {_andCircuitLabels.Peek().Circuit}:;
 | 
				
			||||||
 | 
					                                 {temporaryName} = false;
 | 
				
			||||||
 | 
					                                 {_andCircuitLabels.Peek().End}:;
 | 
				
			||||||
 | 
					                                 """);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _andCircuitLabels.Pop();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Builder.AddLine(
 | 
				
			||||||
 | 
					                    $"{GenerateBasicTypeString(term.VariableType)} {temporaryName} = " +
 | 
				
			||||||
 | 
					                    $"{e.Left.VariableName} {GenerateMultipleOperator(e.Operator)} {e.Right.VariableName};");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            term.VariableName = temporaryName;
 | 
					            term.VariableName = temporaryName;
 | 
				
			||||||
 | 
					            _termVariableName = temporaryName;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -316,26 +355,58 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            e.Left.IsCondition = simpleExpression.IsCondition;
 | 
					            e.Left.IsCondition = simpleExpression.IsCondition;
 | 
				
			||||||
            e.Right.IsCondition = simpleExpression.IsCondition;
 | 
					            e.Right.IsCondition = simpleExpression.IsCondition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (e.Operator.OperatorToken == new Terminator(KeywordType.Or))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _orCircuitLabels.Push(new CircuitLabel($"or_circuit_{_labelCount}",
 | 
				
			||||||
 | 
					                    $"or_end_circuit_{_labelCount}"));
 | 
				
			||||||
 | 
					                _labelCount += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        simpleExpression.OnTermGenerator += (_, e) => { e.Term.IsCondition = simpleExpression.IsCondition; };
 | 
					        simpleExpression.OnTermGenerator += (_, e) => { e.Term.IsCondition = simpleExpression.IsCondition; };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private string? _simpleExpressionVairableName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void PostVisit(SimpleExpression simpleExpression)
 | 
					    public override void PostVisit(SimpleExpression simpleExpression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        base.PostVisit(simpleExpression);
 | 
					        base.PostVisit(simpleExpression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        simpleExpression.OnTermGenerator += (_, e) => { simpleExpression.VariableName = e.Term.VariableName; };
 | 
					        simpleExpression.OnTermGenerator += (_, e) =>
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            simpleExpression.VariableName = e.Term.VariableName;
 | 
				
			||||||
 | 
					            _simpleExpressionVairableName = simpleExpression.VariableName;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        simpleExpression.OnAddGenerator += (_, e) =>
 | 
					        simpleExpression.OnAddGenerator += (_, e) =>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            string temporaryName = GenerateTemporaryVariable();
 | 
					            string temporaryName = GenerateTemporaryVariable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Builder.AddLine(
 | 
					            if (e.Operator.OperatorToken == new Terminator(KeywordType.Or))
 | 
				
			||||||
                $"{GenerateBasicTypeString(simpleExpression.VariableType)} {temporaryName} = " +
 | 
					            {
 | 
				
			||||||
                $"{e.Left.VariableName} {GenerateAddOperator(e.Operator)} {e.Right.VariableName};");
 | 
					                // or的短路代码
 | 
				
			||||||
 | 
					                Builder.AddLine($"""
 | 
				
			||||||
 | 
					                                bool {temporaryName};
 | 
				
			||||||
 | 
					                                {temporaryName} = {e.Left.VariableName} || {e.Right.VariableName};
 | 
				
			||||||
 | 
					                                goto {_orCircuitLabels.Peek().End};
 | 
				
			||||||
 | 
					                                {_orCircuitLabels.Peek().Circuit}:;
 | 
				
			||||||
 | 
					                                {temporaryName} = true;
 | 
				
			||||||
 | 
					                                {_orCircuitLabels.Peek().End}:;
 | 
				
			||||||
 | 
					                                """);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _orCircuitLabels.Pop();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Builder.AddLine(
 | 
				
			||||||
 | 
					                    $"{GenerateBasicTypeString(simpleExpression.VariableType)} {temporaryName} = " +
 | 
				
			||||||
 | 
					                    $"{e.Left.VariableName} {GenerateAddOperator(e.Operator)} {e.Right.VariableName};");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            simpleExpression.VariableName = temporaryName;
 | 
					            simpleExpression.VariableName = temporaryName;
 | 
				
			||||||
 | 
					            _simpleExpressionVairableName = temporaryName;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -723,7 +794,20 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
 | 
				
			|||||||
                                             goto {_whileEndLabels.Peek()};
 | 
					                                             goto {_whileEndLabels.Peek()};
 | 
				
			||||||
                                         """);
 | 
					                                         """);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case KeywordType.And:
 | 
				
			||||||
 | 
					                    // 加上and短路的判断代码
 | 
				
			||||||
 | 
					                    Builder.AddLine($"""
 | 
				
			||||||
 | 
					                                    if (!{_termVariableName})
 | 
				
			||||||
 | 
					                                        goto {_andCircuitLabels.Peek().Circuit};
 | 
				
			||||||
 | 
					                                    """);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case KeywordType.Or:
 | 
				
			||||||
 | 
					                   // 加上or短路的判断代码
 | 
				
			||||||
 | 
					                   Builder.AddLine($"""
 | 
				
			||||||
 | 
					                                   if ({_simpleExpressionVairableName})
 | 
				
			||||||
 | 
					                                        goto {_orCircuitLabels.Peek().Circuit};
 | 
				
			||||||
 | 
					                                   """);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -853,6 +937,8 @@ public class CodeGeneratorVisitor : TypeCheckVisitor
 | 
				
			|||||||
                return basicType.IsReference ? "char *" : "char";
 | 
					                return basicType.IsReference ? "char *" : "char";
 | 
				
			||||||
            case BasicType.Boolean:
 | 
					            case BasicType.Boolean:
 | 
				
			||||||
                return basicType.IsReference ? "bool *" : "bool";
 | 
					                return basicType.IsReference ? "bool *" : "bool";
 | 
				
			||||||
 | 
					            case BasicType.Void:
 | 
				
			||||||
 | 
					                return "void";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return string.Empty;
 | 
					        return string.Empty;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,17 +71,24 @@ public abstract class PascalType : IEquatable<PascalType>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static PascalType operator +(PascalType a, PascalType b)
 | 
					    public static PascalType operator +(PascalType a, PascalType b)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (a is PascalBasicType { Type: BasicType.Boolean } && b is PascalBasicType { Type: BasicType.Boolean })
 | 
					        if (a is not PascalBasicType aType || b is not PascalBasicType bType)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return PascalBasicType.Void;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (aType.Type == BasicType.Boolean && bType.Type == BasicType.Boolean)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return PascalBasicType.Boolean;
 | 
					            return PascalBasicType.Boolean;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (a is PascalBasicType { Type: BasicType.Integer } && b is PascalBasicType { Type: BasicType.Integer })
 | 
					        if (aType.Type == BasicType.Integer && bType.Type == BasicType.Integer)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return PascalBasicType.Integer;
 | 
					            return PascalBasicType.Integer;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (a is PascalBasicType { Type : BasicType.Real } && b is PascalBasicType { Type: BasicType.Real })
 | 
					        if ((aType.Type == BasicType.Real && bType.Type == BasicType.Real)
 | 
				
			||||||
 | 
					            || (aType.Type == BasicType.Real && bType.Type == BasicType.Integer)
 | 
				
			||||||
 | 
					            || (aType.Type == BasicType.Integer && bType.Type == BasicType.Real))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return PascalBasicType.Real;
 | 
					            return PascalBasicType.Real;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user