From c9d96236dd51b4e80717e9eabe2fd6695b01949a Mon Sep 17 00:00:00 2001 From: Chuck Smith Date: Sun, 24 Mar 2024 11:47:31 -0400 Subject: [PATCH] Added overloaded support for array * int --- evaluator/evaluator.go | 19 +++++++++++++++++++ evaluator/evaluator_test.go | 19 +++++++++++++++++++ vm/vm.go | 19 +++++++++++++++++++ vm/vm_test.go | 11 +++++++++++ 4 files changed, 68 insertions(+) diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 62597b4..a350f19 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -306,6 +306,25 @@ func evalIntegerPrefixOperatorExpression(operator string, right object.Object) o func evalInfixExpression(operator string, left, right object.Object) object.Object { switch { + // [1] * 3 + case left.Type() == object.ARRAY_OBJ && right.Type() == object.INTEGER_OBJ: + leftVal := left.(*object.Array).Elements + rightVal := int(right.(*object.Integer).Value) + elements := leftVal + for i := rightVal; i > 1; i-- { + elements = append(elements, leftVal...) + } + return &object.Array{Elements: elements} + // 3 * [1] + case left.Type() == object.INTEGER_OBJ && right.Type() == object.ARRAY_OBJ: + leftVal := int(left.(*object.Integer).Value) + rightVal := right.(*object.Array).Elements + elements := rightVal + for i := leftVal; i > 1; i-- { + elements = append(elements, rightVal...) + } + return &object.Array{Elements: elements} + // " " * 4 case left.Type() == object.STRING_OBJ && right.Type() == object.INTEGER_OBJ: leftVal := left.(*object.String).Value diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index 6cac41c..0cccf77 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -481,6 +481,25 @@ func TestArrayLiterals(t *testing.T) { testIntegerObject(t, result.Elements[2], 6) } +func TestArrayDuplication(t *testing.T) { + input := "[1] * 3" + + evaluated := testEval(input) + result, ok := evaluated.(*object.Array) + if !ok { + t.Fatalf("object is not Array. got=%T (%+v)", evaluated, evaluated) + } + + if len(result.Elements) != 3 { + t.Fatalf("array has wrong num of elements. got=%d", + len(result.Elements)) + } + + testIntegerObject(t, result.Elements[0], 1) + testIntegerObject(t, result.Elements[1], 1) + testIntegerObject(t, result.Elements[2], 1) +} + func TestArrayIndexExpressions(t *testing.T) { tests := []struct { input string diff --git a/vm/vm.go b/vm/vm.go index baed531..4226e5f 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -527,6 +527,25 @@ func (vm *VM) executeBinaryOperation(op code.Opcode) error { switch { + // [1] * 3 + case left.Type() == object.ARRAY_OBJ && right.Type() == object.INTEGER_OBJ: + leftVal := left.(*object.Array).Elements + rightVal := int(right.(*object.Integer).Value) + elements := leftVal + for i := rightVal; i > 1; i-- { + elements = append(elements, leftVal...) + } + return vm.push(&object.Array{Elements: elements}) + // 3 * [1] + case left.Type() == object.INTEGER_OBJ && right.Type() == object.ARRAY_OBJ: + leftVal := int(left.(*object.Integer).Value) + rightVal := right.(*object.Array).Elements + elements := rightVal + for i := leftVal; i > 1; i-- { + elements = append(elements, rightVal...) + } + return vm.push(&object.Array{Elements: elements}) + // " " * 4 case left.Type() == object.STRING_OBJ && right.Type() == object.INTEGER_OBJ: leftVal := left.(*object.String).Value diff --git a/vm/vm_test.go b/vm/vm_test.go index c8533b9..82f1388 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -343,6 +343,17 @@ func TestArrayLiterals(t *testing.T) { runVmTests(t, tests) } +func TestArrayDuplication(t *testing.T) { + tests := []vmTestCase{ + {"[1] * 3", []int{1, 1, 1}}, + {"3 * [1]", []int{1, 1, 1}}, + {"[1, 2] * 2", []int{1, 2, 1, 2}}, + {"2 * [1, 2]", []int{1, 2, 1, 2}}, + } + + runVmTests(t, tests) +} + func TestHashLiterals(t *testing.T) { tests := []vmTestCase{ {