Skip to content

Commit

Permalink
Return proper nil from optional chain
Browse files Browse the repository at this point in the history
Fixes #570
  • Loading branch information
antonmedv committed Apr 16, 2024
1 parent e6e376a commit 5804ccb
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 195 deletions.
23 changes: 21 additions & 2 deletions compiler/compiler.go
Expand Up @@ -92,6 +92,13 @@ type scope struct {
index int
}

func (c *compiler) nodeParent() ast.Node {
if len(c.nodes) > 1 {
return c.nodes[len(c.nodes)-2]
}
return nil
}

func (c *compiler) emitLocation(loc file.Location, op Opcode, arg int) int {
c.bytecode = append(c.bytecode, op)
current := len(c.bytecode)
Expand Down Expand Up @@ -594,9 +601,21 @@ func isSimpleType(node ast.Node) bool {
func (c *compiler) ChainNode(node *ast.ChainNode) {
c.chains = append(c.chains, []int{})
c.compile(node.Node)
// Chain activate (got nit somewhere)
for _, ph := range c.chains[len(c.chains)-1] {
c.patchJump(ph)
c.patchJump(ph) // If chain activated jump here (got nit somewhere).
}
parent := c.nodeParent()
if binary, ok := parent.(*ast.BinaryNode); ok && binary.Operator == "??" {
// If chain is used in nil coalescing operator, we can omit
// nil push at the end of the chain. The ?? operator will
// handle it.
} else {
// We need to put the nil on the stack, otherwise "typed"
// nil will be used as a result of the chain.
j := c.emit(OpJumpIfNotNil, placeholder)
c.emit(OpPop)
c.emit(OpNil)
c.patchJump(j)
}
c.chains = c.chains[:len(c.chains)-1]
}
Expand Down

0 comments on commit 5804ccb

Please sign in to comment.