From 715e2b4be2d839e2bfb550b144074cf3952ecac3 Mon Sep 17 00:00:00 2001 From: zhuliquan Date: Thu, 28 Mar 2024 00:10:08 +0800 Subject: [PATCH 1/2] feat: extract code for compiling equal operator --- compiler/compiler.go | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 808b53c9..a38d977d 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -395,34 +395,12 @@ func (c *compiler) UnaryNode(node *ast.UnaryNode) { } func (c *compiler) BinaryNode(node *ast.BinaryNode) { - l := kind(node.Left) - r := kind(node.Right) - - leftIsSimple := isSimpleType(node.Left) - rightIsSimple := isSimpleType(node.Right) - leftAndRightAreSimple := leftIsSimple && rightIsSimple - switch node.Operator { case "==": - c.compile(node.Left) - c.derefInNeeded(node.Left) - c.compile(node.Right) - c.derefInNeeded(node.Right) - - if l == r && l == reflect.Int && leftAndRightAreSimple { - c.emit(OpEqualInt) - } else if l == r && l == reflect.String && leftAndRightAreSimple { - c.emit(OpEqualString) - } else { - c.emit(OpEqual) - } + c.equalBinaryNode(node) case "!=": - c.compile(node.Left) - c.derefInNeeded(node.Left) - c.compile(node.Right) - c.derefInNeeded(node.Right) - c.emit(OpEqual) + c.equalBinaryNode(node) c.emit(OpNot) case "or", "||": @@ -580,6 +558,28 @@ func (c *compiler) BinaryNode(node *ast.BinaryNode) { } } +func (c *compiler) equalBinaryNode(node *ast.BinaryNode) { + l := kind(node.Left) + r := kind(node.Right) + + leftIsSimple := isSimpleType(node.Left) + rightIsSimple := isSimpleType(node.Right) + leftAndRightAreSimple := leftIsSimple && rightIsSimple + + c.compile(node.Left) + c.derefInNeeded(node.Left) + c.compile(node.Right) + c.derefInNeeded(node.Right) + + if l == r && l == reflect.Int && leftAndRightAreSimple { + c.emit(OpEqualInt) + } else if l == r && l == reflect.String && leftAndRightAreSimple { + c.emit(OpEqualString) + } else { + c.emit(OpEqual) + } +} + func isSimpleType(node ast.Node) bool { if node == nil { return false From 33757149daa05feaeb8734b831081211785e6c86 Mon Sep 17 00:00:00 2001 From: zhuliquan Date: Wed, 26 Jun 2024 23:37:37 +0800 Subject: [PATCH 2/2] fix: fix unary and binary node print consider the precedence of operators and their associative law when printing unary and binary nodes --- ast/print.go | 25 +++++++++++++++++++++++-- ast/print_test.go | 5 +++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/ast/print.go b/ast/print.go index b79048b2..0fd2fa58 100644 --- a/ast/print.go +++ b/ast/print.go @@ -50,8 +50,13 @@ func (n *UnaryNode) String() string { op = fmt.Sprintf("%s ", n.Operator) } wrap := false - switch n.Node.(type) { - case *BinaryNode, *ConditionalNode: + switch b := n.Node.(type) { + case *BinaryNode: + if operator.Binary[b.Operator].Precedence < + operator.Unary[n.Operator].Precedence { + wrap = true + } + case *ConditionalNode: wrap = true } if wrap { @@ -68,10 +73,21 @@ func (n *BinaryNode) String() string { var lhs, rhs string var lwrap, rwrap bool + if l, ok := n.Left.(*UnaryNode); ok { + if operator.Unary[l.Operator].Precedence < + operator.Binary[n.Operator].Precedence { + lwrap = true + } + } if lb, ok := n.Left.(*BinaryNode); ok { if operator.Less(lb.Operator, n.Operator) { lwrap = true } + if operator.Binary[lb.Operator].Precedence == + operator.Binary[n.Operator].Precedence && + operator.Binary[n.Operator].Associativity == operator.Right { + lwrap = true + } if lb.Operator == "??" { lwrap = true } @@ -83,6 +99,11 @@ func (n *BinaryNode) String() string { if operator.Less(rb.Operator, n.Operator) { rwrap = true } + if operator.Binary[rb.Operator].Precedence == + operator.Binary[n.Operator].Precedence && + operator.Binary[n.Operator].Associativity == operator.Left { + rwrap = true + } if operator.IsBoolean(rb.Operator) && n.Operator != rb.Operator { rwrap = true } diff --git a/ast/print_test.go b/ast/print_test.go index a4b20b0a..8f950e27 100644 --- a/ast/print_test.go +++ b/ast/print_test.go @@ -78,6 +78,11 @@ func TestPrint(t *testing.T) { {`{("a" + "b"): 42}`, `{("a" + "b"): 42}`}, {`(One == 1 ? true : false) && Two == 2`, `(One == 1 ? true : false) && Two == 2`}, {`not (a == 1 ? b > 1 : b < 2)`, `not (a == 1 ? b > 1 : b < 2)`}, + {`(-(1+1)) ** 2`, `(-(1 + 1)) ** 2`}, + {`2 ** (-(1+1))`, `2 ** -(1 + 1)`}, + {`(2 ** 2) ** 3`, `(2 ** 2) ** 3`}, + {`(3 + 5) / (5 % 3)`, `(3 + 5) / (5 % 3)`}, + {`(-(1+1)) == 2`, `-(1 + 1) == 2`}, } for _, tt := range tests {