From bcde079af59a638579288be3cfdc7b55290e74f2 Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 22 Nov 2022 20:38:10 +0100 Subject: [PATCH] Fix and/or conditions (they should return the value in the expression, not true/false) --- src/Interpreter/LuarExpressionVisitor.php | 27 ++++++++----------- src/Library/LibString.php | 32 +++++++++++++++++++++++ tests/unit/LuaSuiteTest.php | 1 + 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/Interpreter/LuarExpressionVisitor.php b/src/Interpreter/LuarExpressionVisitor.php index 2e940f6..840bfc8 100644 --- a/src/Interpreter/LuarExpressionVisitor.php +++ b/src/Interpreter/LuarExpressionVisitor.php @@ -1,7 +1,6 @@ fieldlist() ? $this->visitFieldlist($context->fieldlist()) : []; - return Table::fromArray($fieldList); + return new Table(null, $fieldList); } + /** + * @return LuarObject[] + */ public function visitFieldlist(Context\FieldlistContext $context): array { $fieldContexts = $context->field(); if (!$fieldContexts) { @@ -111,13 +113,13 @@ public function visitFieldlist(Context\FieldlistContext $context): array { } if ($key === null && $object instanceof ObjectList) { - $objects = $object->getObjects(); - foreach ($objects as $object) { - $fields[$n++] = $object->getValue(); + $count = $object->count(); + for ($i=0; $i<$count; $i++) { + $fields[$n++] = $object->getObject($i); } } else { $key = $key ?? $n++; - $fields[$key] = $object->getValue(); + $fields[$key] = $object; } } return $fields; @@ -182,7 +184,6 @@ public function visitExpComparison(Context\ExpComparisonContext $context): LuarO throw new LuarRuntimeException("attempt to compare {$o1->getType()} with {$o2->getType()}", $context); } - switch ($op) { case '<': return new Literal(($v1 <=> $v2) === -1); case '>': return new Literal(($v1 <=> $v2) === 1); @@ -250,22 +251,16 @@ public function visitExpPower(Context\ExpPowerContext $context): LuarObject { public function visitExpOr(Context\ExpOrContext $context): LuarObject { $o1 = $this->visitExp($context->exp(0)); - $o2 = $this->visitExp($context->exp(1)); - if ($this->isTrue($o1->getValue())) return $o1; - if ($this->isTrue($o2->getValue())) return $o2; - return new Literal(null); + return $this->visitExp($context->exp(1)); } public function visitExpAnd(Context\ExpAndContext $context): LuarObject { $o1 = $this->visitExp($context->exp(0)); - $o2 = $this->visitExp($context->exp(1)); - - if (!$this->isTrue($o1->getValue())) return new Literal(null); - if (!$this->isTrue($o2->getValue())) return new Literal(null); + if (!$this->isTrue($o1->getValue())) return $o1; - return $o2; + return $this->visitExp($context->exp(1)); } public function visitExpConcat(Context\ExpConcatContext $context): LuarObject { diff --git a/src/Library/LibString.php b/src/Library/LibString.php index e2d2615..acf28f1 100644 --- a/src/Library/LibString.php +++ b/src/Library/LibString.php @@ -297,4 +297,36 @@ private function gsub(): Invokable { return new ObjectList([ new Literal($return) ]); }); } + + private function gmatch(): Invokable { + return new Invokable(function (ObjectList $ol) { + $subject = (string) $this->validateTypeN($ol, ['string'], 0)->getValue(); + $pattern = (string) $this->validateTypeN($ol, ['string'], 1)->getValue(); + + $regex = $this->patternHelper->patternToRegex($pattern); + preg_match_all($regex, $subject, $matches); + + $countMatches = count($matches); + $results = []; + foreach ($matches[0] as $i => $match) { + $result = []; + + for ($group=1; $group<$countMatches; $group++) { + $result[] = new Literal($matches[$group][$i]); + } + + if ($result === []) { // No groups -> return full match + $result[] = new Literal($match); + } + + $results[] = new ObjectList($result); + } + + return Invokable::fromPhpCallable(function () use (&$results) { + $current = current($results); + next($results); + return $current ?: new ObjectList([]); + }); + }); + } } diff --git a/tests/unit/LuaSuiteTest.php b/tests/unit/LuaSuiteTest.php index b7bff1c..d822463 100644 --- a/tests/unit/LuaSuiteTest.php +++ b/tests/unit/LuaSuiteTest.php @@ -13,6 +13,7 @@ */ class LuaSuiteTest extends TestCase { private function testLua(string $program): void { + ini_set('xdebug.max_nesting_level', -1); $successReturn = "Luar OK!"; $program .= "\nreturn '$successReturn'";