aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Execution/Stack.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Execution/Stack.php')
-rw-r--r--src/Execution/Stack.php166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/Execution/Stack.php b/src/Execution/Stack.php
index 1fa2dae..439726d 100644
--- a/src/Execution/Stack.php
+++ b/src/Execution/Stack.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Nsfisis\Waddiwasi\Execution;
+use Nsfisis\Waddiwasi\Structure\Types\RefType;
+
final class Stack
{
/**
@@ -19,11 +21,165 @@ final class Stack
$this->entries[] = $entry;
}
+ public function pushValue(Val $val): void
+ {
+ $this->push(StackEntry::Value($val));
+ }
+
+ public function pushBool(bool $value): void
+ {
+ $this->pushValue(Val::NumI32((int)$value));
+ }
+
+ /**
+ * @param S32 $value
+ */
+ public function pushI32(int $value): void
+ {
+ $this->pushValue(Val::NumI32($value));
+ }
+
+ /**
+ * @param S64 $value
+ */
+ public function pushI64(int $value): void
+ {
+ $this->pushValue(Val::NumI64($value));
+ }
+
+ /**
+ * @param F32 $value
+ */
+ public function pushF32(float $value): void
+ {
+ $this->pushValue(Val::NumF32($value));
+ }
+
+ /**
+ * @param F64 $value
+ */
+ public function pushF64(float $value): void
+ {
+ $this->pushValue(Val::NumF64($value));
+ }
+
+ public function pushRefNull(RefType $type): void
+ {
+ $this->pushValue(Val::RefNull($type));
+ }
+
+ public function pushRefFunc(FuncAddr $addr): void
+ {
+ $this->pushValue(Val::RefFunc($addr));
+ }
+
+ public function pushRefExtern(ExternAddr $addr): void
+ {
+ $this->pushValue(Val::RefExtern($addr));
+ }
+
public function pop(): ?StackEntry
{
return array_pop($this->entries);
}
+ public function popValue(): Val
+ {
+ $result = $this->pop();
+ assert($result instanceof StackEntries\Value);
+ return $result->inner;
+ }
+
+ /**
+ * @return list<Val>
+ */
+ public function popNValues(int $n): array
+ {
+ $results = [];
+ for ($i = 0; $i < $n; $i++) {
+ $results[] = $this->popValue();
+ }
+ return $results;
+ }
+
+ /**
+ * @return S32
+ */
+ public function popI32(): int
+ {
+ $v = $this->popValue();
+ assert($v instanceof Vals\Num);
+ assert($v->inner instanceof Nums\I32);
+ return $v->inner->value;
+ }
+
+ /**
+ * @return S64
+ */
+ public function popI64(): int
+ {
+ $v = $this->popValue();
+ assert($v instanceof Vals\Num);
+ assert($v->inner instanceof Nums\I64);
+ return $v->inner->value;
+ }
+
+ /**
+ * @return F32
+ */
+ public function popF32(): float
+ {
+ $v = $this->popValue();
+ assert($v instanceof Vals\Num);
+ assert($v->inner instanceof Nums\F32_);
+ return $v->inner->value;
+ }
+
+ /**
+ * @return F64
+ */
+ public function popF64(): float
+ {
+ $v = $this->popValue();
+ assert($v instanceof Vals\Num);
+ assert($v->inner instanceof Nums\F64_);
+ return $v->inner->value;
+ }
+
+ public function popRef(): Ref
+ {
+ $v = $this->popValue();
+ assert($v instanceof Vals\Ref);
+ return $v->inner;
+ }
+
+ /**
+ * @return list<Val>
+ */
+ public function popValuesToLabel(): array
+ {
+ $results = [];
+ while (!$this->isEmpty()) {
+ $top = $this->pop();
+ if ($top instanceof StackEntries\Value) {
+ $results[] = $top->inner;
+ } else {
+ assert($top instanceof StackEntries\Label);
+ break;
+ }
+ }
+ return $results;
+ }
+
+ public function popEntriesToCurrentFrame(): void
+ {
+ while (!$this->isEmpty()) {
+ if ($this->pop() instanceof StackEntries\Frame) {
+ return;
+ }
+ }
+ }
+
public function top(): ?StackEntry
{
$n = array_key_last($this->entries);
@@ -39,4 +195,14 @@ final class Stack
{
return $this->count() === 0;
}
+
+ public function currentFrame(): StackEntries\Frame
+ {
+ for ($i = count($this->entries) - 1; 0 <= $i; $i--) {
+ if ($this->entries[$i] instanceof StackEntries\Frame) {
+ return $this->entries[$i];
+ }
+ }
+ throw new \RuntimeException('No frame found');
+ }
}