Skip to content

Commit

Permalink
Fix printing methods
Browse files Browse the repository at this point in the history
  • Loading branch information
m3m0r7 committed Jan 2, 2024
1 parent 3f3566e commit c1a1e6f
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Comparable;

use RubyVM\VM\Core\Runtime\Attribute\BindAliasAs;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Enumerable\Array_;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\FalseClass;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\TrueClass;
use RubyVM\VM\Core\Runtime\BasicObject\Symbolizable;
Expand Down Expand Up @@ -32,6 +33,17 @@ public static function createBy(mixed $value = ''): self
return new self(new StringSymbol($value));
}

public function chars(): Array_
{
$array = [];
$string = (string) $this->symbol;
for ($i = 0; $i < strlen($string); ++$i) {
$array[] = String_::createBy($string[$i]);
}

return Array_::createBy($array);
}

#[BindAliasAs('+')]
public function plus(RubyClassInterface $object): String_
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public function count(): int

public function inspect(): RubyClassInterface
{
$keys = array_keys($this->hash);
$values = array_values($this->hash);

uksort($keys, static fn (int $a, $b) => $b <=> $a);
uksort($values, static fn (int $a, $b) => $b <=> $a);

return String_::createBy(sprintf(
'{%s}',
implode(
Expand All @@ -66,8 +72,8 @@ public function inspect(): RubyClassInterface
$key,
$value->inspect(),
),
array_keys($this->hash),
array_values($this->hash),
$keys,
$values,
)
),
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function process(): ProcessedStatus
} else {
$this->context->vmStack()->push(
new Operand(
Array_::createBy([$array->valueOf()]),
Array_::createBy([$array]),
),
);
}
Expand Down
60 changes: 49 additions & 11 deletions src/VM/Core/Runtime/Provider/ProvideBasicClassMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Comparable\Integer_;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Comparable\String_;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Enumerable\Enumerable;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Enumerable\Hash;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Exception;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\NilClass;
use RubyVM\VM\Core\Runtime\BasicObject\Kernel\Object_\Proc;
Expand All @@ -29,14 +30,58 @@ public function p(RubyClassInterface $object): RubyClassInterface
}

public function puts(RubyClassInterface $object): RubyClassInterface
{
$string = $this->_print($object);

$this
->context()
->IOContext()
->stdOut
->write(
$string . (str_ends_with((string) $string, "\n") ? '' : "\n"),
);

// The puts returns (nil)
return NilClass::createBy();
}

public function print(RubyClassInterface $object): RubyClassInterface
{
$output = '';

if ($object instanceof Enumerable) {
$output = (string) $object->inspect();
} elseif ($object instanceof NilClass) {
$output = '';
} else {
$output = (string) $object;
}

$this
->context()
->IOContext()
->stdOut
->write(
$output,
);

// The puts returns (nil)
return NilClass::createBy();
}

private function _print(RubyClassInterface $object): string
{
$string = '';

if ($object instanceof Exception) {
$string .= (string) $object;
$string = (string) $object;
} elseif ($object instanceof Enumerable) {
foreach ($object as $number) {
$string .= "{$number}\n";
if ($object instanceof Hash) {
$string = (string) $object->inspect();
} else {
foreach ($object as $number) {
$string .= "{$number}\n";
}
}
} elseif ($object instanceof NilClass) {
// When an argument is a nil symbol, then displays a break only
Expand All @@ -47,14 +92,7 @@ public function puts(RubyClassInterface $object): RubyClassInterface
$string = (string) $object->setRuntimeContext($this->context())->inspect();
}

if (!str_ends_with($string, "\n")) {
$string .= "\n";
}

$this->context()->IOContext()->stdOut->write($string);

// The puts returns (nil)
return NilClass::createBy();
return $string;
}

public function exit(RubyClassInterface $code = null): never
Expand Down
2 changes: 1 addition & 1 deletion src/VM/Core/YARV/Essential/Symbol/ArraySymbol.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __toString(): string
return sprintf(
'[%s]',
implode(', ', array_map(
static fn ($value) => (string) $value,
static fn ($value) => (string) $value->inspect(),
$this->array,
))
);
Expand Down
4 changes: 3 additions & 1 deletion tests/Version/RubyVM/Call/Method/PTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function testSimpleP(): void
$rubyVMManager = $this->createRubyVMFromCode(
<<< '_'
p "Hello World!"
p "Hello World!".chars
p [1, 2, 3, 4, 5, 6]
p true
p false
Expand All @@ -34,11 +35,12 @@ public function testSimpleP(): void
$this->assertSame(ExecutedStatus::SUCCESS, $executor->execute()->executedStatus);
$this->assertSame(<<<'_'
"Hello World!"
["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"]
[1, 2, 3, 4, 5, 6]
true
false
nil
{:key2=>"World!", :key1=>"Hello!"}
{:key1=>"Hello!", :key2=>"World!"}

_, $rubyVMManager->stdOut->readAll());
}
Expand Down
52 changes: 52 additions & 0 deletions tests/Version/RubyVM/Call/Method/PrintTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Tests\RubyVM\Version\RubyVM\Call\Method;

use RubyVM\VM\Core\Runtime\Executor\ExecutedStatus;
use Tests\RubyVM\Helper\TestApplication;

/**
* @internal
*
* @coversNothing
*/
class PrintTest extends TestApplication
{
public function testPrint(): void
{
$rubyVMManager = $this->createRubyVMFromCode(
<<< '_'
print "Hello World!"
print "\n"
print "Hello World!".chars
print "\n"
print [1, 2, 3, 4, 5, 6]
print "\n"
print true
print "\n"
print false
print "\n"
print nil
print "\n"
print({ key1: "Hello!", key2: "World!"})
_,
);

$executor = $rubyVMManager
->rubyVM
->disassemble();

$this->assertSame(ExecutedStatus::SUCCESS, $executor->execute()->executedStatus);
$this->assertSame(<<<'_'
Hello World!
["H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"]
[1, 2, 3, 4, 5, 6]
true
false
{:key1=>"Hello!", :key2=>"World!"}
_, $rubyVMManager->stdOut->readAll());
}
}
65 changes: 65 additions & 0 deletions tests/Version/RubyVM/Call/Method/PutsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace Tests\RubyVM\Version\RubyVM\Call\Method;

use RubyVM\VM\Core\Runtime\Executor\ExecutedStatus;
use Tests\RubyVM\Helper\TestApplication;

/**
* @internal
*
* @coversNothing
*/
class PutsTest extends TestApplication
{
public function testPuts(): void
{
$rubyVMManager = $this->createRubyVMFromCode(
<<< '_'
puts "Hello World!"
puts "Hello World!".chars
puts [1, 2, 3, 4, 5, 6]
puts true
puts false
puts nil
puts({ key1: "Hello!", key2: "World!"})
_,
);

$executor = $rubyVMManager
->rubyVM
->disassemble();

// NOTE: The IDE will be deleted one space, here is hack add one space.
$space = ' ';
$this->assertSame(ExecutedStatus::SUCCESS, $executor->execute()->executedStatus);
$this->assertSame(<<<_
Hello World!
H
e
l
l
o
{$space}
W
o
r
l
d
!
1
2
3
4
5
6
true
false
{:key1=>"Hello!", :key2=>"World!"}
_, $rubyVMManager->stdOut->readAll());
}
}

0 comments on commit c1a1e6f

Please sign in to comment.