Halt to halt the VM
This commit is contained in:
@@ -62,6 +62,7 @@ const (
|
|||||||
OpGetFree
|
OpGetFree
|
||||||
OpCurrentClosure
|
OpCurrentClosure
|
||||||
OpLoadModule
|
OpLoadModule
|
||||||
|
OpHalt
|
||||||
)
|
)
|
||||||
|
|
||||||
type Definition struct {
|
type Definition struct {
|
||||||
@@ -113,6 +114,7 @@ var definitions = map[Opcode]*Definition{
|
|||||||
OpGetFree: {"OpGetFree", []int{1}},
|
OpGetFree: {"OpGetFree", []int{1}},
|
||||||
OpCurrentClosure: {"OpCurrentClosure", []int{}},
|
OpCurrentClosure: {"OpCurrentClosure", []int{}},
|
||||||
OpLoadModule: {"OpLoadModule", []int{}},
|
OpLoadModule: {"OpLoadModule", []int{}},
|
||||||
|
OpHalt: {"OpHalt", []int{}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func Lookup(op byte) (*Definition, error) {
|
func Lookup(op byte) (*Definition, error) {
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c.emit(code.OpHalt)
|
||||||
|
|
||||||
case *ast.ExpressionStatement:
|
case *ast.ExpressionStatement:
|
||||||
c.l++
|
c.l++
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -45,6 +46,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -55,6 +57,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpSub),
|
code.Make(code.OpSub),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -65,6 +68,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpMul),
|
code.Make(code.OpMul),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,6 +79,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpDiv),
|
code.Make(code.OpDiv),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -85,6 +90,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpMod),
|
code.Make(code.OpMod),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -95,6 +101,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpLeftShift),
|
code.Make(code.OpLeftShift),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -105,6 +112,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpRightShift),
|
code.Make(code.OpRightShift),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -114,6 +122,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpMinus),
|
code.Make(code.OpMinus),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -124,6 +133,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpBitwiseOR),
|
code.Make(code.OpBitwiseOR),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -135,6 +145,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpBitwiseXOR),
|
code.Make(code.OpBitwiseXOR),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -146,6 +157,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpBitwiseAND),
|
code.Make(code.OpBitwiseAND),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -161,6 +173,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpTrue),
|
code.Make(code.OpTrue),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -169,6 +182,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpFalse),
|
code.Make(code.OpFalse),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -177,6 +191,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpNull),
|
code.Make(code.OpNull),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -187,6 +202,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpGreaterThan),
|
code.Make(code.OpGreaterThan),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -197,6 +213,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpGreaterThan),
|
code.Make(code.OpGreaterThan),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -207,6 +224,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpGreaterThanEqual),
|
code.Make(code.OpGreaterThanEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -217,6 +235,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpGreaterThanEqual),
|
code.Make(code.OpGreaterThanEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -227,6 +246,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpEqual),
|
code.Make(code.OpEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -237,6 +257,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpNotEqual),
|
code.Make(code.OpNotEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -247,6 +268,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpFalse),
|
code.Make(code.OpFalse),
|
||||||
code.Make(code.OpEqual),
|
code.Make(code.OpEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -257,6 +279,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpFalse),
|
code.Make(code.OpFalse),
|
||||||
code.Make(code.OpNotEqual),
|
code.Make(code.OpNotEqual),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -267,6 +290,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpFalse),
|
code.Make(code.OpFalse),
|
||||||
code.Make(code.OpAnd),
|
code.Make(code.OpAnd),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -277,6 +301,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpFalse),
|
code.Make(code.OpFalse),
|
||||||
code.Make(code.OpOr),
|
code.Make(code.OpOr),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -286,6 +311,7 @@ func TestBooleanExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpTrue),
|
code.Make(code.OpTrue),
|
||||||
code.Make(code.OpNot),
|
code.Make(code.OpNot),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -300,20 +326,20 @@ func TestConditionals(t *testing.T) {
|
|||||||
if (true) { 10 }; 3333;
|
if (true) { 10 }; 3333;
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{10, 3333},
|
constants: []interface{}{10, 3333},
|
||||||
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 11\n0010 OpNull\n0011 OpPop\n0012 OpConstant 1\n0015 OpPop\n",
|
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 11\n0010 OpNull\n0011 OpPop\n0012 OpConstant 1\n0015 OpPop\n0016 OpHalt\n",
|
||||||
}, {
|
}, {
|
||||||
input: `
|
input: `
|
||||||
if (true) { 10 } else { 20 }; 3333;
|
if (true) { 10 } else { 20 }; 3333;
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{10, 20, 3333},
|
constants: []interface{}{10, 20, 3333},
|
||||||
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 13\n0010 OpConstant 1\n0013 OpPop\n0014 OpConstant 2\n0017 OpPop\n",
|
instructions: "0000 OpTrue\n0001 OpJumpNotTruthy 10\n0004 OpConstant 0\n0007 OpJump 13\n0010 OpConstant 1\n0013 OpPop\n0014 OpConstant 2\n0017 OpPop\n0018 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
x := 0; if (true) { x = 1; }; if (false) { x = 2; }
|
x := 0; if (true) { x = 1; }; if (false) { x = 2; }
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{0, 1, 2},
|
constants: []interface{}{0, 1, 2},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpTrue\n0008 OpJumpNotTruthy 20\n0011 OpConstant 1\n0014 OpAssignGlobal 0\n0017 OpJump 21\n0020 OpNull\n0021 OpPop\n0022 OpFalse\n0023 OpJumpNotTruthy 35\n0026 OpConstant 2\n0029 OpAssignGlobal 0\n0032 OpJump 36\n0035 OpNull\n0036 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpTrue\n0008 OpJumpNotTruthy 20\n0011 OpConstant 1\n0014 OpAssignGlobal 0\n0017 OpJump 21\n0020 OpNull\n0021 OpPop\n0022 OpFalse\n0023 OpJumpNotTruthy 35\n0026 OpConstant 2\n0029 OpAssignGlobal 0\n0032 OpJump 36\n0035 OpNull\n0036 OpPop\n0037 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +354,7 @@ func TestGlobalBindExpressions(t *testing.T) {
|
|||||||
two := 2;
|
two := 2;
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{1, 2},
|
constants: []interface{}{1, 2},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpSetGlobal 1\n0013 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpSetGlobal 1\n0013 OpPop\n0014 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -336,7 +362,7 @@ func TestGlobalBindExpressions(t *testing.T) {
|
|||||||
one;
|
one;
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{1},
|
constants: []interface{}{1},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpPop\n0011 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -345,7 +371,7 @@ func TestGlobalBindExpressions(t *testing.T) {
|
|||||||
two;
|
two;
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{1},
|
constants: []interface{}{1},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpSetGlobal 1\n0013 OpPop\n0014 OpGetGlobal 1\n0017 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpGetGlobal 0\n0010 OpSetGlobal 1\n0013 OpPop\n0014 OpGetGlobal 1\n0017 OpPop\n0018 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +386,7 @@ func TestStringExpressions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -370,6 +397,7 @@ func TestStringExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -385,6 +413,7 @@ func TestArrayLiterals(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpArray, 0),
|
code.Make(code.OpArray, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -396,6 +425,7 @@ func TestArrayLiterals(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 2),
|
code.Make(code.OpConstant, 2),
|
||||||
code.Make(code.OpArray, 3),
|
code.Make(code.OpArray, 3),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -413,6 +443,7 @@ func TestArrayLiterals(t *testing.T) {
|
|||||||
code.Make(code.OpMul),
|
code.Make(code.OpMul),
|
||||||
code.Make(code.OpArray, 3),
|
code.Make(code.OpArray, 3),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -428,6 +459,7 @@ func TestHashLiterals(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpHash, 0),
|
code.Make(code.OpHash, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -442,6 +474,7 @@ func TestHashLiterals(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 5),
|
code.Make(code.OpConstant, 5),
|
||||||
code.Make(code.OpHash, 6),
|
code.Make(code.OpHash, 6),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -458,6 +491,7 @@ func TestHashLiterals(t *testing.T) {
|
|||||||
code.Make(code.OpMul),
|
code.Make(code.OpMul),
|
||||||
code.Make(code.OpHash, 4),
|
code.Make(code.OpHash, 4),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -480,6 +514,7 @@ func TestIndexExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpGetItem),
|
code.Make(code.OpGetItem),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -494,6 +529,7 @@ func TestIndexExpressions(t *testing.T) {
|
|||||||
code.Make(code.OpSub),
|
code.Make(code.OpSub),
|
||||||
code.Make(code.OpGetItem),
|
code.Make(code.OpGetItem),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -518,6 +554,7 @@ func TestFunctions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 2, 0),
|
code.Make(code.OpClosure, 2, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -535,6 +572,7 @@ func TestFunctions(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 2, 0),
|
code.Make(code.OpClosure, 2, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -555,6 +593,7 @@ func TestFunctionsWithoutReturn(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 0, 0),
|
code.Make(code.OpClosure, 0, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -576,7 +615,7 @@ func TestClosures(t *testing.T) {
|
|||||||
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpAdd\n0005 OpReturn\n"),
|
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpAdd\n0005 OpReturn\n"),
|
||||||
Instructions("0000 OpGetLocal 0\n0002 OpClosure 0 1\n0006 OpReturn\n"),
|
Instructions("0000 OpGetLocal 0\n0002 OpClosure 0 1\n0006 OpReturn\n"),
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 1 0\n0004 OpPop\n",
|
instructions: "0000 OpClosure 1 0\n0004 OpPop\n0005 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -593,7 +632,7 @@ func TestClosures(t *testing.T) {
|
|||||||
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpClosure 0 2\n0008 OpReturn\n"),
|
Instructions("0000 OpGetFree 0\n0002 OpGetLocal 0\n0004 OpClosure 0 2\n0008 OpReturn\n"),
|
||||||
Instructions("0000 OpGetLocal 0\n0002 OpClosure 1 1\n0006 OpReturn\n"),
|
Instructions("0000 OpGetLocal 0\n0002 OpClosure 1 1\n0006 OpReturn\n"),
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 2 0\n0004 OpPop\n",
|
instructions: "0000 OpClosure 2 0\n0004 OpPop\n0005 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -622,7 +661,7 @@ func TestClosures(t *testing.T) {
|
|||||||
Instructions("0000 OpConstant 2\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetFree 0\n0008 OpGetLocal 0\n0010 OpClosure 4 2\n0014 OpReturn\n"),
|
Instructions("0000 OpConstant 2\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetFree 0\n0008 OpGetLocal 0\n0010 OpClosure 4 2\n0014 OpReturn\n"),
|
||||||
Instructions("0000 OpConstant 1\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetLocal 0\n0008 OpClosure 5 1\n0012 OpReturn\n"),
|
Instructions("0000 OpConstant 1\n0003 OpSetLocal 0\n0005 OpPop\n0006 OpGetLocal 0\n0008 OpClosure 5 1\n0012 OpReturn\n"),
|
||||||
},
|
},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpClosure 6 0\n0011 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpClosure 6 0\n0011 OpPop\n0012 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +722,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
24,
|
24,
|
||||||
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 1 0\n0004 OpCall 0\n0006 OpPop\n",
|
instructions: "0000 OpClosure 1 0\n0004 OpCall 0\n0006 OpPop\n0007 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -694,7 +733,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
24,
|
24,
|
||||||
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
Instructions("0000 OpConstant 0\n0003 OpReturn\n"),
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 1 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpCall 0\n0013 OpPop\n",
|
instructions: "0000 OpClosure 1 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpCall 0\n0013 OpPop\n0014 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -705,7 +744,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
Instructions("0000 OpGetLocal 0\n0002 OpReturn\n"),
|
Instructions("0000 OpGetLocal 0\n0002 OpReturn\n"),
|
||||||
24,
|
24,
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpCall 1\n0016 OpPop\n",
|
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpCall 1\n0016 OpPop\n0017 OpHalt\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: `
|
input: `
|
||||||
@@ -718,7 +757,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
25,
|
25,
|
||||||
26,
|
26,
|
||||||
},
|
},
|
||||||
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpConstant 2\n0017 OpConstant 3\n0020 OpCall 3\n0022 OpPop\n",
|
instructions: "0000 OpClosure 0 0\n0004 OpSetGlobal 0\n0007 OpPop\n0008 OpGetGlobal 0\n0011 OpConstant 1\n0014 OpConstant 2\n0017 OpConstant 3\n0020 OpCall 3\n0022 OpPop\n0023 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,7 +772,7 @@ func TestAssignmentExpressions(t *testing.T) {
|
|||||||
x = 2
|
x = 2
|
||||||
`,
|
`,
|
||||||
constants: []interface{}{1, 2},
|
constants: []interface{}{1, 2},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpAssignGlobal 0\n0013 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpSetGlobal 0\n0006 OpPop\n0007 OpConstant 1\n0010 OpAssignGlobal 0\n0013 OpPop\n0014 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,6 +802,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpClosure, 2, 0),
|
code.Make(code.OpClosure, 2, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -785,6 +825,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 2, 0),
|
code.Make(code.OpClosure, 2, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -812,6 +853,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpClosure, 1, 0),
|
code.Make(code.OpClosure, 1, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -834,6 +876,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 1, 0),
|
code.Make(code.OpClosure, 1, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -863,6 +906,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 2, 0),
|
code.Make(code.OpClosure, 2, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -883,6 +927,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpSetGlobal, 0),
|
code.Make(code.OpSetGlobal, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -908,6 +953,7 @@ func TestBuiltins(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpCall, 2),
|
code.Make(code.OpCall, 2),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -923,6 +969,7 @@ func TestBuiltins(t *testing.T) {
|
|||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpClosure, 0, 0),
|
code.Make(code.OpClosure, 0, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -957,6 +1004,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 2),
|
code.Make(code.OpConstant, 2),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -995,6 +1043,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpGetGlobal, 0),
|
code.Make(code.OpGetGlobal, 0),
|
||||||
code.Make(code.OpCall, 0),
|
code.Make(code.OpCall, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1024,6 +1073,8 @@ func TestIteration(t *testing.T) {
|
|||||||
code.Make(code.OpNull),
|
code.Make(code.OpNull),
|
||||||
// 0012
|
// 0012
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
|
// 0013
|
||||||
|
code.Make(code.OpHalt),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1036,7 +1087,7 @@ func TestImportExpressions(t *testing.T) {
|
|||||||
{
|
{
|
||||||
input: `import("foo")`,
|
input: `import("foo")`,
|
||||||
constants: []interface{}{"foo"},
|
constants: []interface{}{"foo"},
|
||||||
instructions: "0000 OpConstant 0\n0003 OpLoadModule\n0004 OpPop\n",
|
instructions: "0000 OpConstant 0\n0003 OpLoadModule\n0004 OpPop\n0005 OpHalt\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -686,7 +686,7 @@ func (vm *VM) LastPoppedStackElem() object.Object {
|
|||||||
return vm.stack[vm.sp]
|
return vm.stack[vm.sp]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) Run() error {
|
func (vm *VM) Run() (err error) {
|
||||||
var n int
|
var n int
|
||||||
var ip int
|
var ip int
|
||||||
var ins code.Instructions
|
var ins code.Instructions
|
||||||
@@ -699,9 +699,7 @@ func (vm *VM) Run() error {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
for err == nil {
|
||||||
|
|
||||||
for vm.frame.ip < len(vm.frame.Instructions())-1 && err == nil {
|
|
||||||
vm.frame.ip++
|
vm.frame.ip++
|
||||||
|
|
||||||
ip = vm.frame.ip
|
ip = vm.frame.ip
|
||||||
@@ -894,6 +892,9 @@ func (vm *VM) Run() error {
|
|||||||
case code.OpMinus:
|
case code.OpMinus:
|
||||||
err = vm.executeMinus()
|
err = vm.executeMinus()
|
||||||
|
|
||||||
|
case code.OpHalt:
|
||||||
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("unhandled opcode: %s", op)
|
err = fmt.Errorf("unhandled opcode: %s", op)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user