@@ -92,6 +92,13 @@ type scope struct {
92
92
index int
93
93
}
94
94
95
+ func (c * compiler ) nodeParent () ast.Node {
96
+ if len (c .nodes ) > 1 {
97
+ return c .nodes [len (c .nodes )- 2 ]
98
+ }
99
+ return nil
100
+ }
101
+
95
102
func (c * compiler ) emitLocation (loc file.Location , op Opcode , arg int ) int {
96
103
c .bytecode = append (c .bytecode , op )
97
104
current := len (c .bytecode )
@@ -594,9 +601,21 @@ func isSimpleType(node ast.Node) bool {
594
601
func (c * compiler ) ChainNode (node * ast.ChainNode ) {
595
602
c .chains = append (c .chains , []int {})
596
603
c .compile (node .Node )
597
- // Chain activate (got nit somewhere)
598
604
for _ , ph := range c .chains [len (c .chains )- 1 ] {
599
- c .patchJump (ph )
605
+ c .patchJump (ph ) // If chain activated jump here (got nit somewhere).
606
+ }
607
+ parent := c .nodeParent ()
608
+ if binary , ok := parent .(* ast.BinaryNode ); ok && binary .Operator == "??" {
609
+ // If chain is used in nil coalescing operator, we can omit
610
+ // nil push at the end of the chain. The ?? operator will
611
+ // handle it.
612
+ } else {
613
+ // We need to put the nil on the stack, otherwise "typed"
614
+ // nil will be used as a result of the chain.
615
+ j := c .emit (OpJumpIfNotNil , placeholder )
616
+ c .emit (OpPop )
617
+ c .emit (OpNil )
618
+ c .patchJump (j )
600
619
}
601
620
c .chains = c .chains [:len (c .chains )- 1 ]
602
621
}
0 commit comments