runningwater пре 3 година
родитељ
комит
35040e6326
6 измењених фајлова са 37 додато и 6 уклоњено
  1. 5 1
      code/code.go
  2. 5 4
      code/code_test.go
  3. 8 0
      compiler/compiler.go
  4. 1 0
      compiler/compiler_test.go
  5. 17 0
      vm/vm.go
  6. 1 1
      vm/vm_test.go

+ 5 - 1
code/code.go

@@ -49,6 +49,8 @@ func (ins Instructions) fmtInstructions(def *Definition, operands []int) string
 	}
 
 	switch operandCount {
+	case 0:
+		return def.Name
 	case 1:
 		return fmt.Sprintf("%s %d", def.Name, operands[0])
 	}
@@ -60,6 +62,7 @@ type Opcode byte
 
 const (
 	OpConstant Opcode = iota
+	OpAdd
 )
 
 // Definition For debugging and testing purposes
@@ -75,7 +78,8 @@ type Definition struct {
 }
 
 var definitions = map[Opcode]*Definition{
-	OpConstant: {Name: "OpConstant", OperandWidths: []int{2}},
+	OpConstant: {"OpConstant", []int{2}},
+	OpAdd:      {"OpAdd", []int{}}, // doesn't have any operands
 }
 
 func Lookup(op byte) (*Definition, error) {

+ 5 - 4
code/code_test.go

@@ -9,6 +9,7 @@ func TestMake(t *testing.T) {
 		expected []byte
 	}{
 		{OpConstant, []int{65534}, []byte{byte(OpConstant), 0xFF, 0xFE}},
+		{OpAdd, []int{}, []byte{byte(OpAdd)}},
 	}
 
 	for _, tt := range tests {
@@ -28,14 +29,14 @@ func TestMake(t *testing.T) {
 
 func TestInstructionsString(t *testing.T) {
 	instructions := []Instructions{
-		Make(OpConstant, 1),
+		Make(OpAdd),
 		Make(OpConstant, 2),
 		Make(OpConstant, 65535),
 	}
 
-	expected := `0000 OpConstant 1
-0003 OpConstant 2
-0006 OpConstant 65535
+	expected := `0000 OpAdd
+0001 OpConstant 2
+0004 OpConstant 65535
 `
 
 	concatted := Instructions{}

+ 8 - 0
compiler/compiler.go

@@ -6,6 +6,7 @@
 package compiler
 
 import (
+	"fmt"
 	"github/runnignwater/monkey/ast"
 	"github/runnignwater/monkey/code"
 	"github/runnignwater/monkey/object"
@@ -49,6 +50,13 @@ func (c *Compiler) Compile(node ast.Node) error {
 			return err
 		}
 
+		switch node.Operator {
+		case "+":
+			c.emit(code.OpAdd)
+		default:
+			return fmt.Errorf("unknown operator %s", node.Operator)
+		}
+
 	case *ast.IntegerLiteral:
 		integer := &object.Integer{Value: node.Value}
 		c.emit(code.OpConstant, c.addConstant(integer))

+ 1 - 0
compiler/compiler_test.go

@@ -24,6 +24,7 @@ func TestIntegerArithmetic(t *testing.T) {
 			expectedInstructions: []code.Instructions{
 				code.Make(code.OpConstant, 0),
 				code.Make(code.OpConstant, 1),
+				code.Make(code.OpAdd),
 			},
 		},
 	}

+ 17 - 0
vm/vm.go

@@ -53,6 +53,17 @@ func (vm *VM) Run() error {
 			if err != nil {
 				return err
 			}
+		case code.OpAdd:
+			right := vm.pop()
+			left := vm.pop()
+			leftValue := left.(*object.Integer).Value
+			rightValue := right.(*object.Integer).Value
+
+			result := leftValue + rightValue
+			err := vm.push(&object.Integer{Value: result})
+			if err != nil {
+				return err
+			}
 		}
 	}
 
@@ -69,3 +80,9 @@ func (vm *VM) push(o object.Object) error {
 
 	return nil
 }
+
+func (vm *VM) pop() object.Object {
+	o := vm.stack[vm.sp-1]
+	vm.sp--
+	return o
+}

+ 1 - 1
vm/vm_test.go

@@ -19,7 +19,7 @@ func TestIntegerArithmetic(t *testing.T) {
 	tests := []vmTestCase{
 		{"1", 1},
 		{"2", 2},
-		{"1 + 2", 2},
+		{"1 + 2", 3},
 	}
 
 	runVmTests(t, tests)