|
|
@@ -135,7 +135,7 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
- if c.lastInstructionIsPop() {
|
|
|
+ if c.lastInstructionIs(code.OpPop) {
|
|
|
c.removeLastPop()
|
|
|
}
|
|
|
|
|
|
@@ -152,7 +152,7 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- if c.lastInstructionIsPop() {
|
|
|
+ if c.lastInstructionIs(code.OpPop) {
|
|
|
c.removeLastPop()
|
|
|
}
|
|
|
}
|
|
|
@@ -248,6 +248,12 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
+ if c.lastInstructionIs(code.OpPop) {
|
|
|
+ c.replaceLastPopWithReturn()
|
|
|
+ }
|
|
|
+ if !c.lastInstructionIs(code.OpReturnValue) {
|
|
|
+ c.emit(code.OpReturn)
|
|
|
+ }
|
|
|
instructions := c.leaveScope()
|
|
|
|
|
|
compiledFn := &object.CompileFunction{Instructions: instructions}
|
|
|
@@ -298,6 +304,13 @@ func (c *Compiler) lastInstructionIsPop() bool {
|
|
|
return c.scopes[c.scopeIndex].lastInstruction.Opcode == code.OpPop
|
|
|
}
|
|
|
|
|
|
+func (c *Compiler) lastInstructionIs(op code.Opcode) bool {
|
|
|
+ if len(c.currentInstructions()) == 0 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return c.scopes[c.scopeIndex].lastInstruction.Opcode == op
|
|
|
+}
|
|
|
+
|
|
|
func (c *Compiler) removeLastPop() {
|
|
|
last := c.scopes[c.scopeIndex].lastInstruction
|
|
|
previous := c.scopes[c.scopeIndex].previousInstruction
|
|
|
@@ -346,6 +359,13 @@ func (c *Compiler) leaveScope() code.Instructions {
|
|
|
return ins
|
|
|
}
|
|
|
|
|
|
+func (c *Compiler) replaceLastPopWithReturn() {
|
|
|
+ lastPop := c.scopes[c.scopeIndex].lastInstruction.Position
|
|
|
+ c.replaceInstruction(lastPop, code.Make(code.OpReturnValue))
|
|
|
+
|
|
|
+ c.scopes[c.scopeIndex].lastInstruction.Opcode = code.OpReturnValue
|
|
|
+}
|
|
|
+
|
|
|
func (c *Compiler) ByteCode() *ByteCode {
|
|
|
return &ByteCode{
|
|
|
Instructions: c.currentInstructions(),
|