Skip to content

Commit 5804ccb

Browse files
committed
Return proper nil from optional chain
Fixes #570
1 parent e6e376a commit 5804ccb

File tree

4 files changed

+235
-195
lines changed

4 files changed

+235
-195
lines changed

compiler/compiler.go

+21-2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ type scope struct {
9292
index int
9393
}
9494

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+
95102
func (c *compiler) emitLocation(loc file.Location, op Opcode, arg int) int {
96103
c.bytecode = append(c.bytecode, op)
97104
current := len(c.bytecode)
@@ -594,9 +601,21 @@ func isSimpleType(node ast.Node) bool {
594601
func (c *compiler) ChainNode(node *ast.ChainNode) {
595602
c.chains = append(c.chains, []int{})
596603
c.compile(node.Node)
597-
// Chain activate (got nit somewhere)
598604
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)
600619
}
601620
c.chains = c.chains[:len(c.chains)-1]
602621
}

0 commit comments

Comments
 (0)