Browse Source

Fix: and/or

AnnulusGames 1 year ago
parent
commit
2e1b5e1f59
1 changed files with 87 additions and 65 deletions
  1. 87 65
      src/Lua/CodeAnalysis/Compilation/LuaCompiler.cs

+ 87 - 65
src/Lua/CodeAnalysis/Compilation/LuaCompiler.cs

@@ -131,74 +131,96 @@ public sealed class LuaCompiler : ISyntaxNodeVisitor<ScopeCompilationContext, bo
     public bool VisitBinaryExpressionNode(BinaryExpressionNode node, ScopeCompilationContext context)
     {
         var r = context.StackPosition;
-        (var b, var c) = GetBAndC(node, context);
-
-        switch (node.OperatorType)
+        if (node.OperatorType is BinaryOperator.And or BinaryOperator.Or)
         {
-            case BinaryOperator.Addition:
-                context.PushInstruction(Instruction.Add(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Subtraction:
-                context.PushInstruction(Instruction.Sub(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Multiplication:
-                context.PushInstruction(Instruction.Mul(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Division:
-                context.PushInstruction(Instruction.Div(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Modulo:
-                context.PushInstruction(Instruction.Mod(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Exponentiation:
-                context.PushInstruction(Instruction.Pow(r, b, c), node.Position);
-                break;
-            case BinaryOperator.Equality:
-                context.PushInstruction(Instruction.Eq(1, b, c), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.Inequality:
-                context.PushInstruction(Instruction.Eq(0, b, c), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.GreaterThan:
-                context.PushInstruction(Instruction.Lt(1, c, b), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.GreaterThanOrEqual:
-                context.PushInstruction(Instruction.Le(1, c, b), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.LessThan:
-                context.PushInstruction(Instruction.Lt(1, b, c), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.LessThanOrEqual:
-                context.PushInstruction(Instruction.Le(1, b, c), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
-                context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
-                break;
-            case BinaryOperator.Concat:
-                context.PushInstruction(Instruction.Concat(r, b, c), node.Position);
-                break;
-            case BinaryOperator.And:
-                context.PushInstruction(Instruction.TestSet(r, b, 0), node.Position);
-                context.PushInstruction(Instruction.Jmp(0, 1), node.Position);
-                context.PushInstruction(Instruction.Move(r, c), node.Position);
-                break;
-            case BinaryOperator.Or:
-                context.PushInstruction(Instruction.TestSet(r, b, 1), node.Position);
-                context.PushInstruction(Instruction.Jmp(0, 1), node.Position);
-                context.PushInstruction(Instruction.Move(r, c), node.Position);
-                break;
+            byte a;
+            if (node.LeftNode is IdentifierNode leftIdentifier)
+            {
+                a = LoadIdentifier(leftIdentifier.Name, context, leftIdentifier.Position, true);
+            }
+            else
+            {
+                node.LeftNode.Accept(this, context);
+                a = context.StackTopPosition;
+            }
+
+            context.PushInstruction(Instruction.Test(a, (byte)(node.OperatorType is BinaryOperator.And ? 0 : 1)), node.Position);
+            var testJmpIndex = context.Function.Instructions.Length;
+            context.PushInstruction(Instruction.Jmp(0, 0), node.Position);
+
+            context.StackPosition = r;
+            if (node.RightNode is IdentifierNode rightIdentifier)
+            {
+                LoadIdentifier(rightIdentifier.Name, context, rightIdentifier.Position, true);
+            }
+            else
+            {
+                node.RightNode.Accept(this, context);
+            }
+
+            context.Function.Instructions[testJmpIndex].SBx = context.Function.Instructions.Length - testJmpIndex - 1;
         }
+        else
+        {
+            (var b, var c) = GetBAndC(node, context);
+
+            switch (node.OperatorType)
+            {
+                case BinaryOperator.Addition:
+                    context.PushInstruction(Instruction.Add(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Subtraction:
+                    context.PushInstruction(Instruction.Sub(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Multiplication:
+                    context.PushInstruction(Instruction.Mul(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Division:
+                    context.PushInstruction(Instruction.Div(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Modulo:
+                    context.PushInstruction(Instruction.Mod(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Exponentiation:
+                    context.PushInstruction(Instruction.Pow(r, b, c), node.Position);
+                    break;
+                case BinaryOperator.Equality:
+                    context.PushInstruction(Instruction.Eq(1, b, c), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.Inequality:
+                    context.PushInstruction(Instruction.Eq(0, b, c), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.GreaterThan:
+                    context.PushInstruction(Instruction.Lt(1, c, b), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.GreaterThanOrEqual:
+                    context.PushInstruction(Instruction.Le(1, c, b), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.LessThan:
+                    context.PushInstruction(Instruction.Lt(1, b, c), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.LessThanOrEqual:
+                    context.PushInstruction(Instruction.Le(1, b, c), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 1, 1), node.Position);
+                    context.PushInstruction(Instruction.LoadBool(r, 0, 0), node.Position);
+                    break;
+                case BinaryOperator.Concat:
+                    context.PushInstruction(Instruction.Concat(r, b, c), node.Position);
+                    break;
+            }
 
-        context.StackPosition = (byte)(r + 1);
+            context.StackPosition = (byte)(r + 1);
+        }
 
         return true;
     }