Skip to content

Instantly share code, notes, and snippets.

@mrnugget
Last active May 29, 2019 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrnugget/33cd3189cc09fca16ad3b022eb0e6f4f to your computer and use it in GitHub Desktop.
Save mrnugget/33cd3189cc09fca16ad3b022eb0e6f4f to your computer and use it in GitHub Desktop.
Little bug in "Writing A Compiler In Go" 1.0
func TestCallingRecursiveFunctionsInFunctions(t *testing.T) {
tests := []vmTestCase{
{
// This works
input: `
let inner = fn(x) {
if (x == 0) {
return 0;
} else {
inner(x - 1);
}
};
inner(1);
`,
expected: 0,
},
{
// This also works
input: `
let inner = fn(x) {
if (x == 0) {
return 0;
} else {
inner(x - 1);
}
};
let wrapper = fn() {
inner(1);
};
wrapper();
`,
expected: 0,
},
{
// This does _NOT_ work
input: `
let wrapper = fn() {
let inner = fn(x) {
if (x == 0) {
return 0;
} else {
inner(x - 1);
}
};
inner(1);
};
wrapper();
`,
expected: 0,
},
}
runVmTests(t, tests)
}
This is a compiler/constant-pool dump from the third test case:
CONSTANT 0 0xc00009a158 (*object.Integer):
Value: 0
CONSTANT 1 0xc00009a168 (*object.Integer):
Value: 0
CONSTANT 2 0xc00009a190 (*object.Integer):
Value: 1
CONSTANT 3 0xc000078e40 (*object.CompiledFunction):
Instructions:
0000 OpGetLocal 0
0002 OpConstant 0
0005 OpEqual
0006 OpJumpNotTruthy 16
0009 OpConstant 1
0012 OpReturnValue
0013 OpJump 26
0016 OpGetFree 0
0018 OpGetLocal 0
0020 OpConstant 2
0023 OpSub
0024 OpCall 1
0026 OpReturnValue
CONSTANT 4 0xc00009a1b8 (*object.Integer):
Value: 1
CONSTANT 5 0xc000078e70 (*object.CompiledFunction):
Instructions:
0000 OpGetLocal 0
0002 OpClosure 3 1
0006 OpSetLocal 0
0008 OpGetLocal 0
0010 OpConstant 4
0013 OpCall 1
0015 OpReturnValue
main:
0000 OpClosure 5 0
0004 OpSetGlobal 0
0007 OpGetGlobal 0
0010 OpCall 0
0012 OpPop
This is VM trace of the third test case.
FRAME INS OP ARG ARG SP STACK
[01] 0000 OpClosure 5 0 sp= 1 stack=[ Closure[0xc00000a900] ]
[01] 0004 OpSetGlobal 0 sp=0 stack=[]
[01] 0007 OpGetGlobal 0 sp= 1 stack=[ Closure[0xc00000a900] ]
[01] 0010 OpCall 0 sp= 2 stack=[ Closure[0xc00000a900] | <nil> ]
[02] 0000 OpGetLocal 0 sp= 3 stack=[ Closure[0xc00000a900] | <nil> | <nil> ]
[02] 0002 OpClosure 3 1 sp= 3 stack=[ Closure[0xc00000a900] | <nil> | Closure[0xc00000a980] ]
[02] 0006 OpSetLocal 0 sp= 2 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] ]
[02] 0008 OpGetLocal 0 sp= 3 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] ]
[02] 0010 OpConstant 4 sp= 4 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 ]
[02] 0013 OpCall 1 sp= 4 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 ]
[03] 0000 OpGetLocal 0 sp= 5 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | 1 ]
[03] 0002 OpConstant 0 sp= 6 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | 1 | 0 ]
[03] 0005 OpEqual sp= 5 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | false ]
[03] 0006 OpJumpNotTruthy 16 sp= 4 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 ]
[03] 0016 OpGetFree 0 sp= 5 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | <nil> ]
[03] 0018 OpGetLocal 0 sp= 6 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | <nil> | 1 ]
[03] 0020 OpConstant 2 sp= 7 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | <nil> | 1 | 1 ]
[03] 0023 OpSub sp= 6 stack=[ Closure[0xc00000a900] | Closure[0xc00000a980] | Closure[0xc00000a980] | 1 | <nil> | 0 ]
[03] 0024 OpCall 1--- FAIL: TestCallingRecursiveFunctionsInFunctions (0.00s)
vm_test.go:644: vm error: calling non-closure and non-builtin
FAIL
FAIL github.com/mrnugget/monkey/vm 0.005s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment