Added overloaded support for str * int
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"monkey/ast"
|
"monkey/ast"
|
||||||
"monkey/object"
|
"monkey/object"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -304,6 +305,18 @@ func evalIntegerPrefixOperatorExpression(operator string, right object.Object) o
|
|||||||
|
|
||||||
func evalInfixExpression(operator string, left, right object.Object) object.Object {
|
func evalInfixExpression(operator string, left, right object.Object) object.Object {
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
|
// " " * 4
|
||||||
|
case left.Type() == object.STRING_OBJ && right.Type() == object.INTEGER_OBJ:
|
||||||
|
leftVal := left.(*object.String).Value
|
||||||
|
rightVal := right.(*object.Integer).Value
|
||||||
|
return &object.String{Value: strings.Repeat(leftVal, int(rightVal))}
|
||||||
|
// 4 * " "
|
||||||
|
case left.Type() == object.INTEGER_OBJ && right.Type() == object.STRING_OBJ:
|
||||||
|
leftVal := left.(*object.Integer).Value
|
||||||
|
rightVal := right.(*object.String).Value
|
||||||
|
return &object.String{Value: strings.Repeat(rightVal, int(leftVal))}
|
||||||
|
|
||||||
case left.Type() == object.BOOLEAN_OBJ && right.Type() == object.BOOLEAN_OBJ:
|
case left.Type() == object.BOOLEAN_OBJ && right.Type() == object.BOOLEAN_OBJ:
|
||||||
return evalBooleanInfixExpression(operator, left, right)
|
return evalBooleanInfixExpression(operator, left, right)
|
||||||
case left.Type() == object.INTEGER_OBJ && right.Type() == object.INTEGER_OBJ:
|
case left.Type() == object.INTEGER_OBJ && right.Type() == object.INTEGER_OBJ:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEvalIntegerExpression(t *testing.T) {
|
func TestEvalExpressions(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input string
|
input string
|
||||||
expected interface{}
|
expected interface{}
|
||||||
@@ -36,6 +36,8 @@ func TestEvalIntegerExpression(t *testing.T) {
|
|||||||
{"1 | 2", 3},
|
{"1 | 2", 3},
|
||||||
{"2 ^ 4", 6},
|
{"2 ^ 4", 6},
|
||||||
{"3 & 6", 2},
|
{"3 & 6", 2},
|
||||||
|
{`" " * 4`, " "},
|
||||||
|
{`4 * " "`, " "},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
12
vm/vm.go
12
vm/vm.go
@@ -526,6 +526,18 @@ func (vm *VM) executeBinaryOperation(op code.Opcode) error {
|
|||||||
rightType := right.Type()
|
rightType := right.Type()
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
|
// " " * 4
|
||||||
|
case left.Type() == object.STRING_OBJ && right.Type() == object.INTEGER_OBJ:
|
||||||
|
leftVal := left.(*object.String).Value
|
||||||
|
rightVal := right.(*object.Integer).Value
|
||||||
|
return vm.push(&object.String{Value: strings.Repeat(leftVal, int(rightVal))})
|
||||||
|
// 4 * " "
|
||||||
|
case left.Type() == object.INTEGER_OBJ && right.Type() == object.STRING_OBJ:
|
||||||
|
leftVal := left.(*object.Integer).Value
|
||||||
|
rightVal := right.(*object.String).Value
|
||||||
|
return vm.push(&object.String{Value: strings.Repeat(rightVal, int(leftVal))})
|
||||||
|
|
||||||
case leftType == object.BOOLEAN_OBJ && rightType == object.BOOLEAN_OBJ:
|
case leftType == object.BOOLEAN_OBJ && rightType == object.BOOLEAN_OBJ:
|
||||||
return vm.executeBinaryBooleanOperation(op, left, right)
|
return vm.executeBinaryBooleanOperation(op, left, right)
|
||||||
case leftType == object.INTEGER_OBJ && rightType == object.INTEGER_OBJ:
|
case leftType == object.INTEGER_OBJ && rightType == object.INTEGER_OBJ:
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ func TestStringExpressions(t *testing.T) {
|
|||||||
{`"monkey"`, "monkey"},
|
{`"monkey"`, "monkey"},
|
||||||
{`"mon" + "key"`, "monkey"},
|
{`"mon" + "key"`, "monkey"},
|
||||||
{`"mon" + "key" + "banana"`, "monkeybanana"},
|
{`"mon" + "key" + "banana"`, "monkeybanana"},
|
||||||
|
{`" " * 4`, " "},
|
||||||
|
{`4 * " "`, " "},
|
||||||
}
|
}
|
||||||
|
|
||||||
runVmTests(t, tests)
|
runVmTests(t, tests)
|
||||||
|
|||||||
Reference in New Issue
Block a user