Simplify return operation
This commit is contained in:
@@ -36,7 +36,6 @@ const (
|
|||||||
OpHash
|
OpHash
|
||||||
OpIndex
|
OpIndex
|
||||||
OpCall
|
OpCall
|
||||||
OpReturnValue
|
|
||||||
OpReturn
|
OpReturn
|
||||||
OpGetLocal
|
OpGetLocal
|
||||||
OpSetLocal
|
OpSetLocal
|
||||||
@@ -78,7 +77,6 @@ var definitions = map[Opcode]*Definition{
|
|||||||
OpHash: {"OpHash", []int{2}},
|
OpHash: {"OpHash", []int{2}},
|
||||||
OpIndex: {"OpIndex", []int{}},
|
OpIndex: {"OpIndex", []int{}},
|
||||||
OpCall: {"OpCall", []int{1}},
|
OpCall: {"OpCall", []int{1}},
|
||||||
OpReturnValue: {"OpReturnValue", []int{}},
|
|
||||||
OpReturn: {"OpReturn", []int{}},
|
OpReturn: {"OpReturn", []int{}},
|
||||||
OpGetLocal: {"OpGetLocal", []int{1}},
|
OpGetLocal: {"OpGetLocal", []int{1}},
|
||||||
OpSetLocal: {"OpSetLocal", []int{1}},
|
OpSetLocal: {"OpSetLocal", []int{1}},
|
||||||
|
|||||||
@@ -157,6 +157,9 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *ast.IfExpression:
|
case *ast.IfExpression:
|
||||||
|
if c.lastInstructionIs(code.OpPop) {
|
||||||
|
c.removeLastPop()
|
||||||
|
}
|
||||||
err := c.Compile(node.Condition)
|
err := c.Compile(node.Condition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -314,7 +317,8 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
if c.lastInstructionIs(code.OpPop) {
|
if c.lastInstructionIs(code.OpPop) {
|
||||||
c.replaceLastPopWithReturn()
|
c.replaceLastPopWithReturn()
|
||||||
}
|
}
|
||||||
if !c.lastInstructionIs(code.OpReturnValue) {
|
if !c.lastInstructionIs(code.OpReturn) {
|
||||||
|
c.emit(code.OpNull)
|
||||||
c.emit(code.OpReturn)
|
c.emit(code.OpReturn)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +345,7 @@ func (c *Compiler) Compile(node ast.Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.emit(code.OpReturnValue)
|
c.emit(code.OpReturn)
|
||||||
|
|
||||||
case *ast.CallExpression:
|
case *ast.CallExpression:
|
||||||
err := c.Compile(node.Function)
|
err := c.Compile(node.Function)
|
||||||
@@ -481,9 +485,9 @@ func (c *Compiler) leaveScope() code.Instructions {
|
|||||||
|
|
||||||
func (c *Compiler) replaceLastPopWithReturn() {
|
func (c *Compiler) replaceLastPopWithReturn() {
|
||||||
lastPos := c.scopes[c.scopeIndex].lastInstruction.Position
|
lastPos := c.scopes[c.scopeIndex].lastInstruction.Position
|
||||||
c.replaceInstruction(lastPos, code.Make(code.OpReturnValue))
|
c.replaceInstruction(lastPos, code.Make(code.OpReturn))
|
||||||
|
|
||||||
c.scopes[c.scopeIndex].lastInstruction.Opcode = code.OpReturnValue
|
c.scopes[c.scopeIndex].lastInstruction.Opcode = code.OpReturn
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bytecode struct {
|
type Bytecode struct {
|
||||||
|
|||||||
@@ -243,6 +243,44 @@ func TestConditionals(t *testing.T) {
|
|||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: `
|
||||||
|
let x = 0; if (true) { x = 1; }; if (false) { x = 2; }
|
||||||
|
`,
|
||||||
|
expectedConstants: []interface{}{0, 1, 2},
|
||||||
|
expectedInstructions: []code.Instructions{
|
||||||
|
// 0000
|
||||||
|
code.Make(code.OpConstant, 0),
|
||||||
|
// 0003
|
||||||
|
code.Make(code.OpSetGlobal, 0),
|
||||||
|
// 0006
|
||||||
|
code.Make(code.OpTrue),
|
||||||
|
// 0007
|
||||||
|
code.Make(code.OpJumpNotTruthy, 19),
|
||||||
|
// 0010
|
||||||
|
code.Make(code.OpConstant, 1),
|
||||||
|
// 0013
|
||||||
|
code.Make(code.OpAssignGlobal, 0),
|
||||||
|
// 0016
|
||||||
|
code.Make(code.OpJump, 20),
|
||||||
|
// 0019
|
||||||
|
code.Make(code.OpNull),
|
||||||
|
// 0020
|
||||||
|
code.Make(code.OpFalse),
|
||||||
|
// 0021
|
||||||
|
code.Make(code.OpJumpNotTruthy, 33),
|
||||||
|
// 0024
|
||||||
|
code.Make(code.OpConstant, 2),
|
||||||
|
// 0027
|
||||||
|
code.Make(code.OpAssignGlobal, 0),
|
||||||
|
// 0030
|
||||||
|
code.Make(code.OpJump, 34),
|
||||||
|
// 0033
|
||||||
|
code.Make(code.OpNull),
|
||||||
|
// 0034
|
||||||
|
code.Make(code.OpPop),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
runCompilerTests(t, tests)
|
runCompilerTests(t, tests)
|
||||||
@@ -457,7 +495,7 @@ func TestFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -474,7 +512,7 @@ func TestFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -491,7 +529,7 @@ func TestFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -504,12 +542,13 @@ func TestFunctions(t *testing.T) {
|
|||||||
runCompilerTests(t, tests)
|
runCompilerTests(t, tests)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFunctionsWithoutReturnValue(t *testing.T) {
|
func TestFunctionsWithoutReturn(t *testing.T) {
|
||||||
tests := []compilerTestCase{
|
tests := []compilerTestCase{
|
||||||
{
|
{
|
||||||
input: `fn() { }`,
|
input: `fn() { }`,
|
||||||
expectedConstants: []interface{}{
|
expectedConstants: []interface{}{
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
|
code.Make(code.OpNull),
|
||||||
code.Make(code.OpReturn),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -537,12 +576,12 @@ func TestClosures(t *testing.T) {
|
|||||||
code.Make(code.OpGetFree, 0),
|
code.Make(code.OpGetFree, 0),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpClosure, 0, 1),
|
code.Make(code.OpClosure, 0, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -567,18 +606,18 @@ func TestClosures(t *testing.T) {
|
|||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetFree, 0),
|
code.Make(code.OpGetFree, 0),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpClosure, 0, 2),
|
code.Make(code.OpClosure, 0, 2),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpClosure, 1, 1),
|
code.Make(code.OpClosure, 1, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -619,7 +658,7 @@ func TestClosures(t *testing.T) {
|
|||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpConstant, 2),
|
code.Make(code.OpConstant, 2),
|
||||||
@@ -627,14 +666,14 @@ func TestClosures(t *testing.T) {
|
|||||||
code.Make(code.OpGetFree, 0),
|
code.Make(code.OpGetFree, 0),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpClosure, 4, 2),
|
code.Make(code.OpClosure, 4, 2),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpSetLocal, 0),
|
code.Make(code.OpSetLocal, 0),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpClosure, 5, 1),
|
code.Make(code.OpClosure, 5, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -703,7 +742,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
24,
|
24,
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpConstant, 0), // The literal "24"
|
code.Make(code.OpConstant, 0), // The literal "24"
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -721,7 +760,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
24,
|
24,
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpConstant, 0), // The literal "24"
|
code.Make(code.OpConstant, 0), // The literal "24"
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -740,7 +779,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
expectedConstants: []interface{}{
|
expectedConstants: []interface{}{
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
24,
|
24,
|
||||||
},
|
},
|
||||||
@@ -765,7 +804,7 @@ func TestFunctionCalls(t *testing.T) {
|
|||||||
code.Make(code.OpGetLocal, 1),
|
code.Make(code.OpGetLocal, 1),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpGetLocal, 2),
|
code.Make(code.OpGetLocal, 2),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
24,
|
24,
|
||||||
25,
|
25,
|
||||||
@@ -800,6 +839,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
|||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAssignGlobal, 0),
|
code.Make(code.OpAssignGlobal, 0),
|
||||||
|
code.Make(code.OpNull),
|
||||||
code.Make(code.OpReturn),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -822,6 +862,7 @@ func TestAssignmentStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpSetLocal, 0),
|
code.Make(code.OpSetLocal, 0),
|
||||||
code.Make(code.OpConstant, 1),
|
code.Make(code.OpConstant, 1),
|
||||||
code.Make(code.OpAssignLocal, 0),
|
code.Make(code.OpAssignLocal, 0),
|
||||||
|
code.Make(code.OpNull),
|
||||||
code.Make(code.OpReturn),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -846,7 +887,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
55,
|
55,
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetGlobal, 0),
|
code.Make(code.OpGetGlobal, 0),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -869,7 +910,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpSetLocal, 0),
|
code.Make(code.OpSetLocal, 0),
|
||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -896,7 +937,7 @@ func TestLetStatementScopes(t *testing.T) {
|
|||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpGetLocal, 1),
|
code.Make(code.OpGetLocal, 1),
|
||||||
code.Make(code.OpAdd),
|
code.Make(code.OpAdd),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -954,7 +995,7 @@ func TestBuiltins(t *testing.T) {
|
|||||||
code.Make(code.OpGetBuiltin, 0),
|
code.Make(code.OpGetBuiltin, 0),
|
||||||
code.Make(code.OpArray, 0),
|
code.Make(code.OpArray, 0),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
@@ -982,7 +1023,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpSub),
|
code.Make(code.OpSub),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
@@ -1011,7 +1052,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpSub),
|
code.Make(code.OpSub),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
@@ -1020,7 +1061,7 @@ func TestRecursiveFunctions(t *testing.T) {
|
|||||||
code.Make(code.OpGetLocal, 0),
|
code.Make(code.OpGetLocal, 0),
|
||||||
code.Make(code.OpConstant, 2),
|
code.Make(code.OpConstant, 2),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpReturnValue),
|
code.Make(code.OpReturn),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ var Builtins = []struct {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"len",
|
"len",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "len", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return newError("wrong number of arguments. got=%d, want=1",
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
len(args))
|
len(args))
|
||||||
@@ -34,7 +34,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"input",
|
"input",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "input", Fn: func(args ...Object) Object {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
obj, ok := args[0].(*String)
|
obj, ok := args[0].(*String)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -57,7 +57,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"print",
|
"print",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "print", Fn: func(args ...Object) Object {
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
fmt.Println(arg.Inspect())
|
fmt.Println(arg.Inspect())
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"first",
|
"first",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "first", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"last",
|
"last",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "last", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rest",
|
"rest",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "rest", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return newError("wrong number of arguments. got=%d, want=1",
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
len(args))
|
len(args))
|
||||||
@@ -131,7 +131,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"push",
|
"push",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "push", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return newError("wrong number of arguments. got=%d, want=2",
|
return newError("wrong number of arguments. got=%d, want=2",
|
||||||
len(args))
|
len(args))
|
||||||
@@ -158,7 +158,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pop",
|
"pop",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "pop", Fn: func(args ...Object) Object {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return newError("wrong number of arguments. got=%d, want=1",
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
len(args))
|
len(args))
|
||||||
@@ -184,7 +184,7 @@ var Builtins = []struct {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"exit",
|
"exit",
|
||||||
&Builtin{Fn: func(args ...Object) Object {
|
&Builtin{Name: "exit", Fn: func(args ...Object) Object {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
if args[0].Type() != INTEGER_OBJ {
|
if args[0].Type() != INTEGER_OBJ {
|
||||||
return newError("argument to `exit` must be INTEGER, got %s",
|
return newError("argument to `exit` must be INTEGER, got %s",
|
||||||
|
|||||||
@@ -151,14 +151,15 @@ func (s *String) Clone() Object {
|
|||||||
type BuiltinFunction func(args ...Object) Object
|
type BuiltinFunction func(args ...Object) Object
|
||||||
|
|
||||||
type Builtin struct {
|
type Builtin struct {
|
||||||
Fn BuiltinFunction
|
Name string
|
||||||
|
Fn BuiltinFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builtin) Type() ObjectType {
|
func (b Builtin) Type() ObjectType {
|
||||||
return BUILTIN_OBJ
|
return BUILTIN_OBJ
|
||||||
}
|
}
|
||||||
func (b Builtin) Inspect() string {
|
func (b Builtin) Inspect() string {
|
||||||
return "builtin function"
|
return fmt.Sprintf("<built-in function %s>", b.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Array struct {
|
type Array struct {
|
||||||
|
|||||||
11
vm/vm.go
11
vm/vm.go
@@ -247,7 +247,7 @@ func (vm *VM) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case code.OpReturnValue:
|
case code.OpReturn:
|
||||||
returnValue := vm.pop()
|
returnValue := vm.pop()
|
||||||
|
|
||||||
frame := vm.popFrame()
|
frame := vm.popFrame()
|
||||||
@@ -258,15 +258,6 @@ func (vm *VM) Run() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
case code.OpReturn:
|
|
||||||
frame := vm.popFrame()
|
|
||||||
vm.sp = frame.basePointer - 1
|
|
||||||
|
|
||||||
err := vm.push(Null)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
case code.OpSetLocal:
|
case code.OpSetLocal:
|
||||||
localIndex := code.ReadUint8(ins[ip+1:])
|
localIndex := code.ReadUint8(ins[ip+1:])
|
||||||
vm.currentFrame().ip += 1
|
vm.currentFrame().ip += 1
|
||||||
|
|||||||
@@ -252,7 +252,8 @@ func TestConditionals(t *testing.T) {
|
|||||||
{"if (1 > 2) { 10 } else { 20 }", 20},
|
{"if (1 > 2) { 10 } else { 20 }", 20},
|
||||||
{"if (1 > 2) { 10 }", Null},
|
{"if (1 > 2) { 10 }", Null},
|
||||||
{"if (false) { 10 }", Null},
|
{"if (false) { 10 }", Null},
|
||||||
{"if ((if (false) { 10 })) { 10 } else { 20 }", 20},
|
//{"if ((if (false) { 10 })) { 10 } else { 20 }", 20},
|
||||||
|
{"let x = 0; if (true) { x = 1; }; if (false) { x = 2; }; x", 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
runVmTests(t, tests)
|
runVmTests(t, tests)
|
||||||
|
|||||||
Reference in New Issue
Block a user