Skip to content

Commit

Permalink
Cap & len accepts pointer to array + more tests for builtin package
Browse files Browse the repository at this point in the history
  • Loading branch information
tuqqu committed Sep 13, 2024
1 parent 99f69c0 commit c5cab3a
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 11 deletions.
22 changes: 16 additions & 6 deletions src/Builtin/BuiltinFunc/Cap.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use GoPhp\Argv;
use GoPhp\Error\RuntimeError;
use GoPhp\GoType\ArrayType;
use GoPhp\GoValue\Array\ArrayValue;
use GoPhp\GoValue\Int\IntValue;
use GoPhp\GoValue\PointerValue;
use GoPhp\GoValue\Slice\SliceValue;

use function GoPhp\assert_argc;
Expand All @@ -25,17 +27,25 @@ public function __invoke(Argv $argv): IntValue
{
assert_argc($this, $argv, 1);

$v = $argv[0];
$v = $argv[0]->value;

if ($v->value instanceof ArrayValue) {
return new IntValue($v->value->len());
if ($v instanceof PointerValue && ($v->type()->pointsTo instanceof ArrayType)) {
if ($v->isNil()) {
return new IntValue(0);
}

$v = $v->deref();
}

if ($v instanceof ArrayValue) {
return new IntValue($v->len());
}

if ($v->value instanceof SliceValue) {
return new IntValue($v->value->cap());
if ($v instanceof SliceValue) {
return new IntValue($v->cap());
}

throw RuntimeError::wrongArgumentTypeForBuiltin($v->value, $this->name);
throw RuntimeError::wrongArgumentTypeForBuiltin($v, $this->name);
}

public function name(): string
Expand Down
10 changes: 10 additions & 0 deletions src/Builtin/BuiltinFunc/Len.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use GoPhp\Argv;
use GoPhp\Error\RuntimeError;
use GoPhp\GoType\ArrayType;
use GoPhp\GoValue\Int\IntValue;
use GoPhp\GoValue\PointerValue;
use GoPhp\GoValue\Sequence;

use function GoPhp\assert_argc;
Expand All @@ -26,6 +28,14 @@ public function __invoke(Argv $argv): IntValue

$v = $argv[0]->value;

if ($v instanceof PointerValue && ($v->type()->pointsTo instanceof ArrayType)) {
if ($v->isNil()) {
return new IntValue(0);
}

$v = $v->deref();
}

if (!$v instanceof Sequence) {
throw RuntimeError::wrongArgumentTypeForBuiltin($v, $this->name);
}
Expand Down
4 changes: 2 additions & 2 deletions src/GoValue/Func/Func.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,13 @@ private function doBind(Environment $env): void
}

$boundInstance = $this->boundInstance instanceof PointerValue
? $this->boundInstance->getPointsTo()
? $this->boundInstance->deref()
: $this->boundInstance;

$receiverType = $this->receiver->type;

if ($boundInstance instanceof PointerValue) {
$boundInstance = $boundInstance->getPointsTo();
$boundInstance = $boundInstance->deref();
}

if ($receiverType instanceof PointerType) {
Expand Down
4 changes: 4 additions & 0 deletions src/GoValue/Map/KeyValueTupleMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public function len(): int
public function delete(Hashable&GoValue $at): void
{
unset($this->values[$at->hash()]);

if ($this->len > 0) {
--$this->len;
}
}

public function iter(): iterable
Expand Down
4 changes: 2 additions & 2 deletions src/GoValue/PointerValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function isNil(): bool
return $this->pointsTo === NIL;
}

public function getPointsTo(): AddressableValue
public function deref(): AddressableValue
{
if ($this->isNil()) {
throw PanicError::nilDereference();
Expand All @@ -59,7 +59,7 @@ public function unwrap(): string
public function operate(Operator $op): AddressableValue
{
return match ($op) {
Operator::Mul => $this->getPointsTo(),
Operator::Mul => $this->deref(),
Operator::BitAnd => PointerValue::fromValue($this),
default => throw RuntimeError::undefinedOperator($op, $this),
};
Expand Down
2 changes: 1 addition & 1 deletion src/Interpreter.php
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,7 @@ private function evalSelectorExpr(SelectorExpr $expr): GoValue
$value = try_unwind($value);

if ($value instanceof PointerValue) {
$value = $value->getPointsTo();
$value = $value->deref();
$check = true;
}
} while ($check);
Expand Down
145 changes: 145 additions & 0 deletions tests/Functional/files/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ package main
func main() {
test_copy()
test_append()
test_delete()
test_new()
test_len()
test_cap()
test_make()
test_complex_real_imag()
test_print_println()
}

func test_copy() {
Expand Down Expand Up @@ -53,3 +60,141 @@ func test_append() {
s3 = append(s3, "str"...)
println(len(s3), cap(s3), s3[0], s3[1], s3[2], s3[3], s3[4], s3[5], s3[6], s3[7])
}

func test_delete() {
println("test_delete")

// 1
var s1 map[int]string = map[int]string{0: "A", 1: "B", 2: "C", 3: "D"}
delete(s1, 2)
println(len(s1), s1[0], s1[1], s1[2], s1[3])

// 2
var s2 map[string]int = map[string]int{"A": 0, "B": 1, "C": 2, "D": 3}
delete(s2, "B")
delete(s2, "C")
println(len(s2), s2["A"], s2["B"], s2["C"], s2["D"])
}

func test_new() {
println("test_new")

// 1
var p1 *int = new(int)
*p1 = 5
println(*p1)

// 2
var p2 *string = new(string)
*p2 = "Hello"
println(*p2)

// 3
var p3 *[]int = new([]int)
*p3 = []int{0, 1, 2}
println((*p3)[0], (*p3)[1], (*p3)[2])
}

func test_len() {
println("test_len")

// 1
var s1 []int = []int{0, 1, 2, 3}
println(len(s1))

// 2
var s2 map[int]string = map[int]string{0: "A", 1: "B", 2: "C", 3: "D"}
println(len(s2))

// 3
var s3 string = "Hello, world!"
println(len(s3))

// 4
var s4 [5]int = [5]int{0, 1, 2, 3, 4}
println(len(s4))

// 5
var s5 *[5]int = new([5]int)
println(len(s5))

// 6
var s6 *[5]int = nil
println(len(s6))
}

func test_cap() {
println("test_cap")

// 1
var s1 []int = make([]int, 3, 5)
println(cap(s1))

// 2
var s2 []int = nil
println(cap(s2))

// 3
var s3 *[5]int = new([5]int)
println(cap(s3))

// 4
var s4 *[5]int = nil
println(cap(s4))

// 4
var s5 [5]int = [5]int{0, 1, 2, 3, 4}
println(cap(s5))
}

func test_complex_real_imag() {
println("test_complex")

// 1
var c1 complex64 = 5 + 6i
println(c1, real(c1), imag(c1))

// 2
var c2 complex128 = 7 + 8i
println(real(c2), imag(c2))

// 3
var c3 complex64 = complex(9, 10)
println(real(c3), imag(c3))

// 4
var c4 complex128 = complex(11, 12)
println(real(c4), imag(c4))
}

func test_make() {
println("test_make")

// 1
var s1 []int = make([]int, 3)
println(len(s1), cap(s1))

// 2
var s2 []string = make([]string, 3, 5)
println(len(s2), cap(s2))

// 3
var s3 map[int]string = make(map[int]string)
println(len(s3))

// 4
var s4 map[string]int = make(map[string]int, 3)
println(len(s4))
}

func test_print_println() {
println("test_print")

print("Hello, ")
print("world!")
print("hello", "world", 1, 2, 3)

println("Hello,-")
println("world!")
println("hello", "world", 1, 2, 3)
}
34 changes: 34 additions & 0 deletions tests/Functional/output/builtin.out
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,37 @@ test_append
5 8 97 98 99 45
6 8 97 98 99 45 9
9 16 97 98 99 45 9 100 115 116
test_delete
3 A B D
2 0 0 0 3
test_new
5
Hello
0 1 2
test_len
4
4
13
5
5
0
test_cap
5
0
5
0
5
test_make
3 3
3 5
0
0
test_complex
(+5.000000+6.000000) 5.000000 6.000000
7.000000 8.000000
9.000000 10.000000
11.000000 12.000000
test_print
Hello, world!helloworld123Hello,-
world!
hello world 1 2 3

0 comments on commit c5cab3a

Please sign in to comment.