From aad41fbcbb99fed6a18c83d8b09b498677f96022 Mon Sep 17 00:00:00 2001 From: nub31 Date: Tue, 9 Sep 2025 16:29:42 +0200 Subject: [PATCH] Logical or/and --- example/src/main.nub | 2 +- .../NubLang/Generation/QBE/QBEGenerator.cs | 7 ++- src/compiler/NubLang/Parsing/Parser.cs | 43 +++++++++++-------- .../Parsing/Syntax/ExpressionSyntax.cs | 4 +- src/compiler/NubLang/Tokenization/Token.cs | 2 + .../NubLang/Tokenization/Tokenizer.cs | 2 + .../TypeChecking/Node/ExpressionNode.cs | 2 + .../NubLang/TypeChecking/TypeChecker.cs | 4 ++ 8 files changed, 45 insertions(+), 21 deletions(-) diff --git a/example/src/main.nub b/example/src/main.nub index 1178f56..94dc2b5 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -5,7 +5,7 @@ func main(args: []cstring): i64 { let x: u32 = 23 - if x == 23 && true + if x == 11 || false { puts("yes") } diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs index a8d76de..4d56110 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -725,13 +725,13 @@ public class QBEGenerator var outputName = TmpName(); - var instruction = BinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type); + var instruction = EmitBinaryInstructionForOperator(binaryExpression.Operator, binaryExpression.Left.Type); _writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}"); return outputName; } - private string BinaryInstructionFor(BinaryOperator op, TypeNode type) + private static string EmitBinaryInstructionForOperator(BinaryOperator op, TypeNode type) { return op switch { @@ -881,6 +881,9 @@ public class QBEGenerator }, _ => throw new NotSupportedException($"Greater than or equal comparison not supported for type '{type}'") }, + // todo(nub31): Implement short circuiting + BinaryOperator.LogicalAnd => "and", + BinaryOperator.LogicalOr => "or", _ => throw new ArgumentOutOfRangeException(nameof(op)) }; } diff --git a/src/compiler/NubLang/Parsing/Parser.cs b/src/compiler/NubLang/Parsing/Parser.cs index 486f277..ed3a464 100644 --- a/src/compiler/NubLang/Parsing/Parser.cs +++ b/src/compiler/NubLang/Parsing/Parser.cs @@ -344,31 +344,34 @@ public sealed class Parser return left; } - private int GetBinaryOperatorPrecedence(BinaryOperatorSyntax operatorSyntax) + private static int GetBinaryOperatorPrecedence(BinaryOperatorSyntax operatorSyntax) { return operatorSyntax switch { - BinaryOperatorSyntax.Multiply => 6, - BinaryOperatorSyntax.Divide => 6, - BinaryOperatorSyntax.Modulo => 6, + BinaryOperatorSyntax.Multiply => 10, + BinaryOperatorSyntax.Divide => 10, + BinaryOperatorSyntax.Modulo => 10, - BinaryOperatorSyntax.Plus => 5, - BinaryOperatorSyntax.Minus => 5, + BinaryOperatorSyntax.Plus => 9, + BinaryOperatorSyntax.Minus => 9, - BinaryOperatorSyntax.LeftShift => 4, - BinaryOperatorSyntax.RightShift => 4, + BinaryOperatorSyntax.LeftShift => 8, + BinaryOperatorSyntax.RightShift => 8, - BinaryOperatorSyntax.GreaterThan => 3, - BinaryOperatorSyntax.GreaterThanOrEqual => 3, - BinaryOperatorSyntax.LessThan => 3, - BinaryOperatorSyntax.LessThanOrEqual => 3, + BinaryOperatorSyntax.GreaterThan => 7, + BinaryOperatorSyntax.GreaterThanOrEqual => 7, + BinaryOperatorSyntax.LessThan => 7, + BinaryOperatorSyntax.LessThanOrEqual => 7, - BinaryOperatorSyntax.Equal => 2, - BinaryOperatorSyntax.NotEqual => 2, + BinaryOperatorSyntax.Equal => 7, + BinaryOperatorSyntax.NotEqual => 7, - BinaryOperatorSyntax.BitwiseAnd => 1, - BinaryOperatorSyntax.BitwiseXor => 0, - BinaryOperatorSyntax.BitwiseOr => -1, + BinaryOperatorSyntax.BitwiseAnd => 6, + BinaryOperatorSyntax.BitwiseXor => 5, + BinaryOperatorSyntax.BitwiseOr => 4, + + BinaryOperatorSyntax.LogicalAnd => 3, + BinaryOperatorSyntax.LogicalOr => 2, _ => throw new ArgumentOutOfRangeException(nameof(operatorSyntax), operatorSyntax, null) }; @@ -396,6 +399,12 @@ public sealed class Parser case Symbol.GreaterThanOrEqual: binaryExpressionOperator = BinaryOperatorSyntax.GreaterThanOrEqual; return true; + case Symbol.And: + binaryExpressionOperator = BinaryOperatorSyntax.LogicalAnd; + return true; + case Symbol.Or: + binaryExpressionOperator = BinaryOperatorSyntax.LogicalOr; + return true; case Symbol.Plus: binaryExpressionOperator = BinaryOperatorSyntax.Plus; return true; diff --git a/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs b/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs index 077aba2..cb42096 100644 --- a/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs +++ b/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs @@ -16,6 +16,8 @@ public enum BinaryOperatorSyntax GreaterThanOrEqual, LessThan, LessThanOrEqual, + LogicalAnd, + LogicalOr, Plus, Minus, Multiply, @@ -25,7 +27,7 @@ public enum BinaryOperatorSyntax RightShift, BitwiseAnd, BitwiseXor, - BitwiseOr + BitwiseOr, } public abstract record ExpressionSyntax(IEnumerable Tokens) : SyntaxNode(Tokens); diff --git a/src/compiler/NubLang/Tokenization/Token.cs b/src/compiler/NubLang/Tokenization/Token.cs index dacd560..297c043 100644 --- a/src/compiler/NubLang/Tokenization/Token.cs +++ b/src/compiler/NubLang/Tokenization/Token.cs @@ -74,4 +74,6 @@ public enum Symbol LeftShift, RightShift, Pipe, + And, + Or, } \ No newline at end of file diff --git a/src/compiler/NubLang/Tokenization/Tokenizer.cs b/src/compiler/NubLang/Tokenization/Tokenizer.cs index 9cb1f2d..f18c109 100644 --- a/src/compiler/NubLang/Tokenization/Tokenizer.cs +++ b/src/compiler/NubLang/Tokenization/Tokenizer.cs @@ -30,6 +30,8 @@ public sealed class Tokenizer [['>', '=']] = Symbol.GreaterThanOrEqual, [['<', '<']] = Symbol.LeftShift, [['>', '>']] = Symbol.RightShift, + [['&', '&']] = Symbol.And, + [['|', '|']] = Symbol.Or, [[':']] = Symbol.Colon, [['(']] = Symbol.OpenParen, [[')']] = Symbol.CloseParen, diff --git a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs b/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs index 4d214c7..0928db6 100644 --- a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs +++ b/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs @@ -16,6 +16,8 @@ public enum BinaryOperator GreaterThanOrEqual, LessThan, LessThanOrEqual, + LogicalAnd, + LogicalOr, Plus, Minus, Multiply, diff --git a/src/compiler/NubLang/TypeChecking/TypeChecker.cs b/src/compiler/NubLang/TypeChecking/TypeChecker.cs index ce3f8f3..6730360 100644 --- a/src/compiler/NubLang/TypeChecking/TypeChecker.cs +++ b/src/compiler/NubLang/TypeChecking/TypeChecker.cs @@ -364,6 +364,8 @@ public sealed class TypeChecker BinaryOperatorSyntax.BitwiseAnd => BinaryOperator.BitwiseAnd, BinaryOperatorSyntax.BitwiseXor => BinaryOperator.BitwiseXor, BinaryOperatorSyntax.BitwiseOr => BinaryOperator.BitwiseOr, + BinaryOperatorSyntax.LogicalAnd => BinaryOperator.LogicalAnd, + BinaryOperatorSyntax.LogicalOr => BinaryOperator.LogicalOr, _ => throw new ArgumentOutOfRangeException(nameof(expression.Operator), expression.Operator, null) }; @@ -375,6 +377,8 @@ public sealed class TypeChecker BinaryOperator.GreaterThanOrEqual => new BoolTypeNode(), BinaryOperator.LessThan => new BoolTypeNode(), BinaryOperator.LessThanOrEqual => new BoolTypeNode(), + BinaryOperator.LogicalAnd => new BoolTypeNode(), + BinaryOperator.LogicalOr => new BoolTypeNode(), BinaryOperator.Plus => boundLeft.Type, BinaryOperator.Minus => boundLeft.Type, BinaryOperator.Multiply => boundLeft.Type,