Skip to content

Commit

Permalink
Features: Conditional expression and try...on error block.
Browse files Browse the repository at this point in the history
- Feature (experimental syntax?): "X if (bool) else Y" conditional expression.
  - Usage should be simpler than writing a full, potentially multilined IF statement.
    ```
    if (bool) {
      result = X;
    } else {
      result = Y;
    }
    ```
    versus the new `result = X if (bool) else Y`.
- Feature (experimental): "try ... on error" construct.
  - It is now possible to catch errors using new "try { .... } on error { ... }" construct.
  - This was handy for writing language tests that are expected to fail.
    - I'm unsure of any other advantages for end-users given the potential scope of Primi. We will see...
  - Handler class: TryStatement.
- Fixed grammar bug:
  - It was not possible to place //comments inside array definition that spans multiple lines. That's possible now.
- Fixed bug in HandlerFactory:
  - $strict flag being true was silently ignored when a handler was missing (the factory returned false) in any previous non-strict calls. This is fixed now.
  • Loading branch information
smuuf committed Mar 2, 2020
1 parent 7a5287c commit e9f401b
Show file tree
Hide file tree
Showing 11 changed files with 1,042 additions and 814 deletions.
15 changes: 15 additions & 0 deletions example/try_error.primi
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// try..on error block catches any errors.
//

was_error = false
executed_after_error = false
try {
// Division by zero, bruh!
1 / 0
executed_after_error = true
} on error {
was_error = true
}
assert(was_error, 'Raised error was caught')
assert(!executed_after_error, 'Code after error was not executed')
2 changes: 1 addition & 1 deletion src/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public function getVariable(string $name): ?Value {
return self::$globals[$name];
}

// This should be slightly faster than throwsin exceptions for undefined
// This should be slightly faster than throwing exceptions for undefined
// variables.
return null;

Expand Down
25 changes: 12 additions & 13 deletions src/factories/HandlerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ class HandlerFactory extends \Smuuf\Primi\StrictObject {

public static function get(string $name, ?bool $strict = true) {

// Using caching should be faster than repeatedly building strings and checking classes and stuff.
if (isset(self::$cache[$name])) {
return self::$cache[$name];
// Using caching is faster than repeatedly building strings and checking
// classes and stuff.
$class = self::$cache[$name] ?? (
class_exists($class = __NAMESPACE__ . "\\Handlers\\$name")
? $class
: false
);

if ($class === false && $strict) {
throw new \LogicException("Handler '$name' not found.");
}

$className = __NAMESPACE__ . "\\Handlers\\$name";
if (!class_exists($className)) {
if ($strict) {
throw new \LogicException("Handler '$className' not found.");
}
$className = false;
}

self::$cache[$name] = $className;
return $className;
self::$cache[$name] = $class;
return $class;

}

Expand Down
46 changes: 46 additions & 0 deletions src/handlers/CondExpr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Context;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Helpers\Common;
use \Smuuf\Primi\Helpers\SimpleHandler;
use \Smuuf\Primi\InternalUndefinedTruthnessException;

class CondExpr extends SimpleHandler {

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

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

try {

// If the result of the left hand equals to truthy value,
// execute the code branch stored in the right-hand node.
if (Common::isTruthy($return)) {
$trueHandler = HandlerFactory::get($node['true']['name']);
return $trueHandler::handle($node['true'], $context);
} else {
$falseHandler = HandlerFactory::get($node['false']['name']);
return $falseHandler::handle($node['false'], $context);
}

} catch (InternalUndefinedTruthnessException $e) {
throw new ErrorException($e->getMessage(), $node);
}

}

public static function reduce(array &$node): void {

if (!isset($node['cond'])) {
$node = $node['true'];
}

}

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

namespace Smuuf\Primi\Handlers;

use \Smuuf\Primi\Context;
use \Smuuf\Primi\ErrorException;
use \Smuuf\Primi\HandlerFactory;
use \Smuuf\Primi\Helpers\SimpleHandler;

class TryStatement extends SimpleHandler {

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

try {

// Execute the main code.
$mainHandler = HandlerFactory::get($node['main']['name']);
return $mainHandler::handle($node['main'], $context);

} catch (ErrorException $e) {

// Execute the onerror block if any error occured with the main
// code.
$errorHandler = HandlerFactory::get($node['onerror']['name']);
return $errorHandler::handle($node['onerror'], $context);

}

}

}
Loading

0 comments on commit e9f401b

Please sign in to comment.