Skip to content

Commit

Permalink
Merge pull request #15 from smuuf/logicexpr
Browse files Browse the repository at this point in the history
Logic expressions and other stuff
  • Loading branch information
smuuf authored Oct 21, 2018
2 parents 009cf91 + f1e2e66 commit 959e548
Show file tree
Hide file tree
Showing 51 changed files with 1,524 additions and 880 deletions.
2 changes: 1 addition & 1 deletion src/StrictObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Smuuf\Primi;

class StrictObject {
abstract class StrictObject {

/**
* Used when trying to access undeclared or inaccessible property.
Expand Down
8 changes: 4 additions & 4 deletions src/exceptions/InternalArgumentCountException.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public function __construct(int $passed = null, int $expected = null) {

}

public function getPassedCount() {
$this->passedCount;
public function getPassedCount(): int {
return $this->passedCount;
}

public function getExpectedCount() {
$this->expectedCount;
public function getExpectedCount(): int {
return $this->expectedCount;
}

}
2 changes: 1 addition & 1 deletion src/exceptions/InternalBinaryOperationxception.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use \Smuuf\Primi\Structures\Value;

class InternalBinaryOperationxception extends InternalException {
class InternalBinaryOperationException extends InternalException {

protected $op;
protected $left;
Expand Down
7 changes: 7 additions & 0 deletions src/exceptions/InternalUndefinedTruthnessException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Smuuf\Primi;

class InternalUndefinedTruthnessException extends InternalException {

}
4 changes: 2 additions & 2 deletions src/extensions/psl/ArrayExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ public static function array_shuffle(ArrayValue $arr): ArrayValue {

// Do NOT modify the original array argument (as PHP would do).
$copy = clone $arr;
shuffle($arr->value);
shuffle($copy->value);

return $arr;
return $copy;

}

Expand Down
7 changes: 1 addition & 6 deletions src/extensions/psl/CastingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,7 @@ public static function to_bool(Value $value): BoolValue {
BoolValue::class
);

// Only empty string is considered falsey ("" -> false, "0" -> true).
if ($value instanceof StringValue) {
return new BoolValue($value->value !== "");
}

return new BoolValue((bool) $value->value);
return new BoolValue(Common::isTruthy($value));

}

Expand Down
10 changes: 5 additions & 5 deletions src/handlers/Addition.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\InternalBinaryOperationxception;
use \Smuuf\Primi\InternalBinaryOperationException;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Context;

use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\Helpers\BinaryOpHandler;
use \Smuuf\Primi\Helpers\BinaryLTR;

/**
* Node fields:
Expand All @@ -21,9 +21,9 @@ public static function handle(array $node, Context $context) {

try {

return BinaryOpHandler::handle($node, $context);
return BinaryLTR::handle($node, $context);

} catch (InternalBinaryOperationxception $e) {
} catch (InternalBinaryOperationException $e) {

throw new ErrorException(sprintf(
"Cannot use operator '%s' with '%s' and '%s'",
Expand All @@ -40,7 +40,7 @@ public static function reduce(array $node) {

// No need to represent this kind of node as Addition when there's only one operand.
// Take the only operand here and subtitute the Addition node with it.
if (isset($node['operands']['name'])) {
if (!isset($node['ops'])) {
return $node['operands'];
}

Expand Down
2 changes: 1 addition & 1 deletion src/handlers/ChainedFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static function chain(
) {

// 1) We'll extract the function name directly from the "fn" child node.
$name = $node['fn']['text'];
$name = $node['fn']['core']['text'];

// 2) We'll try to find type-matching function first.
// That is: A function which name is prepended by the subject's type
Expand Down
37 changes: 18 additions & 19 deletions src/handlers/Comparison.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Structures\Value;
use \Smuuf\Primi\Helpers\ComparisonLTR;
use \Smuuf\Primi\InternalBinaryOperationException;
use \Smuuf\Primi\ISupportsComparison;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\HandlerFactory;
Expand All @@ -13,37 +15,34 @@
* left: A "+" or "-" sign signalling the 'side' of the first operand.
* right: List of operand nodes.
*/
class Comparison extends \Smuuf\Primi\StrictObject implements IHandler {
class Comparison extends \Smuuf\Primi\StrictObject implements IHandler, IReducer {

public static function handle(array $node, Context $context) {

// Execute the left-hand node and get its return value.
$leftHandler = HandlerFactory::get($node['left']['name']);
$leftReturn = $leftHandler::handle($node['left'], $context);

$rightHandler = HandlerFactory::get($node['right']['name']);
$rightReturn = $rightHandler::handle($node['right'], $context);

$op = $node['op']['text'];

try {

if ($leftReturn instanceof ISupportsComparison && $rightReturn instanceof Value) {
return $leftReturn->doComparison($op, $rightReturn);
} else {
throw new \TypeError;
}
return ComparisonLTR::handle($node, $context);

} catch (\TypeError $e) {
} catch (InternalBinaryOperationException $e) {

throw new ErrorException(sprintf(
"Cannot compare '%s' and '%s'",
$leftReturn::TYPE,
$rightReturn::TYPE
"Cannot compare '%s' with '%s'",
($e->getLeft())::TYPE,
($e->getRight())::TYPE
), $node);

}

}

public static function reduce(array $node) {

// If there is no operator, that means there's only one operand.
// In that case, return only the operand node inside.
if (!isset($node['ops'])) {
return $node['operands'];
}

}

}
3 changes: 2 additions & 1 deletion src/handlers/IfStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Context;

Expand All @@ -20,7 +21,7 @@ public static function handle(array $node, Context $context) {

// If the result of the left hand equals to truthy value,
// execute the code branch stored in the right-hand node.
if ($return->getInternalValue()) {
if (Common::isTruthy($return)) {
$rightHandler = HandlerFactory::get($node['right']['name']);
$rightHandler::handle($node['right'], $context);
}
Expand Down
30 changes: 30 additions & 0 deletions src/handlers/LogicalAnd.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\InternalUndefinedTruthnessException;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\Context;
use \Smuuf\Primi\Helpers\LogicalLTR;

class LogicalAnd extends \Smuuf\Primi\StrictObject implements IHandler, IReducer {

public static function handle(array $node, Context $context) {

try {
return LogicalLTR::handle($node, $context);
} catch (InternalUndefinedTruthnessException $e) {
throw new ErrorException($e->getMessage(), $node);
}

}

public static function reduce(array $node) {

if (!isset($node['ops'])) {
return $node['operands'];
}

}

}
30 changes: 30 additions & 0 deletions src/handlers/LogicalOr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\InternalUndefinedTruthnessException;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\Context;
use \Smuuf\Primi\Helpers\LogicalLTR;

class LogicalOr extends \Smuuf\Primi\StrictObject implements IHandler, IReducer {

public static function handle(array $node, Context $context) {

try {
return LogicalLTR::handle($node, $context);
} catch (InternalUndefinedTruthnessException $e) {
throw new ErrorException($e->getMessage(), $node);
}

}

public static function reduce(array $node) {

if (!isset($node['ops'])) {
return $node['operands'];
}

}

}
10 changes: 5 additions & 5 deletions src/handlers/Multiplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\InternalBinaryOperationxception;
use \Smuuf\Primi\InternalBinaryOperationException;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Context;

use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\Helpers\BinaryOpHandler;
use \Smuuf\Primi\Helpers\BinaryLTR;

/**
* Node fields:
Expand All @@ -21,9 +21,9 @@ public static function handle(array $node, Context $context) {

try {

return BinaryOpHandler::handle($node, $context);
return BinaryLTR::handle($node, $context);

} catch (InternalBinaryOperationxception $e) {
} catch (InternalBinaryOperationException $e) {

throw new ErrorException(sprintf(
"Cannot use operator '%s' with '%s' and '%s'",
Expand All @@ -40,7 +40,7 @@ public static function reduce(array $node) {

// No need to represent this kind of node as Multiplication when there's only one operand.
// Take the only operand here and subtitute the Multiplication node with it.
if (isset($node['operands']['name'])) {
if (!isset($node['ops'])) {
return $node['operands'];
}

Expand Down
28 changes: 12 additions & 16 deletions src/handlers/Negation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\Structures\BoolValue;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Context;
Expand All @@ -10,35 +11,30 @@ class Negation extends \Smuuf\Primi\StrictObject implements IHandler, IReducer {

public static function handle(array $node, Context $context) {

$negation = isset($node['not']);

$handler = HandlerFactory::get($node['core']['name']);
$value = $handler::handle($node['core'], $context);

// Should we even handle negation?
if ($negation) {

// If so, let's determine truthness using PHP's own rules (at least
// for now).
$truthness = (bool) $value->getInternalValue();
$value = new BoolValue(!$truthness);
// The final truthness is (at least for now) based on PHP's own rules.
$truthness = Common::isTruthy($value);

}
// Should we even handle negation? If there's an even number of negation
// operators, the result would always have the same truthness as its
// input.
Common::ensureIndexed($node['nots']);
$isNegation = count($node['nots'] ?? []) % 2;

return $value;
return new BoolValue($isNegation ? !$truthness : $truthness);

}

public static function reduce(array $node) {

// If this truly has a negation, do not reduce this node.
if (isset($node['not'])) {
return;
// If not, return only core.
if (!isset($node['nots'])) {
return $node['core'];
}

// Otherwise reduce it to just the core node.
return $node['core'];

}

}
2 changes: 1 addition & 1 deletion src/handlers/UnaryOperator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static function handle(array $node, Context $context) {
throw new InternalException("Handling unary operator without unary node");
}

$variableName = $node['core']['text'];
$variableName = $node['core']['core']['text'];
$value = HandlerFactory
::get($node['core']['name'])
::handle($node['core'], $context);
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/WhileStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Context;

Expand All @@ -15,10 +16,10 @@ class WhileStatement extends \Smuuf\Primi\StrictObject implements IHandler {
public static function handle(array $node, Context $context) {

// Execute the left-hand node and get its return value.
$conditionHandler = HandlerFactory::get($node['left']['name']);
$condHandler = HandlerFactory::get($node['left']['name']);
$blockHandler = HandlerFactory::get($node['right']['name']);

while ($conditionHandler::handle($node['left'], $context)->getInternalValue()) {
while (Common::isTruthy($condHandler::handle($node['left'], $context))) {
$blockHandler::handle($node['right'], $context);
}

Expand Down
Loading

0 comments on commit 959e548

Please sign in to comment.