Browse Source

Merge pull request #28 from AnnulusGames/fix-and-or

Fix and / or
Annulus Games 1 year ago
parent
commit
7e58b1fe49
2 changed files with 82 additions and 66 deletions
  1. 81 66
      src/Lua/CodeAnalysis/Compilation/LuaCompiler.cs
  2. 1 0
      src/Lua/Runtime/LuaVirtualMachine.cs

+ 81 - 66
src/Lua/CodeAnalysis/Compilation/LuaCompiler.cs

@@ -131,74 +131,89 @@ 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;
+            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;
     }
@@ -374,7 +389,7 @@ public sealed class LuaCompiler : ISyntaxNodeVisitor<ScopeCompilationContext, bo
             b = 0;
         }
 
-        CompileExpressionList(node, node.ArgumentNodes, b - 1, context);
+        CompileExpressionList(node, node.ArgumentNodes, b - 2, context);
 
         // push call interuction
         if (isTailCall)

+ 1 - 0
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -948,6 +948,7 @@ public static partial class LuaVirtualMachine
                     Thread = thread,
                     ArgumentCount = 2,
                     SourcePosition = chunk.SourcePositions[pc],
+                    FrameBase = stack.Count - 2,
                 }, methodBuffer, cancellationToken);
 
                 return methodBuffer[0];